add event for when a direct download is triggered

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2021-02-10 13:53:05 +01:00
parent 361f160d0d
commit f824f273b6
No known key found for this signature in database
GPG Key ID: 42B69D8A64526EFB
9 changed files with 97 additions and 14 deletions

View File

@ -25,6 +25,8 @@ declare(strict_types=1);
* *
*/ */
use \OCA\DAV\Direct\ServerFactory;
// no php execution timeout for webdav // no php execution timeout for webdav
if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
@set_time_limit(0); @set_time_limit(0);
@ -36,7 +38,8 @@ ignore_user_abort(true);
$requestUri = \OC::$server->getRequest()->getRequestUri(); $requestUri = \OC::$server->getRequest()->getRequestUri();
$serverFactory = new \OCA\DAV\Direct\ServerFactory(\OC::$server->getConfig(), \OC::$server->getL10N('dav')); /** @var ServerFactory $serverFactory */
$serverFactory = \OC::$server->query(ServerFactory::class);
$server = $serverFactory->createServer( $server = $serverFactory->createServer(
$baseuri, $baseuri,
$requestUri, $requestUri,

View File

@ -176,6 +176,7 @@ return array(
'OCA\\DAV\\Events\\AddressBookDeletedEvent' => $baseDir . '/../lib/Events/AddressBookDeletedEvent.php', 'OCA\\DAV\\Events\\AddressBookDeletedEvent' => $baseDir . '/../lib/Events/AddressBookDeletedEvent.php',
'OCA\\DAV\\Events\\AddressBookShareUpdatedEvent' => $baseDir . '/../lib/Events/AddressBookShareUpdatedEvent.php', 'OCA\\DAV\\Events\\AddressBookShareUpdatedEvent' => $baseDir . '/../lib/Events/AddressBookShareUpdatedEvent.php',
'OCA\\DAV\\Events\\AddressBookUpdatedEvent' => $baseDir . '/../lib/Events/AddressBookUpdatedEvent.php', 'OCA\\DAV\\Events\\AddressBookUpdatedEvent' => $baseDir . '/../lib/Events/AddressBookUpdatedEvent.php',
'OCA\\DAV\\Events\\BeforeFileDirectDownloadedEvent' => $baseDir . '/../lib/Events/BeforeFileDirectDownloadedEvent.php',
'OCA\\DAV\\Events\\CachedCalendarObjectCreatedEvent' => $baseDir . '/../lib/Events/CachedCalendarObjectCreatedEvent.php', 'OCA\\DAV\\Events\\CachedCalendarObjectCreatedEvent' => $baseDir . '/../lib/Events/CachedCalendarObjectCreatedEvent.php',
'OCA\\DAV\\Events\\CachedCalendarObjectDeletedEvent' => $baseDir . '/../lib/Events/CachedCalendarObjectDeletedEvent.php', 'OCA\\DAV\\Events\\CachedCalendarObjectDeletedEvent' => $baseDir . '/../lib/Events/CachedCalendarObjectDeletedEvent.php',
'OCA\\DAV\\Events\\CachedCalendarObjectUpdatedEvent' => $baseDir . '/../lib/Events/CachedCalendarObjectUpdatedEvent.php', 'OCA\\DAV\\Events\\CachedCalendarObjectUpdatedEvent' => $baseDir . '/../lib/Events/CachedCalendarObjectUpdatedEvent.php',

View File

@ -191,6 +191,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Events\\AddressBookDeletedEvent' => __DIR__ . '/..' . '/../lib/Events/AddressBookDeletedEvent.php', 'OCA\\DAV\\Events\\AddressBookDeletedEvent' => __DIR__ . '/..' . '/../lib/Events/AddressBookDeletedEvent.php',
'OCA\\DAV\\Events\\AddressBookShareUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/AddressBookShareUpdatedEvent.php', 'OCA\\DAV\\Events\\AddressBookShareUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/AddressBookShareUpdatedEvent.php',
'OCA\\DAV\\Events\\AddressBookUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/AddressBookUpdatedEvent.php', 'OCA\\DAV\\Events\\AddressBookUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/AddressBookUpdatedEvent.php',
'OCA\\DAV\\Events\\BeforeFileDirectDownloadedEvent' => __DIR__ . '/..' . '/../lib/Events/BeforeFileDirectDownloadedEvent.php',
'OCA\\DAV\\Events\\CachedCalendarObjectCreatedEvent' => __DIR__ . '/..' . '/../lib/Events/CachedCalendarObjectCreatedEvent.php', 'OCA\\DAV\\Events\\CachedCalendarObjectCreatedEvent' => __DIR__ . '/..' . '/../lib/Events/CachedCalendarObjectCreatedEvent.php',
'OCA\\DAV\\Events\\CachedCalendarObjectDeletedEvent' => __DIR__ . '/..' . '/../lib/Events/CachedCalendarObjectDeletedEvent.php', 'OCA\\DAV\\Events\\CachedCalendarObjectDeletedEvent' => __DIR__ . '/..' . '/../lib/Events/CachedCalendarObjectDeletedEvent.php',
'OCA\\DAV\\Events\\CachedCalendarObjectUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/CachedCalendarObjectUpdatedEvent.php', 'OCA\\DAV\\Events\\CachedCalendarObjectUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/CachedCalendarObjectUpdatedEvent.php',

View File

@ -27,6 +27,8 @@ declare(strict_types=1);
namespace OCA\DAV\Direct; namespace OCA\DAV\Direct;
use OCA\DAV\Db\Direct; use OCA\DAV\Db\Direct;
use OCA\DAV\Events\BeforeFileDirectDownloadedEvent;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\File; use OCP\Files\File;
use OCP\Files\IRootFolder; use OCP\Files\IRootFolder;
use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\Forbidden;
@ -43,9 +45,12 @@ class DirectFile implements IFile {
/** @var File */ /** @var File */
private $file; private $file;
public function __construct(Direct $direct, IRootFolder $rootFolder) { private $eventDispatcher;
public function __construct(Direct $direct, IRootFolder $rootFolder, IEventDispatcher $eventDispatcher) {
$this->direct = $direct; $this->direct = $direct;
$this->rootFolder = $rootFolder; $this->rootFolder = $rootFolder;
$this->eventDispatcher = $eventDispatcher;
} }
public function put($data) { public function put($data) {
@ -55,6 +60,8 @@ class DirectFile implements IFile {
public function get() { public function get() {
$this->getFile(); $this->getFile();
$this->eventDispatcher->dispatchTyped(new BeforeFileDirectDownloadedEvent($this->file));
return $this->file->fopen('rb'); return $this->file->fopen('rb');
} }

View File

@ -30,6 +30,7 @@ use OC\Security\Bruteforce\Throttler;
use OCA\DAV\Db\DirectMapper; use OCA\DAV\Db\DirectMapper;
use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory; use OCP\AppFramework\Utility\ITimeFactory;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\IRootFolder; use OCP\Files\IRootFolder;
use OCP\IRequest; use OCP\IRequest;
use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\Forbidden;
@ -53,17 +54,22 @@ class DirectHome implements ICollection {
/** @var IRequest */ /** @var IRequest */
private $request; private $request;
private $eventDispatcher;
public function __construct(IRootFolder $rootFolder, public function __construct(
DirectMapper $mapper, IRootFolder $rootFolder,
ITimeFactory $timeFactory, DirectMapper $mapper,
Throttler $throttler, ITimeFactory $timeFactory,
IRequest $request) { Throttler $throttler,
IRequest $request,
IEventDispatcher $eventDispatcher
) {
$this->rootFolder = $rootFolder; $this->rootFolder = $rootFolder;
$this->mapper = $mapper; $this->mapper = $mapper;
$this->timeFactory = $timeFactory; $this->timeFactory = $timeFactory;
$this->throttler = $throttler; $this->throttler = $throttler;
$this->request = $request; $this->request = $request;
$this->eventDispatcher = $eventDispatcher;
} }
public function createFile($name, $data = null) { public function createFile($name, $data = null) {
@ -83,7 +89,7 @@ class DirectHome implements ICollection {
throw new NotFound(); throw new NotFound();
} }
return new DirectFile($direct, $this->rootFolder); return new DirectFile($direct, $this->rootFolder, $this->eventDispatcher);
} catch (DoesNotExistException $e) { } catch (DoesNotExistException $e) {
// Since the token space is so huge only throttle on non exsisting token // Since the token space is so huge only throttle on non exsisting token
$this->throttler->registerAttempt('directlink', $this->request->getRemoteAddress()); $this->throttler->registerAttempt('directlink', $this->request->getRemoteAddress());

View File

@ -28,22 +28,27 @@ declare(strict_types=1);
namespace OCA\DAV\Direct; namespace OCA\DAV\Direct;
use OC\Security\Bruteforce\Throttler; use OC\Security\Bruteforce\Throttler;
use OCA\DAV\Connector\Sabre\MaintenancePlugin;
use OCA\DAV\Db\DirectMapper; use OCA\DAV\Db\DirectMapper;
use OCP\AppFramework\Utility\ITimeFactory; use OCP\AppFramework\Utility\ITimeFactory;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\IRootFolder; use OCP\Files\IRootFolder;
use OCP\IConfig; use OCP\IConfig;
use OCP\IL10N; use OCP\IL10N;
use OCP\IRequest; use OCP\IRequest;
use OCP\L10N\IFactory;
class ServerFactory { class ServerFactory {
/** @var IConfig */ /** @var IConfig */
private $config; private $config;
/** @var IL10N */ /** @var IL10N */
private $l10n; private $l10n;
private $eventDispatcher;
public function __construct(IConfig $config, IL10N $l10n) { public function __construct(IConfig $config, IFactory $l10nFactory, IEventDispatcher $eventDispatcher) {
$this->config = $config; $this->config = $config;
$this->l10n = $l10n; $this->l10n = $l10nFactory->get('dav');
$this->eventDispatcher = $eventDispatcher;
} }
public function createServer(string $baseURI, public function createServer(string $baseURI,
@ -53,13 +58,13 @@ class ServerFactory {
ITimeFactory $timeFactory, ITimeFactory $timeFactory,
Throttler $throttler, Throttler $throttler,
IRequest $request): Server { IRequest $request): Server {
$home = new DirectHome($rootFolder, $mapper, $timeFactory, $throttler, $request); $home = new DirectHome($rootFolder, $mapper, $timeFactory, $throttler, $request, $this->eventDispatcher);
$server = new Server($home); $server = new Server($home);
$server->httpRequest->setUrl($requestURI); $server->httpRequest->setUrl($requestURI);
$server->setBaseUri($baseURI); $server->setBaseUri($baseURI);
$server->addPlugin(new \OCA\DAV\Connector\Sabre\MaintenancePlugin($this->config, $this->l10n)); $server->addPlugin(new MaintenancePlugin($this->config, $this->l10n));
return $server; return $server;
} }

View File

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\DAV\Events;
use OCP\EventDispatcher\Event;
use OCP\Files\File;
/**
* @since 22.0.0
*/
class BeforeFileDirectDownloadedEvent extends Event {
private $file;
public function __construct(File $file) {
parent::__construct();
$this->file = $file;
}
/**
* @return File
* @since 22.0.0
*/
public function getFile(): File {
return $this->file;
}
}

View File

@ -29,6 +29,7 @@ namespace OCA\DAV\Tests\Unit\Direct;
use OCA\DAV\Db\Direct; use OCA\DAV\Db\Direct;
use OCA\DAV\Direct\DirectFile; use OCA\DAV\Direct\DirectFile;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\File; use OCP\Files\File;
use OCP\Files\Folder; use OCP\Files\Folder;
use OCP\Files\IRootFolder; use OCP\Files\IRootFolder;
@ -52,6 +53,9 @@ class DirectFileTest extends TestCase {
/** @var DirectFile */ /** @var DirectFile */
private $directFile; private $directFile;
/** @var IEventDispatcher */
private $eventDispatcher;
protected function setUp(): void { protected function setUp(): void {
parent::setUp(); parent::setUp();
@ -73,7 +77,9 @@ class DirectFileTest extends TestCase {
->with(42) ->with(42)
->willReturn([$this->file]); ->willReturn([$this->file]);
$this->directFile = new DirectFile($this->direct, $this->rootFolder); $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->directFile = new DirectFile($this->direct, $this->rootFolder, $this->eventDispatcher);
} }
public function testPut() { public function testPut() {

View File

@ -34,6 +34,7 @@ use OCA\DAV\Direct\DirectFile;
use OCA\DAV\Direct\DirectHome; use OCA\DAV\Direct\DirectHome;
use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory; use OCP\AppFramework\Utility\ITimeFactory;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\IRootFolder; use OCP\Files\IRootFolder;
use OCP\IRequest; use OCP\IRequest;
use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\Forbidden;
@ -61,6 +62,9 @@ class DirectHomeTest extends TestCase {
/** @var DirectHome */ /** @var DirectHome */
private $directHome; private $directHome;
/** @var IEventDispatcher */
private $eventDispatcher;
protected function setUp(): void { protected function setUp(): void {
parent::setUp(); parent::setUp();
@ -69,6 +73,7 @@ class DirectHomeTest extends TestCase {
$this->timeFactory = $this->createMock(ITimeFactory::class); $this->timeFactory = $this->createMock(ITimeFactory::class);
$this->throttler = $this->createMock(Throttler::class); $this->throttler = $this->createMock(Throttler::class);
$this->request = $this->createMock(IRequest::class); $this->request = $this->createMock(IRequest::class);
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->timeFactory->method('getTime') $this->timeFactory->method('getTime')
->willReturn(42); ->willReturn(42);
@ -76,12 +81,14 @@ class DirectHomeTest extends TestCase {
$this->request->method('getRemoteAddress') $this->request->method('getRemoteAddress')
->willReturn('1.2.3.4'); ->willReturn('1.2.3.4');
$this->directHome = new DirectHome( $this->directHome = new DirectHome(
$this->rootFolder, $this->rootFolder,
$this->directMapper, $this->directMapper,
$this->timeFactory, $this->timeFactory,
$this->throttler, $this->throttler,
$this->request $this->request,
$this->eventDispatcher
); );
} }