ServerFactory.php 6.3 KB

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