2015-08-07 11:36:14 -04:00
|
|
|
<?php
|
2024-05-27 11:39:07 -04:00
|
|
|
|
2015-08-07 11:36:14 -04:00
|
|
|
/**
|
2024-05-27 11:39:07 -04:00
|
|
|
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
|
|
|
|
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
|
|
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
2015-08-07 11:36:14 -04:00
|
|
|
*/
|
2015-08-30 13:13:01 -04:00
|
|
|
namespace OCA\DAV\Connector\Sabre;
|
2015-08-07 11:36:14 -04:00
|
|
|
|
2024-10-18 06:04:22 -04:00
|
|
|
use OC\Files\View;
|
2025-04-14 09:16:44 -04:00
|
|
|
use OC\KnownUser\KnownUserService;
|
2019-11-21 09:47:11 -05:00
|
|
|
use OCA\DAV\AppInfo\PluginManager;
|
2024-06-04 09:58:39 -04:00
|
|
|
use OCA\DAV\CalDAV\DefaultCalendarValidator;
|
2025-04-14 09:16:44 -04:00
|
|
|
use OCA\DAV\CalDAV\Proxy\ProxyMapper;
|
2024-10-10 06:40:31 -04:00
|
|
|
use OCA\DAV\DAV\CustomPropertiesBackend;
|
2022-05-18 08:54:27 -04:00
|
|
|
use OCA\DAV\DAV\ViewOnlyPlugin;
|
2025-08-13 05:03:40 -04:00
|
|
|
use OCA\DAV\Db\PropertyMapper;
|
2024-10-30 07:25:26 -04:00
|
|
|
use OCA\DAV\Files\BrowserErrorPagePlugin;
|
2025-05-14 09:29:02 -04:00
|
|
|
use OCA\DAV\Files\Sharing\RootCollection;
|
2025-04-14 09:41:13 -04:00
|
|
|
use OCA\DAV\Upload\CleanupService;
|
2024-09-06 08:39:32 -04:00
|
|
|
use OCA\Theming\ThemingDefaults;
|
2025-04-29 10:42:09 -04:00
|
|
|
use OCP\Accounts\IAccountManager;
|
2025-02-03 09:34:01 -05:00
|
|
|
use OCP\App\IAppManager;
|
|
|
|
|
use OCP\Comments\ICommentsManager;
|
2023-07-11 05:50:07 -04:00
|
|
|
use OCP\EventDispatcher\IEventDispatcher;
|
2022-03-09 11:23:59 -05:00
|
|
|
use OCP\Files\Folder;
|
2024-08-27 06:59:06 -04:00
|
|
|
use OCP\Files\IFilenameValidator;
|
2025-04-14 09:41:13 -04:00
|
|
|
use OCP\Files\IRootFolder;
|
2015-08-07 11:36:14 -04:00
|
|
|
use OCP\Files\Mount\IMountManager;
|
|
|
|
|
use OCP\IConfig;
|
2025-08-14 04:01:33 -04:00
|
|
|
use OCP\IDateTimeZone;
|
2015-08-07 11:36:14 -04:00
|
|
|
use OCP\IDBConnection;
|
2025-02-03 09:34:01 -05:00
|
|
|
use OCP\IGroupManager;
|
2020-05-06 12:11:54 -04:00
|
|
|
use OCP\IL10N;
|
2016-07-26 07:15:12 -04:00
|
|
|
use OCP\IPreview;
|
2015-11-13 05:47:32 -05:00
|
|
|
use OCP\IRequest;
|
2015-08-07 11:36:14 -04:00
|
|
|
use OCP\ITagManager;
|
2025-04-14 09:16:44 -04:00
|
|
|
use OCP\IUserManager;
|
2015-08-07 11:36:14 -04:00
|
|
|
use OCP\IUserSession;
|
2019-11-21 09:47:11 -05:00
|
|
|
use OCP\SabrePluginEvent;
|
2025-02-03 09:34:01 -05:00
|
|
|
use OCP\SystemTag\ISystemTagManager;
|
|
|
|
|
use OCP\SystemTag\ISystemTagObjectMapper;
|
2022-03-31 09:34:57 -04:00
|
|
|
use Psr\Log\LoggerInterface;
|
2017-05-18 15:19:39 -04:00
|
|
|
use Sabre\DAV\Auth\Plugin;
|
2025-04-14 09:16:44 -04:00
|
|
|
use Sabre\DAV\SimpleCollection;
|
2015-08-07 11:36:14 -04:00
|
|
|
|
|
|
|
|
class ServerFactory {
|
2015-11-13 05:47:32 -05:00
|
|
|
|
2015-08-07 11:36:14 -04:00
|
|
|
public function __construct(
|
2024-09-28 16:16:42 -04:00
|
|
|
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,
|
2015-08-07 11:36:14 -04:00
|
|
|
) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param callable $viewCallBack callback that should return the view for the dav endpoint
|
|
|
|
|
*/
|
2025-04-14 09:16:44 -04:00
|
|
|
public function createServer(
|
|
|
|
|
bool $isPublicShare,
|
|
|
|
|
string $baseUri,
|
2022-04-12 08:01:13 -04:00
|
|
|
string $requestUri,
|
2017-05-18 15:19:39 -04:00
|
|
|
Plugin $authPlugin,
|
2025-04-14 09:16:44 -04:00
|
|
|
callable $viewCallBack,
|
|
|
|
|
): Server {
|
2025-07-29 11:07:08 -04:00
|
|
|
$debugEnabled = $this->config->getSystemValue('debug', false);
|
2015-08-07 11:36:14 -04:00
|
|
|
// Fire up server
|
2025-04-14 09:16:44 -04:00
|
|
|
if ($isPublicShare) {
|
|
|
|
|
$rootCollection = new SimpleCollection('root');
|
|
|
|
|
$tree = new CachingTree($rootCollection);
|
|
|
|
|
} else {
|
|
|
|
|
$rootCollection = null;
|
|
|
|
|
$tree = new ObjectTree();
|
|
|
|
|
}
|
|
|
|
|
$server = new Server($tree);
|
2015-08-07 11:36:14 -04:00
|
|
|
// Set URL explicitly due to reverse-proxy situations
|
|
|
|
|
$server->httpRequest->setUrl($requestUri);
|
|
|
|
|
$server->setBaseUri($baseUri);
|
|
|
|
|
|
|
|
|
|
// Load plugins
|
2024-10-10 06:40:31 -04:00
|
|
|
$server->addPlugin(new MaintenancePlugin($this->config, $this->l10n));
|
2024-09-06 08:39:32 -04:00
|
|
|
$server->addPlugin(new BlockLegacyClientPlugin(
|
2024-09-28 16:16:42 -04:00
|
|
|
$this->config,
|
2024-09-06 08:39:32 -04:00
|
|
|
\OCP\Server::get(ThemingDefaults::class),
|
|
|
|
|
));
|
2024-10-10 06:40:31 -04:00
|
|
|
$server->addPlugin(new AnonymousOptionsPlugin());
|
2017-05-18 15:19:39 -04:00
|
|
|
$server->addPlugin($authPlugin);
|
2025-07-29 11:07:08 -04:00
|
|
|
if ($debugEnabled) {
|
|
|
|
|
$server->debugEnabled = $debugEnabled;
|
|
|
|
|
$server->addPlugin(new PropFindMonitorPlugin());
|
|
|
|
|
}
|
2025-08-05 07:12:00 -04:00
|
|
|
|
|
|
|
|
$server->addPlugin(new PropFindPreloadNotifyPlugin());
|
2015-08-07 11:36:14 -04:00
|
|
|
// FIXME: The following line is a workaround for legacy components relying on being able to send a GET to /
|
2024-10-10 06:40:31 -04:00
|
|
|
$server->addPlugin(new DummyGetResponsePlugin());
|
|
|
|
|
$server->addPlugin(new ExceptionLoggerPlugin('webdav', $this->logger));
|
|
|
|
|
$server->addPlugin(new LockPlugin());
|
2022-01-31 09:01:58 -05:00
|
|
|
|
2024-09-28 16:16:42 -04:00
|
|
|
$server->addPlugin(new RequestIdHeaderPlugin($this->request));
|
2022-01-31 09:01:58 -05:00
|
|
|
|
2024-09-16 06:51:18 -04:00
|
|
|
$server->addPlugin(new ZipFolderPlugin(
|
2025-04-14 09:16:44 -04:00
|
|
|
$tree,
|
2024-09-16 06:51:18 -04:00
|
|
|
$this->logger,
|
2024-09-28 16:16:42 -04:00
|
|
|
$this->eventDispatcher,
|
2025-08-14 04:01:33 -04:00
|
|
|
\OCP\Server::get(IDateTimeZone::class),
|
2024-09-16 06:51:18 -04:00
|
|
|
));
|
|
|
|
|
|
2016-01-26 11:31:01 -05:00
|
|
|
// Some WebDAV clients do require Class 2 WebDAV support (locking), since
|
|
|
|
|
// we do not provide locking we emulate it using a fake locking plugin.
|
|
|
|
|
if ($this->request->isUserAgent([
|
2020-04-09 03:22:29 -04:00
|
|
|
'/WebDAVFS/',
|
|
|
|
|
'/OneNote/',
|
|
|
|
|
'/Microsoft-WebDAV-MiniRedir/',
|
2016-01-26 11:31:01 -05:00
|
|
|
])) {
|
2024-10-10 06:40:31 -04:00
|
|
|
$server->addPlugin(new FakeLockerPlugin());
|
2015-11-13 05:47:32 -05:00
|
|
|
}
|
2015-08-07 11:36:14 -04:00
|
|
|
|
2024-10-30 07:25:26 -04:00
|
|
|
if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) {
|
|
|
|
|
$server->addPlugin(new BrowserErrorPagePlugin());
|
|
|
|
|
}
|
2016-03-24 09:29:55 -04:00
|
|
|
|
2015-08-07 11:36:14 -04:00
|
|
|
// wait with registering these until auth is handled and the filesystem is setup
|
2025-07-29 11:07:08 -04:00
|
|
|
$server->on('beforeMethod:*', function () use ($server, $tree,
|
|
|
|
|
$viewCallBack, $isPublicShare, $rootCollection, $debugEnabled): void {
|
2015-11-10 04:07:46 -05:00
|
|
|
// ensure the skeleton is copied
|
2016-02-03 15:55:04 -05:00
|
|
|
$userFolder = \OC::$server->getUserFolder();
|
2019-11-21 09:47:11 -05:00
|
|
|
|
2024-10-18 06:04:22 -04:00
|
|
|
/** @var View $view */
|
2015-12-03 09:29:42 -05:00
|
|
|
$view = $viewCallBack($server);
|
2016-08-25 09:48:53 -04:00
|
|
|
if ($userFolder instanceof Folder && $userFolder->getPath() === $view->getRoot()) {
|
|
|
|
|
$rootInfo = $userFolder;
|
|
|
|
|
} else {
|
|
|
|
|
$rootInfo = $view->getFileInfo('');
|
|
|
|
|
}
|
2015-08-07 11:36:14 -04:00
|
|
|
|
2017-04-12 00:16:27 -04:00
|
|
|
// Create Nextcloud Dir
|
2015-08-11 08:46:46 -04:00
|
|
|
if ($rootInfo->getType() === 'dir') {
|
2025-04-14 09:16:44 -04:00
|
|
|
$root = new Directory($view, $rootInfo, $tree);
|
2015-08-11 08:46:46 -04:00
|
|
|
} else {
|
2024-10-10 06:40:31 -04:00
|
|
|
$root = new File($view, $rootInfo);
|
2015-08-11 08:46:46 -04:00
|
|
|
}
|
2025-04-14 09:16:44 -04:00
|
|
|
|
|
|
|
|
if ($isPublicShare) {
|
|
|
|
|
$userPrincipalBackend = new Principal(
|
|
|
|
|
\OCP\Server::get(IUserManager::class),
|
|
|
|
|
\OCP\Server::get(IGroupManager::class),
|
|
|
|
|
\OCP\Server::get(IAccountManager::class),
|
|
|
|
|
\OCP\Server::get(\OCP\Share\IManager::class),
|
|
|
|
|
\OCP\Server::get(IUserSession::class),
|
|
|
|
|
\OCP\Server::get(IAppManager::class),
|
|
|
|
|
\OCP\Server::get(ProxyMapper::class),
|
|
|
|
|
\OCP\Server::get(KnownUserService::class),
|
|
|
|
|
\OCP\Server::get(IConfig::class),
|
|
|
|
|
\OC::$server->getL10NFactory(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Mount the share collection at /public.php/dav/shares/<share token>
|
2025-05-14 09:29:02 -04:00
|
|
|
$rootCollection->addChild(new RootCollection(
|
2025-04-14 09:16:44 -04:00
|
|
|
$root,
|
|
|
|
|
$userPrincipalBackend,
|
|
|
|
|
'principals/shares',
|
|
|
|
|
));
|
2025-04-14 09:41:13 -04:00
|
|
|
|
|
|
|
|
// Mount the upload collection at /public.php/dav/uploads/<share token>
|
|
|
|
|
$rootCollection->addChild(new \OCA\DAV\Upload\RootCollection(
|
|
|
|
|
$userPrincipalBackend,
|
|
|
|
|
'principals/shares',
|
|
|
|
|
\OCP\Server::get(CleanupService::class),
|
|
|
|
|
\OCP\Server::get(IRootFolder::class),
|
|
|
|
|
\OCP\Server::get(IUserSession::class),
|
|
|
|
|
\OCP\Server::get(\OCP\Share\IManager::class),
|
|
|
|
|
));
|
2025-04-14 09:16:44 -04:00
|
|
|
} else {
|
|
|
|
|
/** @var ObjectTree $tree */
|
|
|
|
|
$tree->init($root, $view, $this->mountManager);
|
|
|
|
|
}
|
2015-08-07 11:36:14 -04:00
|
|
|
|
2016-04-18 05:18:50 -04:00
|
|
|
$server->addPlugin(
|
2024-10-10 06:40:31 -04:00
|
|
|
new FilesPlugin(
|
2025-04-14 09:16:44 -04:00
|
|
|
$tree,
|
2016-04-18 05:18:50 -04:00
|
|
|
$this->config,
|
2016-06-09 05:29:20 -04:00
|
|
|
$this->request,
|
2016-07-26 07:15:12 -04:00
|
|
|
$this->previewManager,
|
2021-07-21 08:23:49 -04:00
|
|
|
$this->userSession,
|
2024-08-27 06:59:06 -04:00
|
|
|
\OCP\Server::get(IFilenameValidator::class),
|
2025-04-29 10:42:09 -04:00
|
|
|
\OCP\Server::get(IAccountManager::class),
|
2016-04-18 05:18:50 -04:00
|
|
|
false,
|
2025-07-29 11:07:08 -04:00
|
|
|
!$debugEnabled
|
2016-04-18 05:18:50 -04:00
|
|
|
)
|
|
|
|
|
);
|
2025-07-15 06:56:51 -04:00
|
|
|
$server->addPlugin(new QuotaPlugin($view));
|
2024-10-10 06:40:31 -04:00
|
|
|
$server->addPlugin(new ChecksumUpdatePlugin());
|
2015-08-07 11:36:14 -04:00
|
|
|
|
2022-05-18 08:54:27 -04:00
|
|
|
// Allow view-only plugin for webdav requests
|
|
|
|
|
$server->addPlugin(new ViewOnlyPlugin(
|
2024-02-13 08:46:04 -05:00
|
|
|
$userFolder,
|
2022-05-18 08:54:27 -04:00
|
|
|
));
|
|
|
|
|
|
2015-08-07 11:36:14 -04:00
|
|
|
if ($this->userSession->isLoggedIn()) {
|
2025-04-14 09:16:44 -04:00
|
|
|
$server->addPlugin(new TagsPlugin($tree, $this->tagManager, $this->eventDispatcher, $this->userSession));
|
2024-10-10 06:40:31 -04:00
|
|
|
$server->addPlugin(new SharesPlugin(
|
2025-04-14 09:16:44 -04:00
|
|
|
$tree,
|
2016-03-02 12:25:31 -05:00
|
|
|
$this->userSession,
|
|
|
|
|
$userFolder,
|
2025-02-03 09:34:01 -05:00
|
|
|
\OCP\Server::get(\OCP\Share\IManager::class)
|
2016-03-02 12:25:31 -05:00
|
|
|
));
|
2025-02-03 09:34:01 -05:00
|
|
|
$server->addPlugin(new CommentPropertiesPlugin(\OCP\Server::get(ICommentsManager::class), $this->userSession));
|
2024-10-10 06:40:31 -04:00
|
|
|
$server->addPlugin(new FilesReportPlugin(
|
2025-04-14 09:16:44 -04:00
|
|
|
$tree,
|
2016-02-03 15:55:04 -05:00
|
|
|
$view,
|
2025-02-03 09:34:01 -05:00
|
|
|
\OCP\Server::get(ISystemTagManager::class),
|
|
|
|
|
\OCP\Server::get(ISystemTagObjectMapper::class),
|
|
|
|
|
\OCP\Server::get(ITagManager::class),
|
2016-02-03 15:55:04 -05:00
|
|
|
$this->userSession,
|
2025-02-03 09:34:01 -05:00
|
|
|
\OCP\Server::get(IGroupManager::class),
|
2019-03-12 19:42:39 -04:00
|
|
|
$userFolder,
|
2025-02-03 09:34:01 -05:00
|
|
|
\OCP\Server::get(IAppManager::class)
|
2016-02-03 15:55:04 -05:00
|
|
|
));
|
2015-08-11 07:28:33 -04:00
|
|
|
// custom properties plugin must be the last one
|
2015-08-07 11:36:14 -04:00
|
|
|
$server->addPlugin(
|
|
|
|
|
new \Sabre\DAV\PropertyStorage\Plugin(
|
2024-10-10 06:40:31 -04:00
|
|
|
new CustomPropertiesBackend(
|
2024-02-21 16:29:09 -05:00
|
|
|
$server,
|
2025-04-14 09:16:44 -04:00
|
|
|
$tree,
|
2015-08-07 11:36:14 -04:00
|
|
|
$this->databaseConnection,
|
2024-06-04 09:58:39 -04:00
|
|
|
$this->userSession->getUser(),
|
2025-08-13 05:03:40 -04:00
|
|
|
\OCP\Server::get(PropertyMapper::class),
|
2025-02-03 09:34:01 -05:00
|
|
|
\OCP\Server::get(DefaultCalendarValidator::class),
|
2015-08-07 11:36:14 -04:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-10-10 06:40:31 -04:00
|
|
|
$server->addPlugin(new CopyEtagHeaderPlugin());
|
2019-11-21 09:47:11 -05:00
|
|
|
|
|
|
|
|
// Load dav plugins from apps
|
|
|
|
|
$event = new SabrePluginEvent($server);
|
2023-07-11 05:50:07 -04:00
|
|
|
$this->eventDispatcher->dispatchTyped($event);
|
2019-11-21 09:47:11 -05:00
|
|
|
$pluginManager = new PluginManager(
|
|
|
|
|
\OC::$server,
|
2025-02-03 09:34:01 -05:00
|
|
|
\OCP\Server::get(IAppManager::class)
|
2019-11-21 09:47:11 -05:00
|
|
|
);
|
|
|
|
|
foreach ($pluginManager->getAppPlugins() as $appPlugin) {
|
|
|
|
|
$server->addPlugin($appPlugin);
|
|
|
|
|
}
|
2015-08-07 11:36:14 -04:00
|
|
|
}, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request
|
|
|
|
|
return $server;
|
|
|
|
|
}
|
|
|
|
|
}
|