Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 16 additions & 78 deletions apps/dav/lib/Connector/Sabre/QuotaPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,10 @@
*
*/
namespace OCA\DAV\Connector\Sabre;
use OCA\DAV\Files\FilesHome;
use OCA\DAV\Upload\FutureFile;
use OCA\DAV\Upload\UploadFolder;
use OCP\Files\FileInfo;
use OCP\Files\StorageNotAvailableException;
use Sabre\DAV\Exception\InsufficientStorage;
use Sabre\DAV\Exception\ServiceUnavailable;
use Sabre\DAV\INode;
use Sabre\HTTP\URLUtil;

/**
Expand All @@ -44,7 +40,9 @@
*/
class QuotaPlugin extends \Sabre\DAV\ServerPlugin {

/** @var \OC\Files\View */
/**
* @var \OC\Files\View
*/
private $view;

/**
Expand Down Expand Up @@ -76,86 +74,26 @@ public function initialize(\Sabre\DAV\Server $server) {

$this->server = $server;

$server->on('beforeWriteContent', [$this, 'beforeWriteContent'], 10);
$server->on('beforeCreateFile', [$this, 'beforeCreateFile'], 10);
$server->on('beforeMove', [$this, 'beforeMove'], 10);
}

/**
* Check quota before creating file
*
* @param string $uri target file URI
* @param resource $data data
* @param INode $parent Sabre Node
* @param bool $modified modified
*/
public function beforeCreateFile($uri, $data, INode $parent, $modified) {
if (!$parent instanceof Node) {
return;
}

return $this->checkQuota($parent->getPath() . '/' . basename($uri));
}

/**
* Check quota before writing content
*
* @param string $uri target file URI
* @param INode $node Sabre Node
* @param resource $data data
* @param bool $modified modified
*/
public function beforeWriteContent($uri, INode $node, $data, $modified) {
if (!$node instanceof Node) {
return;
}

return $this->checkQuota($node->getPath());
$server->on('beforeWriteContent', array($this, 'checkQuota'), 10);
$server->on('beforeCreateFile', array($this, 'checkQuota'), 10);
}

/**
* Check if we're moving a Futurefile in which case we need to check
* the quota on the target destination.
*
* @param string $source source path
* @param string $destination destination path
*/
public function beforeMove($source, $destination) {
$sourceNode = $this->server->tree->getNodeForPath($source);
if (!$sourceNode instanceof FutureFile) {
return;
}

// get target node for proper path conversion
if ($this->server->tree->nodeExists($destination)) {
$destinationNode = $this->server->tree->getNodeForPath($destination);
$path = $destinationNode->getPath();
} else {
$parentNode = $this->server->tree->getNodeForPath(dirname($destination));
$path = $parentNode->getPath();
}

return $this->checkQuota($path, $sourceNode->getSize());
}


/**
* This method is called before any HTTP method and validates there is enough free space to store the file
*
* @param string $path relative to the users home
* @param int $length
* @param string $uri
* @throws InsufficientStorage
* @return bool
*/
public function checkQuota($path, $length = null) {
if ($length === null) {
$length = $this->getLength();
}

public function checkQuota($uri) {
$length = $this->getLength();
if ($length) {
list($parentPath, $newName) = \Sabre\Uri\split($path);
if(is_null($parentPath)) {
$parentPath = '';
if (substr($uri, 0, 1) !== '/') {
$uri = '/' . $uri;
}
list($parentUri, $newName) = \Sabre\Uri\split($uri);
if(is_null($parentUri)) {
$parentUri = '';
}
$req = $this->server->httpRequest;
if ($req->getHeader('OC-Chunked')) {
Expand All @@ -165,9 +103,9 @@ public function checkQuota($path, $length = null) {
// 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
$path = rtrim($parentPath, '/') . '/' . $info['name'];
$uri = rtrim($parentUri, '/') . '/' . $info['name'];
}
$freeSpace = $this->getFreeSpace($path);
$freeSpace = $this->getFreeSpace($uri);
if ($freeSpace !== FileInfo::SPACE_UNKNOWN && $freeSpace !== FileInfo::SPACE_UNLIMITED && $length > $freeSpace) {
if (isset($chunkHandler)) {
$chunkHandler->cleanup();
Expand Down
2 changes: 1 addition & 1 deletion apps/dav/lib/Connector/Sabre/ServerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public function createServer($baseUri,
!$this->config->getSystemValue('debug', false)
)
);
$server->addPlugin(new \OCA\DAV\Connector\Sabre\QuotaPlugin($view, true));
$server->addPlugin(new \OCA\DAV\Connector\Sabre\QuotaPlugin($view));

if($this->userSession->isLoggedIn()) {
$server->addPlugin(new \OCA\DAV\Connector\Sabre\TagsPlugin($objectTree, $this->tagManager));
Expand Down
2 changes: 1 addition & 1 deletion apps/dav/lib/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public function __construct(IRequest $request, $baseUri) {
);
if ($view !== null) {
$this->server->addPlugin(
new QuotaPlugin($view, false));
new QuotaPlugin($view));
}
$this->server->addPlugin(
new TagsPlugin(
Expand Down
11 changes: 3 additions & 8 deletions apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,7 @@
*
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OC\Files\View;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\QuotaPlugin;
use OCA\DAV\Files\FilesHome;
use OCP\Files\FileInfo;
use Sabre\DAV\Exception\InsufficientStorage;
use Sabre\DAV\Tree;
use Test\TestCase;

/**
Expand All @@ -50,7 +44,7 @@ class QuotaPluginTest extends TestCase {
private function init($quota, $checkedPath = '') {
$view = $this->buildFileViewMock($quota, $checkedPath);
$this->server = new \Sabre\DAV\Server();
$this->plugin = $this->getMockBuilder(QuotaPlugin::class)
$this->plugin = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\QuotaPlugin')
->setConstructorArgs([$view])
->setMethods(['getFileChunking'])
->getMock();
Expand Down Expand Up @@ -230,7 +224,7 @@ public function testCheckQuotaChunkedFail($quota, $chunkTotalSize, $headers) {

private function buildFileViewMock($quota, $checkedPath) {
// mock filesysten
$view = $this->getMockBuilder(View::class)
$view = $this->getMockBuilder('\OC\Files\View')
->setMethods(['free_space'])
->disableOriginalConstructor()
->getMock();
Expand All @@ -241,4 +235,5 @@ private function buildFileViewMock($quota, $checkedPath) {

return $view;
}

}