ServerFactory.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\DAV\Connector\Sabre;
  8. use OCA\DAV\AppInfo\PluginManager;
  9. use OCA\DAV\CalDAV\DefaultCalendarValidator;
  10. use OCA\DAV\DAV\ViewOnlyPlugin;
  11. use OCA\DAV\Files\BrowserErrorPagePlugin;
  12. use OCP\EventDispatcher\IEventDispatcher;
  13. use OCP\Files\Folder;
  14. use OCP\Files\IFilenameValidator;
  15. use OCP\Files\Mount\IMountManager;
  16. use OCP\IConfig;
  17. use OCP\IDBConnection;
  18. use OCP\IL10N;
  19. use OCP\IPreview;
  20. use OCP\IRequest;
  21. use OCP\ITagManager;
  22. use OCP\IUserSession;
  23. use OCP\SabrePluginEvent;
  24. use Psr\Log\LoggerInterface;
  25. use Sabre\DAV\Auth\Plugin;
  26. class ServerFactory {
  27. private IConfig $config;
  28. private LoggerInterface $logger;
  29. private IDBConnection $databaseConnection;
  30. private IUserSession $userSession;
  31. private IMountManager $mountManager;
  32. private ITagManager $tagManager;
  33. private IRequest $request;
  34. private IPreview $previewManager;
  35. private IEventDispatcher $eventDispatcher;
  36. private IL10N $l10n;
  37. public function __construct(
  38. IConfig $config,
  39. LoggerInterface $logger,
  40. IDBConnection $databaseConnection,
  41. IUserSession $userSession,
  42. IMountManager $mountManager,
  43. ITagManager $tagManager,
  44. IRequest $request,
  45. IPreview $previewManager,
  46. IEventDispatcher $eventDispatcher,
  47. IL10N $l10n
  48. ) {
  49. $this->config = $config;
  50. $this->logger = $logger;
  51. $this->databaseConnection = $databaseConnection;
  52. $this->userSession = $userSession;
  53. $this->mountManager = $mountManager;
  54. $this->tagManager = $tagManager;
  55. $this->request = $request;
  56. $this->previewManager = $previewManager;
  57. $this->eventDispatcher = $eventDispatcher;
  58. $this->l10n = $l10n;
  59. }
  60. /**
  61. * @param callable $viewCallBack callback that should return the view for the dav endpoint
  62. */
  63. public function createServer(string $baseUri,
  64. string $requestUri,
  65. Plugin $authPlugin,
  66. callable $viewCallBack): Server {
  67. // Fire up server
  68. $objectTree = new \OCA\DAV\Connector\Sabre\ObjectTree();
  69. $server = new \OCA\DAV\Connector\Sabre\Server($objectTree);
  70. // Set URL explicitly due to reverse-proxy situations
  71. $server->httpRequest->setUrl($requestUri);
  72. $server->setBaseUri($baseUri);
  73. // Load plugins
  74. $server->addPlugin(new \OCA\DAV\Connector\Sabre\MaintenancePlugin($this->config, $this->l10n));
  75. $server->addPlugin(new \OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin($this->config));
  76. $server->addPlugin(new \OCA\DAV\Connector\Sabre\AnonymousOptionsPlugin());
  77. $server->addPlugin($authPlugin);
  78. // FIXME: The following line is a workaround for legacy components relying on being able to send a GET to /
  79. $server->addPlugin(new \OCA\DAV\Connector\Sabre\DummyGetResponsePlugin());
  80. $server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $this->logger));
  81. $server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin());
  82. $server->addPlugin(new RequestIdHeaderPlugin(\OC::$server->get(IRequest::class)));
  83. // Some WebDAV clients do require Class 2 WebDAV support (locking), since
  84. // we do not provide locking we emulate it using a fake locking plugin.
  85. if ($this->request->isUserAgent([
  86. '/WebDAVFS/',
  87. '/OneNote/',
  88. '/Microsoft-WebDAV-MiniRedir/',
  89. ])) {
  90. $server->addPlugin(new \OCA\DAV\Connector\Sabre\FakeLockerPlugin());
  91. }
  92. if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) {
  93. $server->addPlugin(new BrowserErrorPagePlugin());
  94. }
  95. // wait with registering these until auth is handled and the filesystem is setup
  96. $server->on('beforeMethod:*', function () use ($server, $objectTree, $viewCallBack) {
  97. // ensure the skeleton is copied
  98. $userFolder = \OC::$server->getUserFolder();
  99. /** @var \OC\Files\View $view */
  100. $view = $viewCallBack($server);
  101. if ($userFolder instanceof Folder && $userFolder->getPath() === $view->getRoot()) {
  102. $rootInfo = $userFolder;
  103. } else {
  104. $rootInfo = $view->getFileInfo('');
  105. }
  106. // Create Nextcloud Dir
  107. if ($rootInfo->getType() === 'dir') {
  108. $root = new \OCA\DAV\Connector\Sabre\Directory($view, $rootInfo, $objectTree);
  109. } else {
  110. $root = new \OCA\DAV\Connector\Sabre\File($view, $rootInfo);
  111. }
  112. $objectTree->init($root, $view, $this->mountManager);
  113. $server->addPlugin(
  114. new \OCA\DAV\Connector\Sabre\FilesPlugin(
  115. $objectTree,
  116. $this->config,
  117. $this->request,
  118. $this->previewManager,
  119. $this->userSession,
  120. \OCP\Server::get(IFilenameValidator::class),
  121. false,
  122. !$this->config->getSystemValue('debug', false)
  123. )
  124. );
  125. $server->addPlugin(new \OCA\DAV\Connector\Sabre\QuotaPlugin($view, true));
  126. $server->addPlugin(new \OCA\DAV\Connector\Sabre\ChecksumUpdatePlugin());
  127. // Allow view-only plugin for webdav requests
  128. $server->addPlugin(new ViewOnlyPlugin(
  129. $userFolder,
  130. ));
  131. if ($this->userSession->isLoggedIn()) {
  132. $server->addPlugin(new \OCA\DAV\Connector\Sabre\TagsPlugin($objectTree, $this->tagManager));
  133. $server->addPlugin(new \OCA\DAV\Connector\Sabre\SharesPlugin(
  134. $objectTree,
  135. $this->userSession,
  136. $userFolder,
  137. \OC::$server->getShareManager()
  138. ));
  139. $server->addPlugin(new \OCA\DAV\Connector\Sabre\CommentPropertiesPlugin(\OC::$server->getCommentsManager(), $this->userSession));
  140. $server->addPlugin(new \OCA\DAV\Connector\Sabre\FilesReportPlugin(
  141. $objectTree,
  142. $view,
  143. \OC::$server->getSystemTagManager(),
  144. \OC::$server->getSystemTagObjectMapper(),
  145. \OC::$server->getTagManager(),
  146. $this->userSession,
  147. \OC::$server->getGroupManager(),
  148. $userFolder,
  149. \OC::$server->getAppManager()
  150. ));
  151. // custom properties plugin must be the last one
  152. $server->addPlugin(
  153. new \Sabre\DAV\PropertyStorage\Plugin(
  154. new \OCA\DAV\DAV\CustomPropertiesBackend(
  155. $server,
  156. $objectTree,
  157. $this->databaseConnection,
  158. $this->userSession->getUser(),
  159. \OC::$server->get(DefaultCalendarValidator::class),
  160. )
  161. )
  162. );
  163. }
  164. $server->addPlugin(new \OCA\DAV\Connector\Sabre\CopyEtagHeaderPlugin());
  165. // Load dav plugins from apps
  166. $event = new SabrePluginEvent($server);
  167. $this->eventDispatcher->dispatchTyped($event);
  168. $pluginManager = new PluginManager(
  169. \OC::$server,
  170. \OC::$server->getAppManager()
  171. );
  172. foreach ($pluginManager->getAppPlugins() as $appPlugin) {
  173. $server->addPlugin($appPlugin);
  174. }
  175. }, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request
  176. return $server;
  177. }
  178. }