Skip to content
Merged
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
45 changes: 13 additions & 32 deletions apps/dav/lib/Connector/Sabre/ServerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,39 +28,19 @@
use Sabre\DAV\Auth\Plugin;

class ServerFactory {
private IConfig $config;
private LoggerInterface $logger;
private IDBConnection $databaseConnection;
private IUserSession $userSession;
private IMountManager $mountManager;
private ITagManager $tagManager;
private IRequest $request;
private IPreview $previewManager;
private IEventDispatcher $eventDispatcher;
private IL10N $l10n;

public function __construct(
IConfig $config,
LoggerInterface $logger,
IDBConnection $databaseConnection,
IUserSession $userSession,
IMountManager $mountManager,
ITagManager $tagManager,
IRequest $request,
IPreview $previewManager,
IEventDispatcher $eventDispatcher,
IL10N $l10n,
private IConfig $config,
private LoggerInterface $logger,
private IDBConnection $databaseConnection,
private IUserSession $userSession,
private IMountManager $mountManager,
private ITagManager $tagManager,
private IRequest $request,
private IPreview $previewManager,
private IEventDispatcher $eventDispatcher,
private IL10N $l10n,
) {
$this->config = $config;
$this->logger = $logger;
$this->databaseConnection = $databaseConnection;
$this->userSession = $userSession;
$this->mountManager = $mountManager;
$this->tagManager = $tagManager;
$this->request = $request;
$this->previewManager = $previewManager;
$this->eventDispatcher = $eventDispatcher;
$this->l10n = $l10n;
}

/**
Expand All @@ -80,7 +60,7 @@ public function createServer(string $baseUri,
// Load plugins
$server->addPlugin(new \OCA\DAV\Connector\Sabre\MaintenancePlugin($this->config, $this->l10n));
$server->addPlugin(new BlockLegacyClientPlugin(
\OCP\Server::get(IConfig::class),
$this->config,
\OCP\Server::get(ThemingDefaults::class),
));
$server->addPlugin(new \OCA\DAV\Connector\Sabre\AnonymousOptionsPlugin());
Expand All @@ -90,11 +70,12 @@ public function createServer(string $baseUri,
$server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $this->logger));
$server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin());

$server->addPlugin(new RequestIdHeaderPlugin(\OC::$server->get(IRequest::class)));
$server->addPlugin(new RequestIdHeaderPlugin($this->request));

$server->addPlugin(new ZipFolderPlugin(
$objectTree,
$this->logger,
$this->eventDispatcher,
));

// Some WebDAV clients do require Class 2 WebDAV support (locking), since
Expand Down
28 changes: 24 additions & 4 deletions apps/dav/lib/Connector/Sabre/ZipFolderPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
namespace OCA\DAV\Connector\Sabre;

use OC\Streamer;
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Events\BeforeZipCreatedEvent;
use OCP\Files\File as NcFile;
use OCP\Files\Folder as NcFolder;
use OCP\Files\Node as NcNode;
Expand Down Expand Up @@ -37,6 +40,7 @@ class ZipFolderPlugin extends ServerPlugin {
public function __construct(
private Tree $tree,
private LoggerInterface $logger,
private IEventDispatcher $eventDispatcher,
) {
}

Expand Down Expand Up @@ -114,17 +118,33 @@ public function handleDownload(Request $request, Response $response): ?bool {
if ($filesParam !== '') {
$files = json_decode($filesParam);
if (!is_array($files)) {
if (!is_string($files)) {
$files = [$files];
}

foreach ($files as $file) {
if (!is_string($file)) {
// we log this as this means either we - or an app - have a bug somewhere or a user is trying invalid things
$this->logger->notice('Invalid files filter parameter for ZipFolderPlugin', ['filter' => $filesParam]);
// no valid parameter so continue with Sabre behavior
$this->logger->debug('Invalid files filter parameter for ZipFolderPlugin', ['filter' => $filesParam]);
return null;
}

$files = [$files];
}
}

$folder = $node->getNode();
$event = new BeforeZipCreatedEvent($folder, $files);

Check notice

Code scanning / Psalm

ArgumentTypeCoercion

Argument 2 of OCP\Files\Events\BeforeZipCreatedEvent::__construct expects list<string>, but parent type array<array-key, mixed|string> provided
$this->eventDispatcher->dispatchTyped($event);
if ((!$event->isSuccessful()) || $event->getErrorMessage() !== null) {
$errorMessage = $event->getErrorMessage();
if ($errorMessage === null) {
// Not allowed to download but also no explaining error
// so we abort the ZIP creation and fall back to Sabre default behavior.
return null;
}
// Downloading was denied by an app
throw new Forbidden($errorMessage);
}

$content = empty($files) ? $folder->getDirectoryListing() : [];
foreach ($files as $path) {
$child = $node->getChild($path);
Expand Down
15 changes: 8 additions & 7 deletions apps/dav/lib/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ public function __construct(IRequest $request, string $baseUri) {

$this->request = $request;
$this->baseUri = $baseUri;
$logger = \OC::$server->get(LoggerInterface::class);
/** @var IEventDispatcher $dispatcher */
$dispatcher = \OC::$server->get(IEventDispatcher::class);

$logger = \OCP\Server::get(LoggerInterface::class);
$eventDispatcher = \OCP\Server::get(IEventDispatcher::class);

$root = new RootCollection();
$this->server = new \OCA\DAV\Connector\Sabre\Server(new CachingTree($root));
Expand Down Expand Up @@ -123,10 +123,10 @@ public function __construct(IRequest $request, string $baseUri) {

// allow setup of additional auth backends
$event = new SabrePluginEvent($this->server);
$dispatcher->dispatch('OCA\DAV\Connector\Sabre::authInit', $event);
$eventDispatcher->dispatch('OCA\DAV\Connector\Sabre::authInit', $event);

Check notice

Code scanning / Psalm

DeprecatedMethod

The method OCP\EventDispatcher\IEventDispatcher::dispatch has been marked as deprecated

$newAuthEvent = new SabrePluginAuthInitEvent($this->server);
$dispatcher->dispatchTyped($newAuthEvent);
$eventDispatcher->dispatchTyped($newAuthEvent);

$bearerAuthBackend = new BearerAuth(
\OC::$server->getUserSession(),
Expand Down Expand Up @@ -213,12 +213,13 @@ public function __construct(IRequest $request, string $baseUri) {
$this->server->addPlugin(new ZipFolderPlugin(
$this->server->tree,
$logger,
$eventDispatcher,
));

// allow setup of additional plugins
$dispatcher->dispatch('OCA\DAV\Connector\Sabre::addPlugin', $event);
$eventDispatcher->dispatch('OCA\DAV\Connector\Sabre::addPlugin', $event);

Check notice

Code scanning / Psalm

DeprecatedMethod

The method OCP\EventDispatcher\IEventDispatcher::dispatch has been marked as deprecated
$typedEvent = new SabrePluginAddEvent($this->server);
$dispatcher->dispatchTyped($typedEvent);
$eventDispatcher->dispatchTyped($typedEvent);

// Some WebDAV clients do require Class 2 WebDAV support (locking), since
// we do not provide locking we emulate it using a fake locking plugin.
Expand Down
30 changes: 26 additions & 4 deletions lib/public/Files/Events/BeforeZipCreatedEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,45 @@
namespace OCP\Files\Events;

use OCP\EventDispatcher\Event;
use OCP\Files\Folder;

/**
* This event is triggered before a archive is created when a user requested
* downloading a folder or multiple files.
*
* By setting `successful` to false the tar creation can be aborted and the download denied.
*
* @since 25.0.0
*/
class BeforeZipCreatedEvent extends Event {
private string $directory;
private array $files;
private bool $successful = true;
private ?string $errorMessage = null;
private ?Folder $folder = null;

/**
* @param list<string> $files
* @since 25.0.0
* @since 31.0.0 support `OCP\Files\Folder` as `$directory` parameter - passing a string is deprecated now
*/
public function __construct(string $directory, array $files) {
public function __construct(
string|Folder $directory,
private array $files,
) {
parent::__construct();
$this->directory = $directory;
$this->files = $files;
if ($directory instanceof Folder) {
$this->directory = $directory->getPath();
$this->folder = $directory;
} else {
$this->directory = $directory;
}
}

/**
* @since 31.0.0
*/
public function getFolder(): ?Folder {
return $this->folder;
}

/**
Expand Down