ServerFactory.php 5.5 KB

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