You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FakeLockerPlugin.php 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. /**
  3. * @author Lukas Reschke <lukas@statuscode.ch>
  4. * @author Thomas Müller <thomas.mueller@tmit.eu>
  5. *
  6. * @copyright Copyright (c) 2016, ownCloud, Inc.
  7. * @license AGPL-3.0
  8. *
  9. * This code is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License, version 3,
  11. * as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License, version 3,
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>
  20. *
  21. */
  22. namespace OCA\DAV\Connector\Sabre;
  23. use Sabre\DAV\Locks\LockInfo;
  24. use Sabre\DAV\ServerPlugin;
  25. use Sabre\DAV\Xml\Property\LockDiscovery;
  26. use Sabre\DAV\Xml\Property\SupportedLock;
  27. use Sabre\HTTP\RequestInterface;
  28. use Sabre\HTTP\ResponseInterface;
  29. use Sabre\DAV\PropFind;
  30. use Sabre\DAV\INode;
  31. /**
  32. * Class FakeLockerPlugin is a plugin only used when connections come in from
  33. * OS X via Finder. The fake locking plugin does emulate Class 2 WebDAV support
  34. * (locking of files) which allows Finder to access the storage in write mode as
  35. * well.
  36. *
  37. * No real locking is performed, instead the plugin just returns always positive
  38. * responses.
  39. *
  40. * @see https://github.com/owncloud/core/issues/17732
  41. * @package OCA\DAV\Connector\Sabre
  42. */
  43. class FakeLockerPlugin extends ServerPlugin {
  44. /** @var \Sabre\DAV\Server */
  45. private $server;
  46. /** {@inheritDoc} */
  47. public function initialize(\Sabre\DAV\Server $server) {
  48. $this->server = $server;
  49. $this->server->on('method:LOCK', [$this, 'fakeLockProvider'], 1);
  50. $this->server->on('method:UNLOCK', [$this, 'fakeUnlockProvider'], 1);
  51. $server->on('propFind', [$this, 'propFind']);
  52. $server->on('validateTokens', [$this, 'validateTokens']);
  53. }
  54. /**
  55. * Indicate that we support LOCK and UNLOCK
  56. *
  57. * @param string $path
  58. * @return string[]
  59. */
  60. public function getHTTPMethods($path) {
  61. return [
  62. 'LOCK',
  63. 'UNLOCK',
  64. ];
  65. }
  66. /**
  67. * Indicate that we support locking
  68. *
  69. * @return integer[]
  70. */
  71. function getFeatures() {
  72. return [2];
  73. }
  74. /**
  75. * Return some dummy response for PROPFIND requests with regard to locking
  76. *
  77. * @param PropFind $propFind
  78. * @param INode $node
  79. * @return void
  80. */
  81. function propFind(PropFind $propFind, INode $node) {
  82. $propFind->handle('{DAV:}supportedlock', function() {
  83. return new SupportedLock(true);
  84. });
  85. $propFind->handle('{DAV:}lockdiscovery', function() use ($propFind) {
  86. return new LockDiscovery([]);
  87. });
  88. }
  89. /**
  90. * Mark a locking token always as valid
  91. *
  92. * @param RequestInterface $request
  93. * @param array $conditions
  94. */
  95. public function validateTokens(RequestInterface $request, &$conditions) {
  96. foreach($conditions as &$fileCondition) {
  97. if(isset($fileCondition['tokens'])) {
  98. foreach($fileCondition['tokens'] as &$token) {
  99. if(isset($token['token'])) {
  100. if(substr($token['token'], 0, 16) === 'opaquelocktoken:') {
  101. $token['validToken'] = true;
  102. }
  103. }
  104. }
  105. }
  106. }
  107. }
  108. /**
  109. * Fakes a successful LOCK
  110. *
  111. * @param RequestInterface $request
  112. * @param ResponseInterface $response
  113. * @return bool
  114. */
  115. public function fakeLockProvider(RequestInterface $request,
  116. ResponseInterface $response) {
  117. $lockInfo = new LockInfo();
  118. $lockInfo->token = md5($request->getPath());
  119. $lockInfo->uri = $request->getPath();
  120. $lockInfo->depth = \Sabre\DAV\Server::DEPTH_INFINITY;
  121. $lockInfo->timeout = 1800;
  122. $body = $this->server->xml->write('{DAV:}prop', [
  123. '{DAV:}lockdiscovery' =>
  124. new LockDiscovery([$lockInfo])
  125. ]);
  126. $response->setBody($body);
  127. return false;
  128. }
  129. /**
  130. * Fakes a successful LOCK
  131. *
  132. * @param RequestInterface $request
  133. * @param ResponseInterface $response
  134. * @return bool
  135. */
  136. public function fakeUnlockProvider(RequestInterface $request,
  137. ResponseInterface $response) {
  138. $response->setStatus(204);
  139. $response->setHeader('Content-Length', '0');
  140. return false;
  141. }
  142. }