Completed
Push — master ( 5b1d92...31af87 )
by
unknown
57:08 queued 14:46
created
apps/dav/appinfo/v1/publicwebdav.php 2 patches
Indentation   +62 added lines, -62 removed lines patch added patch discarded remove patch
@@ -40,10 +40,10 @@  discard block
 block discarded – undo
40 40
 
41 41
 // Backends
42 42
 $authBackend = new LegacyPublicAuth(
43
-	Server::get(IRequest::class),
44
-	Server::get(\OCP\Share\IManager::class),
45
-	Server::get(ISession::class),
46
-	Server::get(IThrottler::class)
43
+    Server::get(IRequest::class),
44
+    Server::get(\OCP\Share\IManager::class),
45
+    Server::get(ISession::class),
46
+    Server::get(IThrottler::class)
47 47
 );
48 48
 $authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend);
49 49
 
@@ -51,16 +51,16 @@  discard block
 block discarded – undo
51 51
 $eventDispatcher = Server::get(IEventDispatcher::class);
52 52
 
53 53
 $serverFactory = new ServerFactory(
54
-	Server::get(IConfig::class),
55
-	Server::get(LoggerInterface::class),
56
-	Server::get(IDBConnection::class),
57
-	Server::get(IUserSession::class),
58
-	Server::get(IMountManager::class),
59
-	Server::get(ITagManager::class),
60
-	Server::get(IRequest::class),
61
-	Server::get(IPreview::class),
62
-	$eventDispatcher,
63
-	\OC::$server->getL10N('dav')
54
+    Server::get(IConfig::class),
55
+    Server::get(LoggerInterface::class),
56
+    Server::get(IDBConnection::class),
57
+    Server::get(IUserSession::class),
58
+    Server::get(IMountManager::class),
59
+    Server::get(ITagManager::class),
60
+    Server::get(IRequest::class),
61
+    Server::get(IPreview::class),
62
+    $eventDispatcher,
63
+    \OC::$server->getL10N('dav')
64 64
 );
65 65
 
66 66
 $requestUri = Server::get(IRequest::class)->getRequestUri();
@@ -69,54 +69,54 @@  discard block
 block discarded – undo
69 69
 $filesDropPlugin = new FilesDropPlugin();
70 70
 
71 71
 $server = $serverFactory->createServer(
72
-	true,
73
-	$baseuri,
74
-	$requestUri,
75
-	$authPlugin,
76
-	function (\Sabre\DAV\Server $server) use (
77
-		$authBackend,
78
-		$linkCheckPlugin,
79
-		$filesDropPlugin
80
-	) {
81
-		$isAjax = in_array('XMLHttpRequest', explode(',', $_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''));
82
-		/** @var FederatedShareProvider $shareProvider */
83
-		$federatedShareProvider = Server::get(FederatedShareProvider::class);
84
-		if ($federatedShareProvider->isOutgoingServer2serverShareEnabled() === false && !$isAjax) {
85
-			// this is what is thrown when trying to access a non-existing share
86
-			throw new \Sabre\DAV\Exception\NotAuthenticated();
87
-		}
88
-
89
-		$share = $authBackend->getShare();
90
-		$owner = $share->getShareOwner();
91
-		$isReadable = $share->getPermissions() & Constants::PERMISSION_READ;
92
-		$fileId = $share->getNodeId();
93
-
94
-		// FIXME: should not add storage wrappers outside of preSetup, need to find a better way
95
-		$previousLog = Filesystem::logWarningWhenAddingStorageWrapper(false);
96
-		Filesystem::addStorageWrapper('sharePermissions', function ($mountPoint, $storage) use ($share) {
97
-			return new PermissionsMask(['storage' => $storage, 'mask' => $share->getPermissions() | Constants::PERMISSION_SHARE]);
98
-		});
99
-		Filesystem::addStorageWrapper('shareOwner', function ($mountPoint, $storage) use ($share) {
100
-			return new PublicOwnerWrapper(['storage' => $storage, 'owner' => $share->getShareOwner()]);
101
-		});
102
-		Filesystem::logWarningWhenAddingStorageWrapper($previousLog);
103
-
104
-		$rootFolder = Server::get(IRootFolder::class);
105
-		$userFolder = $rootFolder->getUserFolder($owner);
106
-		$node = $userFolder->getFirstNodeById($fileId);
107
-		if (!$node) {
108
-			throw new \Sabre\DAV\Exception\NotFound();
109
-		}
110
-		$linkCheckPlugin->setFileInfo($node);
111
-
112
-		// If not readable (files_drop) enable the filesdrop plugin
113
-		if (!$isReadable) {
114
-			$filesDropPlugin->enable();
115
-		}
116
-		$filesDropPlugin->setShare($share);
117
-
118
-		return new View($node->getPath());
119
-	});
72
+    true,
73
+    $baseuri,
74
+    $requestUri,
75
+    $authPlugin,
76
+    function (\Sabre\DAV\Server $server) use (
77
+        $authBackend,
78
+        $linkCheckPlugin,
79
+        $filesDropPlugin
80
+    ) {
81
+        $isAjax = in_array('XMLHttpRequest', explode(',', $_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''));
82
+        /** @var FederatedShareProvider $shareProvider */
83
+        $federatedShareProvider = Server::get(FederatedShareProvider::class);
84
+        if ($federatedShareProvider->isOutgoingServer2serverShareEnabled() === false && !$isAjax) {
85
+            // this is what is thrown when trying to access a non-existing share
86
+            throw new \Sabre\DAV\Exception\NotAuthenticated();
87
+        }
88
+
89
+        $share = $authBackend->getShare();
90
+        $owner = $share->getShareOwner();
91
+        $isReadable = $share->getPermissions() & Constants::PERMISSION_READ;
92
+        $fileId = $share->getNodeId();
93
+
94
+        // FIXME: should not add storage wrappers outside of preSetup, need to find a better way
95
+        $previousLog = Filesystem::logWarningWhenAddingStorageWrapper(false);
96
+        Filesystem::addStorageWrapper('sharePermissions', function ($mountPoint, $storage) use ($share) {
97
+            return new PermissionsMask(['storage' => $storage, 'mask' => $share->getPermissions() | Constants::PERMISSION_SHARE]);
98
+        });
99
+        Filesystem::addStorageWrapper('shareOwner', function ($mountPoint, $storage) use ($share) {
100
+            return new PublicOwnerWrapper(['storage' => $storage, 'owner' => $share->getShareOwner()]);
101
+        });
102
+        Filesystem::logWarningWhenAddingStorageWrapper($previousLog);
103
+
104
+        $rootFolder = Server::get(IRootFolder::class);
105
+        $userFolder = $rootFolder->getUserFolder($owner);
106
+        $node = $userFolder->getFirstNodeById($fileId);
107
+        if (!$node) {
108
+            throw new \Sabre\DAV\Exception\NotFound();
109
+        }
110
+        $linkCheckPlugin->setFileInfo($node);
111
+
112
+        // If not readable (files_drop) enable the filesdrop plugin
113
+        if (!$isReadable) {
114
+            $filesDropPlugin->enable();
115
+        }
116
+        $filesDropPlugin->setShare($share);
117
+
118
+        return new View($node->getPath());
119
+    });
120 120
 
121 121
 $server->addPlugin($linkCheckPlugin);
122 122
 $server->addPlugin($filesDropPlugin);
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -73,7 +73,7 @@  discard block
 block discarded – undo
73 73
 	$baseuri,
74 74
 	$requestUri,
75 75
 	$authPlugin,
76
-	function (\Sabre\DAV\Server $server) use (
76
+	function(\Sabre\DAV\Server $server) use (
77 77
 		$authBackend,
78 78
 		$linkCheckPlugin,
79 79
 		$filesDropPlugin
@@ -93,10 +93,10 @@  discard block
 block discarded – undo
93 93
 
94 94
 		// FIXME: should not add storage wrappers outside of preSetup, need to find a better way
95 95
 		$previousLog = Filesystem::logWarningWhenAddingStorageWrapper(false);
96
-		Filesystem::addStorageWrapper('sharePermissions', function ($mountPoint, $storage) use ($share) {
96
+		Filesystem::addStorageWrapper('sharePermissions', function($mountPoint, $storage) use ($share) {
97 97
 			return new PermissionsMask(['storage' => $storage, 'mask' => $share->getPermissions() | Constants::PERMISSION_SHARE]);
98 98
 		});
99
-		Filesystem::addStorageWrapper('shareOwner', function ($mountPoint, $storage) use ($share) {
99
+		Filesystem::addStorageWrapper('shareOwner', function($mountPoint, $storage) use ($share) {
100 100
 			return new PublicOwnerWrapper(['storage' => $storage, 'owner' => $share->getShareOwner()]);
101 101
 		});
102 102
 		Filesystem::logWarningWhenAddingStorageWrapper($previousLog);
Please login to merge, or discard this patch.
apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php 1 patch
Indentation   +425 added lines, -425 removed lines patch added patch discarded remove patch
@@ -27,445 +27,445 @@
 block discarded – undo
27 27
 use Test\Traits\UserTrait;
28 28
 
29 29
 class TestViewDirectory extends View {
30
-	public function __construct(
31
-		private $updatables,
32
-		private $deletables,
33
-		private $canRename = true,
34
-	) {
35
-	}
36
-
37
-	public function isUpdatable($path) {
38
-		return $this->updatables[$path];
39
-	}
40
-
41
-	public function isCreatable($path) {
42
-		return $this->updatables[$path];
43
-	}
44
-
45
-	public function isDeletable($path) {
46
-		return $this->deletables[$path];
47
-	}
48
-
49
-	public function rename($source, $target, array $options = []) {
50
-		return $this->canRename;
51
-	}
52
-
53
-	public function getRelativePath($path): ?string {
54
-		return $path;
55
-	}
30
+    public function __construct(
31
+        private $updatables,
32
+        private $deletables,
33
+        private $canRename = true,
34
+    ) {
35
+    }
36
+
37
+    public function isUpdatable($path) {
38
+        return $this->updatables[$path];
39
+    }
40
+
41
+    public function isCreatable($path) {
42
+        return $this->updatables[$path];
43
+    }
44
+
45
+    public function isDeletable($path) {
46
+        return $this->deletables[$path];
47
+    }
48
+
49
+    public function rename($source, $target, array $options = []) {
50
+        return $this->canRename;
51
+    }
52
+
53
+    public function getRelativePath($path): ?string {
54
+        return $path;
55
+    }
56 56
 }
57 57
 
58 58
 
59 59
 #[\PHPUnit\Framework\Attributes\Group('DB')]
60 60
 class DirectoryTest extends \Test\TestCase {
61
-	use UserTrait;
62
-
63
-	private View&MockObject $view;
64
-	private FileInfo&MockObject $info;
65
-	private IStorage&MockObject $storage;
66
-
67
-	protected function setUp(): void {
68
-		parent::setUp();
69
-
70
-		$this->view = $this->createMock(View::class);
71
-		$this->info = $this->createMock(FileInfo::class);
72
-		$this->storage = $this->createMock(IStorage::class);
73
-		$this->info->method('getStorage')
74
-			->willReturn($this->storage);
75
-		$this->info->method('isReadable')
76
-			->willReturn(true);
77
-		$this->info->method('getType')
78
-			->willReturn(Node::TYPE_FOLDER);
79
-		$this->info->method('getName')
80
-			->willReturn('folder');
81
-		$this->info->method('getPath')
82
-			->willReturn('/admin/files/folder');
83
-		$this->info->method('getPermissions')
84
-			->willReturn(Constants::PERMISSION_READ);
85
-	}
86
-
87
-	private function getDir(string $path = '/'): Directory {
88
-		$this->view->expects($this->once())
89
-			->method('getRelativePath')
90
-			->willReturn($path);
91
-
92
-		$this->info->expects($this->once())
93
-			->method('getPath')
94
-			->willReturn($path);
95
-
96
-		return new Directory($this->view, $this->info);
97
-	}
98
-
99
-
100
-	public function testDeleteRootFolderFails(): void {
101
-		$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
102
-
103
-		$this->info->expects($this->any())
104
-			->method('isDeletable')
105
-			->willReturn(true);
106
-		$this->view->expects($this->never())
107
-			->method('rmdir');
108
-		$dir = $this->getDir();
109
-		$dir->delete();
110
-	}
111
-
112
-
113
-	public function testDeleteForbidden(): void {
114
-		$this->expectException(Forbidden::class);
115
-
116
-		// deletion allowed
117
-		$this->info->expects($this->once())
118
-			->method('isDeletable')
119
-			->willReturn(true);
120
-
121
-		// but fails
122
-		$this->view->expects($this->once())
123
-			->method('rmdir')
124
-			->with('sub')
125
-			->willThrowException(new ForbiddenException('', true));
126
-
127
-		$dir = $this->getDir('sub');
128
-		$dir->delete();
129
-	}
130
-
131
-
132
-	public function testDeleteFolderWhenAllowed(): void {
133
-		// deletion allowed
134
-		$this->info->expects($this->once())
135
-			->method('isDeletable')
136
-			->willReturn(true);
137
-
138
-		// but fails
139
-		$this->view->expects($this->once())
140
-			->method('rmdir')
141
-			->with('sub')
142
-			->willReturn(true);
143
-
144
-		$dir = $this->getDir('sub');
145
-		$dir->delete();
146
-	}
147
-
148
-
149
-	public function testDeleteFolderFailsWhenNotAllowed(): void {
150
-		$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
151
-
152
-		$this->info->expects($this->once())
153
-			->method('isDeletable')
154
-			->willReturn(false);
155
-
156
-		$dir = $this->getDir('sub');
157
-		$dir->delete();
158
-	}
159
-
160
-
161
-	public function testDeleteFolderThrowsWhenDeletionFailed(): void {
162
-		$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
163
-
164
-		// deletion allowed
165
-		$this->info->expects($this->once())
166
-			->method('isDeletable')
167
-			->willReturn(true);
168
-
169
-		// but fails
170
-		$this->view->expects($this->once())
171
-			->method('rmdir')
172
-			->with('sub')
173
-			->willReturn(false);
174
-
175
-		$dir = $this->getDir('sub');
176
-		$dir->delete();
177
-	}
178
-
179
-	public function testGetChildren(): void {
180
-		$info1 = $this->createMock(FileInfo::class);
181
-		$info2 = $this->createMock(FileInfo::class);
182
-		$info1->method('getName')
183
-			->willReturn('first');
184
-		$info1->method('getPath')
185
-			->willReturn('folder/first');
186
-		$info1->method('getEtag')
187
-			->willReturn('abc');
188
-		$info2->method('getName')
189
-			->willReturn('second');
190
-		$info2->method('getPath')
191
-			->willReturn('folder/second');
192
-		$info2->method('getEtag')
193
-			->willReturn('def');
61
+    use UserTrait;
62
+
63
+    private View&MockObject $view;
64
+    private FileInfo&MockObject $info;
65
+    private IStorage&MockObject $storage;
66
+
67
+    protected function setUp(): void {
68
+        parent::setUp();
69
+
70
+        $this->view = $this->createMock(View::class);
71
+        $this->info = $this->createMock(FileInfo::class);
72
+        $this->storage = $this->createMock(IStorage::class);
73
+        $this->info->method('getStorage')
74
+            ->willReturn($this->storage);
75
+        $this->info->method('isReadable')
76
+            ->willReturn(true);
77
+        $this->info->method('getType')
78
+            ->willReturn(Node::TYPE_FOLDER);
79
+        $this->info->method('getName')
80
+            ->willReturn('folder');
81
+        $this->info->method('getPath')
82
+            ->willReturn('/admin/files/folder');
83
+        $this->info->method('getPermissions')
84
+            ->willReturn(Constants::PERMISSION_READ);
85
+    }
86
+
87
+    private function getDir(string $path = '/'): Directory {
88
+        $this->view->expects($this->once())
89
+            ->method('getRelativePath')
90
+            ->willReturn($path);
91
+
92
+        $this->info->expects($this->once())
93
+            ->method('getPath')
94
+            ->willReturn($path);
95
+
96
+        return new Directory($this->view, $this->info);
97
+    }
98
+
99
+
100
+    public function testDeleteRootFolderFails(): void {
101
+        $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
102
+
103
+        $this->info->expects($this->any())
104
+            ->method('isDeletable')
105
+            ->willReturn(true);
106
+        $this->view->expects($this->never())
107
+            ->method('rmdir');
108
+        $dir = $this->getDir();
109
+        $dir->delete();
110
+    }
111
+
112
+
113
+    public function testDeleteForbidden(): void {
114
+        $this->expectException(Forbidden::class);
115
+
116
+        // deletion allowed
117
+        $this->info->expects($this->once())
118
+            ->method('isDeletable')
119
+            ->willReturn(true);
120
+
121
+        // but fails
122
+        $this->view->expects($this->once())
123
+            ->method('rmdir')
124
+            ->with('sub')
125
+            ->willThrowException(new ForbiddenException('', true));
126
+
127
+        $dir = $this->getDir('sub');
128
+        $dir->delete();
129
+    }
130
+
131
+
132
+    public function testDeleteFolderWhenAllowed(): void {
133
+        // deletion allowed
134
+        $this->info->expects($this->once())
135
+            ->method('isDeletable')
136
+            ->willReturn(true);
137
+
138
+        // but fails
139
+        $this->view->expects($this->once())
140
+            ->method('rmdir')
141
+            ->with('sub')
142
+            ->willReturn(true);
143
+
144
+        $dir = $this->getDir('sub');
145
+        $dir->delete();
146
+    }
147
+
148
+
149
+    public function testDeleteFolderFailsWhenNotAllowed(): void {
150
+        $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
151
+
152
+        $this->info->expects($this->once())
153
+            ->method('isDeletable')
154
+            ->willReturn(false);
155
+
156
+        $dir = $this->getDir('sub');
157
+        $dir->delete();
158
+    }
159
+
160
+
161
+    public function testDeleteFolderThrowsWhenDeletionFailed(): void {
162
+        $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
163
+
164
+        // deletion allowed
165
+        $this->info->expects($this->once())
166
+            ->method('isDeletable')
167
+            ->willReturn(true);
168
+
169
+        // but fails
170
+        $this->view->expects($this->once())
171
+            ->method('rmdir')
172
+            ->with('sub')
173
+            ->willReturn(false);
174
+
175
+        $dir = $this->getDir('sub');
176
+        $dir->delete();
177
+    }
178
+
179
+    public function testGetChildren(): void {
180
+        $info1 = $this->createMock(FileInfo::class);
181
+        $info2 = $this->createMock(FileInfo::class);
182
+        $info1->method('getName')
183
+            ->willReturn('first');
184
+        $info1->method('getPath')
185
+            ->willReturn('folder/first');
186
+        $info1->method('getEtag')
187
+            ->willReturn('abc');
188
+        $info2->method('getName')
189
+            ->willReturn('second');
190
+        $info2->method('getPath')
191
+            ->willReturn('folder/second');
192
+        $info2->method('getEtag')
193
+            ->willReturn('def');
194 194
 
195
-		$this->view->expects($this->once())
196
-			->method('getDirectoryContent')
197
-			->willReturn([$info1, $info2]);
195
+        $this->view->expects($this->once())
196
+            ->method('getDirectoryContent')
197
+            ->willReturn([$info1, $info2]);
198 198
 
199
-		$this->view->expects($this->any())
200
-			->method('getRelativePath')
201
-			->willReturnCallback(function ($path) {
202
-				return str_replace('/admin/files/', '', $path);
203
-			});
204
-
205
-		$this->view->expects($this->any())
206
-			->method('getAbsolutePath')
207
-			->willReturnCallback(function ($path) {
208
-				return Filesystem::normalizePath('/admin/files' . $path);
209
-			});
199
+        $this->view->expects($this->any())
200
+            ->method('getRelativePath')
201
+            ->willReturnCallback(function ($path) {
202
+                return str_replace('/admin/files/', '', $path);
203
+            });
204
+
205
+        $this->view->expects($this->any())
206
+            ->method('getAbsolutePath')
207
+            ->willReturnCallback(function ($path) {
208
+                return Filesystem::normalizePath('/admin/files' . $path);
209
+            });
210 210
 
211
-		$this->overwriteService(View::class, $this->view);
212
-
213
-		$dir = new Directory($this->view, $this->info);
214
-		$nodes = $dir->getChildren();
215
-
216
-		$this->assertCount(2, $nodes);
217
-
218
-		// calling a second time just returns the cached values,
219
-		// does not call getDirectoryContents again
220
-		$dir->getChildren();
221
-	}
211
+        $this->overwriteService(View::class, $this->view);
212
+
213
+        $dir = new Directory($this->view, $this->info);
214
+        $nodes = $dir->getChildren();
215
+
216
+        $this->assertCount(2, $nodes);
217
+
218
+        // calling a second time just returns the cached values,
219
+        // does not call getDirectoryContents again
220
+        $dir->getChildren();
221
+    }
222 222
 
223 223
 
224
-	public function testGetChildrenNoPermission(): void {
225
-		$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
224
+    public function testGetChildrenNoPermission(): void {
225
+        $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
226 226
 
227
-		$info = $this->createMock(FileInfo::class);
228
-		$info->expects($this->any())
229
-			->method('isReadable')
230
-			->willReturn(false);
231
-
232
-		$dir = new Directory($this->view, $info);
233
-		$dir->getChildren();
234
-	}
235
-
236
-
237
-	public function testGetChildNoPermission(): void {
238
-		$this->expectException(\Sabre\DAV\Exception\NotFound::class);
239
-
240
-		$this->info->expects($this->any())
241
-			->method('isReadable')
242
-			->willReturn(false);
243
-
244
-		$dir = new Directory($this->view, $this->info);
245
-		$dir->getChild('test');
246
-	}
247
-
248
-
249
-	public function testGetChildThrowStorageNotAvailableException(): void {
250
-		$this->expectException(\Sabre\DAV\Exception\ServiceUnavailable::class);
251
-
252
-		$this->view->expects($this->once())
253
-			->method('getFileInfo')
254
-			->willThrowException(new StorageNotAvailableException());
255
-
256
-		$dir = new Directory($this->view, $this->info);
257
-		$dir->getChild('.');
258
-	}
259
-
260
-
261
-	public function testGetChildThrowInvalidPath(): void {
262
-		$this->expectException(InvalidPath::class);
263
-
264
-		$this->view->expects($this->once())
265
-			->method('verifyPath')
266
-			->willThrowException(new InvalidPathException());
267
-		$this->view->expects($this->never())
268
-			->method('getFileInfo');
269
-
270
-		$dir = new Directory($this->view, $this->info);
271
-		$dir->getChild('.');
272
-	}
273
-
274
-	public function testGetQuotaInfoUnlimited(): void {
275
-		$this->createUser('user', 'password');
276
-		self::loginAsUser('user');
277
-		$mountPoint = $this->createMock(IMountPoint::class);
278
-		$storage = $this->createMock(Quota::class);
279
-		$mountPoint->method('getStorage')
280
-			->willReturn($storage);
281
-
282
-		$storage->expects($this->any())
283
-			->method('instanceOfStorage')
284
-			->willReturnMap([
285
-				['\OCA\Files_Sharing\SharedStorage', false],
286
-				['\OC\Files\Storage\Wrapper\Quota', false],
287
-				[Storage::class, false],
288
-			]);
289
-
290
-		$storage->expects($this->once())
291
-			->method('getOwner')
292
-			->willReturn('user');
227
+        $info = $this->createMock(FileInfo::class);
228
+        $info->expects($this->any())
229
+            ->method('isReadable')
230
+            ->willReturn(false);
231
+
232
+        $dir = new Directory($this->view, $info);
233
+        $dir->getChildren();
234
+    }
235
+
236
+
237
+    public function testGetChildNoPermission(): void {
238
+        $this->expectException(\Sabre\DAV\Exception\NotFound::class);
239
+
240
+        $this->info->expects($this->any())
241
+            ->method('isReadable')
242
+            ->willReturn(false);
243
+
244
+        $dir = new Directory($this->view, $this->info);
245
+        $dir->getChild('test');
246
+    }
247
+
248
+
249
+    public function testGetChildThrowStorageNotAvailableException(): void {
250
+        $this->expectException(\Sabre\DAV\Exception\ServiceUnavailable::class);
251
+
252
+        $this->view->expects($this->once())
253
+            ->method('getFileInfo')
254
+            ->willThrowException(new StorageNotAvailableException());
255
+
256
+        $dir = new Directory($this->view, $this->info);
257
+        $dir->getChild('.');
258
+    }
259
+
260
+
261
+    public function testGetChildThrowInvalidPath(): void {
262
+        $this->expectException(InvalidPath::class);
263
+
264
+        $this->view->expects($this->once())
265
+            ->method('verifyPath')
266
+            ->willThrowException(new InvalidPathException());
267
+        $this->view->expects($this->never())
268
+            ->method('getFileInfo');
269
+
270
+        $dir = new Directory($this->view, $this->info);
271
+        $dir->getChild('.');
272
+    }
273
+
274
+    public function testGetQuotaInfoUnlimited(): void {
275
+        $this->createUser('user', 'password');
276
+        self::loginAsUser('user');
277
+        $mountPoint = $this->createMock(IMountPoint::class);
278
+        $storage = $this->createMock(Quota::class);
279
+        $mountPoint->method('getStorage')
280
+            ->willReturn($storage);
281
+
282
+        $storage->expects($this->any())
283
+            ->method('instanceOfStorage')
284
+            ->willReturnMap([
285
+                ['\OCA\Files_Sharing\SharedStorage', false],
286
+                ['\OC\Files\Storage\Wrapper\Quota', false],
287
+                [Storage::class, false],
288
+            ]);
289
+
290
+        $storage->expects($this->once())
291
+            ->method('getOwner')
292
+            ->willReturn('user');
293 293
 
294
-		$storage->expects($this->never())
295
-			->method('getQuota');
294
+        $storage->expects($this->never())
295
+            ->method('getQuota');
296 296
 
297
-		$storage->expects($this->once())
298
-			->method('free_space')
299
-			->willReturn(800);
297
+        $storage->expects($this->once())
298
+            ->method('free_space')
299
+            ->willReturn(800);
300 300
 
301
-		$this->info->expects($this->any())
302
-			->method('getPath')
303
-			->willReturn('/admin/files/foo');
301
+        $this->info->expects($this->any())
302
+            ->method('getPath')
303
+            ->willReturn('/admin/files/foo');
304 304
 
305
-		$this->info->expects($this->once())
306
-			->method('getSize')
307
-			->willReturn(200);
305
+        $this->info->expects($this->once())
306
+            ->method('getSize')
307
+            ->willReturn(200);
308 308
 
309
-		$this->info->expects($this->once())
310
-			->method('getMountPoint')
311
-			->willReturn($mountPoint);
312
-
313
-		$this->view->expects($this->any())
314
-			->method('getRelativePath')
315
-			->willReturn('/foo');
316
-
317
-		$this->info->expects($this->once())
318
-			->method('getInternalPath')
319
-			->willReturn('/foo');
320
-
321
-		$mountPoint->method('getMountPoint')
322
-			->willReturn('/user/files/mymountpoint');
323
-
324
-		$dir = new Directory($this->view, $this->info);
325
-		$this->assertEquals([200, -3], $dir->getQuotaInfo()); //200 used, unlimited
326
-	}
327
-
328
-	public function testGetQuotaInfoSpecific(): void {
329
-		$this->createUser('user', 'password');
330
-		self::loginAsUser('user');
331
-		$mountPoint = $this->createMock(IMountPoint::class);
332
-		$storage = $this->createMock(Quota::class);
333
-		$mountPoint->method('getStorage')
334
-			->willReturn($storage);
335
-
336
-		$storage->expects($this->any())
337
-			->method('instanceOfStorage')
338
-			->willReturnMap([
339
-				['\OCA\Files_Sharing\SharedStorage', false],
340
-				['\OC\Files\Storage\Wrapper\Quota', true],
341
-				[Storage::class, false],
342
-			]);
343
-
344
-		$storage->expects($this->once())
345
-			->method('getOwner')
346
-			->willReturn('user');
347
-
348
-		$storage->expects($this->once())
349
-			->method('getQuota')
350
-			->willReturn(1000);
351
-
352
-		$storage->expects($this->once())
353
-			->method('free_space')
354
-			->willReturn(800);
355
-
356
-		$this->info->expects($this->once())
357
-			->method('getSize')
358
-			->willReturn(200);
359
-
360
-		$this->info->expects($this->once())
361
-			->method('getMountPoint')
362
-			->willReturn($mountPoint);
363
-
364
-		$this->info->expects($this->once())
365
-			->method('getInternalPath')
366
-			->willReturn('/foo');
367
-
368
-		$mountPoint->method('getMountPoint')
369
-			->willReturn('/user/files/mymountpoint');
370
-
371
-		$this->view->expects($this->any())
372
-			->method('getRelativePath')
373
-			->willReturn('/foo');
374
-
375
-		$dir = new Directory($this->view, $this->info);
376
-		$this->assertEquals([200, 800], $dir->getQuotaInfo()); //200 used, 800 free
377
-	}
378
-
379
-	#[\PHPUnit\Framework\Attributes\DataProvider('moveFailedProvider')]
380
-	public function testMoveFailed(string $source, string $destination, array $updatables, array $deletables): void {
381
-		$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
382
-
383
-		$this->moveTest($source, $destination, $updatables, $deletables);
384
-	}
385
-
386
-	#[\PHPUnit\Framework\Attributes\DataProvider('moveSuccessProvider')]
387
-	public function testMoveSuccess(string $source, string $destination, array $updatables, array $deletables): void {
388
-		$this->moveTest($source, $destination, $updatables, $deletables);
389
-		$this->addToAssertionCount(1);
390
-	}
391
-
392
-	#[\PHPUnit\Framework\Attributes\DataProvider('moveFailedInvalidCharsProvider')]
393
-	public function testMoveFailedInvalidChars(string $source, string $destination, array $updatables, array $deletables): void {
394
-		$this->expectException(InvalidPath::class);
395
-
396
-		$this->moveTest($source, $destination, $updatables, $deletables);
397
-	}
398
-
399
-	public static function moveFailedInvalidCharsProvider(): array {
400
-		return [
401
-			['a/valid', "a/i\nvalid", ['a' => true, 'a/valid' => true, 'a/c*' => false], []],
402
-		];
403
-	}
404
-
405
-	public static function moveFailedProvider(): array {
406
-		return [
407
-			['a/b', 'a/c', ['a' => false, 'a/b' => false, 'a/c' => false], []],
408
-			['a/b', 'b/b', ['a' => false, 'a/b' => false, 'b' => false, 'b/b' => false], []],
409
-			['a/b', 'b/b', ['a' => false, 'a/b' => true, 'b' => false, 'b/b' => false], []],
410
-			['a/b', 'b/b', ['a' => true, 'a/b' => true, 'b' => false, 'b/b' => false], []],
411
-			['a/b', 'b/b', ['a' => true, 'a/b' => true, 'b' => true, 'b/b' => false], ['a/b' => false]],
412
-			['a/b', 'a/c', ['a' => false, 'a/b' => true, 'a/c' => false], []],
413
-		];
414
-	}
415
-
416
-	public static function moveSuccessProvider(): array {
417
-		return [
418
-			['a/b', 'b/b', ['a' => true, 'a/b' => true, 'b' => true, 'b/b' => false], ['a/b' => true]],
419
-			// older files with special chars can still be renamed to valid names
420
-			['a/b*', 'b/b', ['a' => true, 'a/b*' => true, 'b' => true, 'b/b' => false], ['a/b*' => true]],
421
-		];
422
-	}
423
-
424
-	private function moveTest(string $source, string $destination, array $updatables, array $deletables): void {
425
-		$view = new TestViewDirectory($updatables, $deletables);
426
-
427
-		$sourceInfo = new FileInfo($source, null, null, [
428
-			'type' => FileInfo::TYPE_FOLDER,
429
-		], null);
430
-		$targetInfo = new FileInfo(dirname($destination), null, null, [
431
-			'type' => FileInfo::TYPE_FOLDER,
432
-		], null);
433
-
434
-		$sourceNode = new Directory($view, $sourceInfo);
435
-		$targetNode = $this->getMockBuilder(Directory::class)
436
-			->onlyMethods(['childExists'])
437
-			->setConstructorArgs([$view, $targetInfo])
438
-			->getMock();
439
-		$targetNode->expects($this->any())->method('childExists')
440
-			->with(basename($destination))
441
-			->willReturn(false);
442
-		$this->assertTrue($targetNode->moveInto(basename($destination), $source, $sourceNode));
443
-	}
444
-
445
-
446
-	public function testFailingMove(): void {
447
-		$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
448
-		$this->expectExceptionMessage('Could not copy directory b, target exists');
449
-
450
-		$source = 'a/b';
451
-		$destination = 'c/b';
452
-		$updatables = ['a' => true, 'a/b' => true, 'b' => true, 'c/b' => false];
453
-		$deletables = ['a/b' => true];
454
-
455
-		$view = new TestViewDirectory($updatables, $deletables);
456
-
457
-		$sourceInfo = new FileInfo($source, null, null, ['type' => FileInfo::TYPE_FOLDER], null);
458
-		$targetInfo = new FileInfo(dirname($destination), null, null, ['type' => FileInfo::TYPE_FOLDER], null);
459
-
460
-		$sourceNode = new Directory($view, $sourceInfo);
461
-		$targetNode = $this->getMockBuilder(Directory::class)
462
-			->onlyMethods(['childExists'])
463
-			->setConstructorArgs([$view, $targetInfo])
464
-			->getMock();
465
-		$targetNode->expects($this->once())->method('childExists')
466
-			->with(basename($destination))
467
-			->willReturn(true);
468
-
469
-		$targetNode->moveInto(basename($destination), $source, $sourceNode);
470
-	}
309
+        $this->info->expects($this->once())
310
+            ->method('getMountPoint')
311
+            ->willReturn($mountPoint);
312
+
313
+        $this->view->expects($this->any())
314
+            ->method('getRelativePath')
315
+            ->willReturn('/foo');
316
+
317
+        $this->info->expects($this->once())
318
+            ->method('getInternalPath')
319
+            ->willReturn('/foo');
320
+
321
+        $mountPoint->method('getMountPoint')
322
+            ->willReturn('/user/files/mymountpoint');
323
+
324
+        $dir = new Directory($this->view, $this->info);
325
+        $this->assertEquals([200, -3], $dir->getQuotaInfo()); //200 used, unlimited
326
+    }
327
+
328
+    public function testGetQuotaInfoSpecific(): void {
329
+        $this->createUser('user', 'password');
330
+        self::loginAsUser('user');
331
+        $mountPoint = $this->createMock(IMountPoint::class);
332
+        $storage = $this->createMock(Quota::class);
333
+        $mountPoint->method('getStorage')
334
+            ->willReturn($storage);
335
+
336
+        $storage->expects($this->any())
337
+            ->method('instanceOfStorage')
338
+            ->willReturnMap([
339
+                ['\OCA\Files_Sharing\SharedStorage', false],
340
+                ['\OC\Files\Storage\Wrapper\Quota', true],
341
+                [Storage::class, false],
342
+            ]);
343
+
344
+        $storage->expects($this->once())
345
+            ->method('getOwner')
346
+            ->willReturn('user');
347
+
348
+        $storage->expects($this->once())
349
+            ->method('getQuota')
350
+            ->willReturn(1000);
351
+
352
+        $storage->expects($this->once())
353
+            ->method('free_space')
354
+            ->willReturn(800);
355
+
356
+        $this->info->expects($this->once())
357
+            ->method('getSize')
358
+            ->willReturn(200);
359
+
360
+        $this->info->expects($this->once())
361
+            ->method('getMountPoint')
362
+            ->willReturn($mountPoint);
363
+
364
+        $this->info->expects($this->once())
365
+            ->method('getInternalPath')
366
+            ->willReturn('/foo');
367
+
368
+        $mountPoint->method('getMountPoint')
369
+            ->willReturn('/user/files/mymountpoint');
370
+
371
+        $this->view->expects($this->any())
372
+            ->method('getRelativePath')
373
+            ->willReturn('/foo');
374
+
375
+        $dir = new Directory($this->view, $this->info);
376
+        $this->assertEquals([200, 800], $dir->getQuotaInfo()); //200 used, 800 free
377
+    }
378
+
379
+    #[\PHPUnit\Framework\Attributes\DataProvider('moveFailedProvider')]
380
+    public function testMoveFailed(string $source, string $destination, array $updatables, array $deletables): void {
381
+        $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
382
+
383
+        $this->moveTest($source, $destination, $updatables, $deletables);
384
+    }
385
+
386
+    #[\PHPUnit\Framework\Attributes\DataProvider('moveSuccessProvider')]
387
+    public function testMoveSuccess(string $source, string $destination, array $updatables, array $deletables): void {
388
+        $this->moveTest($source, $destination, $updatables, $deletables);
389
+        $this->addToAssertionCount(1);
390
+    }
391
+
392
+    #[\PHPUnit\Framework\Attributes\DataProvider('moveFailedInvalidCharsProvider')]
393
+    public function testMoveFailedInvalidChars(string $source, string $destination, array $updatables, array $deletables): void {
394
+        $this->expectException(InvalidPath::class);
395
+
396
+        $this->moveTest($source, $destination, $updatables, $deletables);
397
+    }
398
+
399
+    public static function moveFailedInvalidCharsProvider(): array {
400
+        return [
401
+            ['a/valid', "a/i\nvalid", ['a' => true, 'a/valid' => true, 'a/c*' => false], []],
402
+        ];
403
+    }
404
+
405
+    public static function moveFailedProvider(): array {
406
+        return [
407
+            ['a/b', 'a/c', ['a' => false, 'a/b' => false, 'a/c' => false], []],
408
+            ['a/b', 'b/b', ['a' => false, 'a/b' => false, 'b' => false, 'b/b' => false], []],
409
+            ['a/b', 'b/b', ['a' => false, 'a/b' => true, 'b' => false, 'b/b' => false], []],
410
+            ['a/b', 'b/b', ['a' => true, 'a/b' => true, 'b' => false, 'b/b' => false], []],
411
+            ['a/b', 'b/b', ['a' => true, 'a/b' => true, 'b' => true, 'b/b' => false], ['a/b' => false]],
412
+            ['a/b', 'a/c', ['a' => false, 'a/b' => true, 'a/c' => false], []],
413
+        ];
414
+    }
415
+
416
+    public static function moveSuccessProvider(): array {
417
+        return [
418
+            ['a/b', 'b/b', ['a' => true, 'a/b' => true, 'b' => true, 'b/b' => false], ['a/b' => true]],
419
+            // older files with special chars can still be renamed to valid names
420
+            ['a/b*', 'b/b', ['a' => true, 'a/b*' => true, 'b' => true, 'b/b' => false], ['a/b*' => true]],
421
+        ];
422
+    }
423
+
424
+    private function moveTest(string $source, string $destination, array $updatables, array $deletables): void {
425
+        $view = new TestViewDirectory($updatables, $deletables);
426
+
427
+        $sourceInfo = new FileInfo($source, null, null, [
428
+            'type' => FileInfo::TYPE_FOLDER,
429
+        ], null);
430
+        $targetInfo = new FileInfo(dirname($destination), null, null, [
431
+            'type' => FileInfo::TYPE_FOLDER,
432
+        ], null);
433
+
434
+        $sourceNode = new Directory($view, $sourceInfo);
435
+        $targetNode = $this->getMockBuilder(Directory::class)
436
+            ->onlyMethods(['childExists'])
437
+            ->setConstructorArgs([$view, $targetInfo])
438
+            ->getMock();
439
+        $targetNode->expects($this->any())->method('childExists')
440
+            ->with(basename($destination))
441
+            ->willReturn(false);
442
+        $this->assertTrue($targetNode->moveInto(basename($destination), $source, $sourceNode));
443
+    }
444
+
445
+
446
+    public function testFailingMove(): void {
447
+        $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
448
+        $this->expectExceptionMessage('Could not copy directory b, target exists');
449
+
450
+        $source = 'a/b';
451
+        $destination = 'c/b';
452
+        $updatables = ['a' => true, 'a/b' => true, 'b' => true, 'c/b' => false];
453
+        $deletables = ['a/b' => true];
454
+
455
+        $view = new TestViewDirectory($updatables, $deletables);
456
+
457
+        $sourceInfo = new FileInfo($source, null, null, ['type' => FileInfo::TYPE_FOLDER], null);
458
+        $targetInfo = new FileInfo(dirname($destination), null, null, ['type' => FileInfo::TYPE_FOLDER], null);
459
+
460
+        $sourceNode = new Directory($view, $sourceInfo);
461
+        $targetNode = $this->getMockBuilder(Directory::class)
462
+            ->onlyMethods(['childExists'])
463
+            ->setConstructorArgs([$view, $targetInfo])
464
+            ->getMock();
465
+        $targetNode->expects($this->once())->method('childExists')
466
+            ->with(basename($destination))
467
+            ->willReturn(true);
468
+
469
+        $targetNode->moveInto(basename($destination), $source, $sourceNode);
470
+    }
471 471
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/ServerFactory.php 2 patches
Indentation   +213 added lines, -213 removed lines patch added patch discarded remove patch
@@ -47,237 +47,237 @@
 block discarded – undo
47 47
 
48 48
 class ServerFactory {
49 49
 
50
-	public function __construct(
51
-		private IConfig $config,
52
-		private LoggerInterface $logger,
53
-		private IDBConnection $databaseConnection,
54
-		private IUserSession $userSession,
55
-		private IMountManager $mountManager,
56
-		private ITagManager $tagManager,
57
-		private IRequest $request,
58
-		private IPreview $previewManager,
59
-		private IEventDispatcher $eventDispatcher,
60
-		private IL10N $l10n,
61
-	) {
62
-	}
50
+    public function __construct(
51
+        private IConfig $config,
52
+        private LoggerInterface $logger,
53
+        private IDBConnection $databaseConnection,
54
+        private IUserSession $userSession,
55
+        private IMountManager $mountManager,
56
+        private ITagManager $tagManager,
57
+        private IRequest $request,
58
+        private IPreview $previewManager,
59
+        private IEventDispatcher $eventDispatcher,
60
+        private IL10N $l10n,
61
+    ) {
62
+    }
63 63
 
64
-	/**
65
-	 * @param callable $viewCallBack callback that should return the view for the dav endpoint
66
-	 */
67
-	public function createServer(
68
-		bool $isPublicShare,
69
-		string $baseUri,
70
-		string $requestUri,
71
-		Plugin $authPlugin,
72
-		callable $viewCallBack,
73
-	): Server {
74
-		// /public.php/webdav/ shows the files in the share in the root itself
75
-		// and not under /public.php/webdav/files/{token} so we should keep
76
-		// compatibility for that.
77
-		$needsSharesInRoot = $baseUri === '/public.php/webdav/';
78
-		$useCollection = $isPublicShare && !$needsSharesInRoot;
79
-		$debugEnabled = $this->config->getSystemValue('debug', false);
80
-		[$tree, $rootCollection] = $this->getTree($useCollection);
81
-		$server = new Server($tree);
82
-		// Set URL explicitly due to reverse-proxy situations
83
-		$server->httpRequest->setUrl($requestUri);
84
-		$server->setBaseUri($baseUri);
64
+    /**
65
+     * @param callable $viewCallBack callback that should return the view for the dav endpoint
66
+     */
67
+    public function createServer(
68
+        bool $isPublicShare,
69
+        string $baseUri,
70
+        string $requestUri,
71
+        Plugin $authPlugin,
72
+        callable $viewCallBack,
73
+    ): Server {
74
+        // /public.php/webdav/ shows the files in the share in the root itself
75
+        // and not under /public.php/webdav/files/{token} so we should keep
76
+        // compatibility for that.
77
+        $needsSharesInRoot = $baseUri === '/public.php/webdav/';
78
+        $useCollection = $isPublicShare && !$needsSharesInRoot;
79
+        $debugEnabled = $this->config->getSystemValue('debug', false);
80
+        [$tree, $rootCollection] = $this->getTree($useCollection);
81
+        $server = new Server($tree);
82
+        // Set URL explicitly due to reverse-proxy situations
83
+        $server->httpRequest->setUrl($requestUri);
84
+        $server->setBaseUri($baseUri);
85 85
 
86
-		// Load plugins
87
-		$server->addPlugin(new MaintenancePlugin($this->config, $this->l10n));
88
-		$server->addPlugin(new BlockLegacyClientPlugin(
89
-			$this->config,
90
-			\OCP\Server::get(ThemingDefaults::class),
91
-		));
92
-		$server->addPlugin(new AnonymousOptionsPlugin());
93
-		$server->addPlugin($authPlugin);
94
-		if ($debugEnabled) {
95
-			$server->debugEnabled = $debugEnabled;
96
-			$server->addPlugin(new PropFindMonitorPlugin());
97
-		}
86
+        // Load plugins
87
+        $server->addPlugin(new MaintenancePlugin($this->config, $this->l10n));
88
+        $server->addPlugin(new BlockLegacyClientPlugin(
89
+            $this->config,
90
+            \OCP\Server::get(ThemingDefaults::class),
91
+        ));
92
+        $server->addPlugin(new AnonymousOptionsPlugin());
93
+        $server->addPlugin($authPlugin);
94
+        if ($debugEnabled) {
95
+            $server->debugEnabled = $debugEnabled;
96
+            $server->addPlugin(new PropFindMonitorPlugin());
97
+        }
98 98
 
99
-		$server->addPlugin(new PropFindPreloadNotifyPlugin());
100
-		// FIXME: The following line is a workaround for legacy components relying on being able to send a GET to /
101
-		$server->addPlugin(new DummyGetResponsePlugin());
102
-		$server->addPlugin(new ExceptionLoggerPlugin('webdav', $this->logger));
103
-		$server->addPlugin(new LockPlugin());
99
+        $server->addPlugin(new PropFindPreloadNotifyPlugin());
100
+        // FIXME: The following line is a workaround for legacy components relying on being able to send a GET to /
101
+        $server->addPlugin(new DummyGetResponsePlugin());
102
+        $server->addPlugin(new ExceptionLoggerPlugin('webdav', $this->logger));
103
+        $server->addPlugin(new LockPlugin());
104 104
 
105
-		$server->addPlugin(new RequestIdHeaderPlugin($this->request));
105
+        $server->addPlugin(new RequestIdHeaderPlugin($this->request));
106 106
 
107
-		$server->addPlugin(new ZipFolderPlugin(
108
-			$tree,
109
-			$this->logger,
110
-			$this->eventDispatcher,
111
-			\OCP\Server::get(IDateTimeZone::class),
112
-		));
107
+        $server->addPlugin(new ZipFolderPlugin(
108
+            $tree,
109
+            $this->logger,
110
+            $this->eventDispatcher,
111
+            \OCP\Server::get(IDateTimeZone::class),
112
+        ));
113 113
 
114
-		// Some WebDAV clients do require Class 2 WebDAV support (locking), since
115
-		// we do not provide locking we emulate it using a fake locking plugin.
116
-		if ($this->request->isUserAgent([
117
-			'/WebDAVFS/',
118
-			'/OneNote/',
119
-			'/Microsoft-WebDAV-MiniRedir/',
120
-		])) {
121
-			$server->addPlugin(new FakeLockerPlugin());
122
-		}
114
+        // Some WebDAV clients do require Class 2 WebDAV support (locking), since
115
+        // we do not provide locking we emulate it using a fake locking plugin.
116
+        if ($this->request->isUserAgent([
117
+            '/WebDAVFS/',
118
+            '/OneNote/',
119
+            '/Microsoft-WebDAV-MiniRedir/',
120
+        ])) {
121
+            $server->addPlugin(new FakeLockerPlugin());
122
+        }
123 123
 
124
-		if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) {
125
-			$server->addPlugin(new BrowserErrorPagePlugin());
126
-		}
124
+        if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) {
125
+            $server->addPlugin(new BrowserErrorPagePlugin());
126
+        }
127 127
 
128
-		// wait with registering these until auth is handled and the filesystem is setup
129
-		$server->on('beforeMethod:*', function () use ($server,
130
-			$tree, $viewCallBack, $isPublicShare, $rootCollection, $debugEnabled): void {
131
-			// ensure the skeleton is copied
132
-			$userFolder = \OC::$server->getUserFolder();
128
+        // wait with registering these until auth is handled and the filesystem is setup
129
+        $server->on('beforeMethod:*', function () use ($server,
130
+            $tree, $viewCallBack, $isPublicShare, $rootCollection, $debugEnabled): void {
131
+            // ensure the skeleton is copied
132
+            $userFolder = \OC::$server->getUserFolder();
133 133
 
134
-			/** @var View $view */
135
-			$view = $viewCallBack($server);
136
-			if ($userFolder instanceof Folder && $userFolder->getPath() === $view->getRoot()) {
137
-				$rootInfo = $userFolder;
138
-			} else {
139
-				$rootInfo = $view->getFileInfo('');
140
-			}
134
+            /** @var View $view */
135
+            $view = $viewCallBack($server);
136
+            if ($userFolder instanceof Folder && $userFolder->getPath() === $view->getRoot()) {
137
+                $rootInfo = $userFolder;
138
+            } else {
139
+                $rootInfo = $view->getFileInfo('');
140
+            }
141 141
 
142
-			// Create Nextcloud Dir
143
-			if ($rootInfo->getType() === 'dir') {
144
-				$root = new Directory($view, $rootInfo, $tree);
145
-			} else {
146
-				$root = new File($view, $rootInfo);
147
-			}
142
+            // Create Nextcloud Dir
143
+            if ($rootInfo->getType() === 'dir') {
144
+                $root = new Directory($view, $rootInfo, $tree);
145
+            } else {
146
+                $root = new File($view, $rootInfo);
147
+            }
148 148
 
149
-			if ($rootCollection !== null) {
150
-				$this->initRootCollection($rootCollection, $root);
151
-			} else {
152
-				/** @var ObjectTree $tree */
153
-				$tree->init($root, $view, $this->mountManager);
154
-			}
149
+            if ($rootCollection !== null) {
150
+                $this->initRootCollection($rootCollection, $root);
151
+            } else {
152
+                /** @var ObjectTree $tree */
153
+                $tree->init($root, $view, $this->mountManager);
154
+            }
155 155
 
156
-			$server->addPlugin(
157
-				new FilesPlugin(
158
-					$tree,
159
-					$this->config,
160
-					$this->request,
161
-					$this->previewManager,
162
-					$this->userSession,
163
-					\OCP\Server::get(IFilenameValidator::class),
164
-					\OCP\Server::get(IAccountManager::class),
165
-					$isPublicShare,
166
-					!$debugEnabled
167
-				)
168
-			);
169
-			$server->addPlugin(new QuotaPlugin($view));
170
-			$server->addPlugin(new ChecksumUpdatePlugin());
156
+            $server->addPlugin(
157
+                new FilesPlugin(
158
+                    $tree,
159
+                    $this->config,
160
+                    $this->request,
161
+                    $this->previewManager,
162
+                    $this->userSession,
163
+                    \OCP\Server::get(IFilenameValidator::class),
164
+                    \OCP\Server::get(IAccountManager::class),
165
+                    $isPublicShare,
166
+                    !$debugEnabled
167
+                )
168
+            );
169
+            $server->addPlugin(new QuotaPlugin($view));
170
+            $server->addPlugin(new ChecksumUpdatePlugin());
171 171
 
172
-			// Allow view-only plugin for webdav requests
173
-			$server->addPlugin(new ViewOnlyPlugin(
174
-				$userFolder,
175
-			));
172
+            // Allow view-only plugin for webdav requests
173
+            $server->addPlugin(new ViewOnlyPlugin(
174
+                $userFolder,
175
+            ));
176 176
 
177
-			if ($this->userSession->isLoggedIn()) {
178
-				$server->addPlugin(new TagsPlugin($tree, $this->tagManager, $this->eventDispatcher, $this->userSession));
179
-				$server->addPlugin(new SharesPlugin(
180
-					$tree,
181
-					$this->userSession,
182
-					$userFolder,
183
-					\OCP\Server::get(\OCP\Share\IManager::class)
184
-				));
185
-				$server->addPlugin(new CommentPropertiesPlugin(\OCP\Server::get(ICommentsManager::class), $this->userSession));
186
-				$server->addPlugin(new FilesReportPlugin(
187
-					$tree,
188
-					$view,
189
-					\OCP\Server::get(ISystemTagManager::class),
190
-					\OCP\Server::get(ISystemTagObjectMapper::class),
191
-					\OCP\Server::get(ITagManager::class),
192
-					$this->userSession,
193
-					\OCP\Server::get(IGroupManager::class),
194
-					$userFolder,
195
-					\OCP\Server::get(IAppManager::class)
196
-				));
197
-				// custom properties plugin must be the last one
198
-				$server->addPlugin(
199
-					new \Sabre\DAV\PropertyStorage\Plugin(
200
-						new CustomPropertiesBackend(
201
-							$server,
202
-							$tree,
203
-							$this->databaseConnection,
204
-							$this->userSession->getUser(),
205
-							\OCP\Server::get(PropertyMapper::class),
206
-							\OCP\Server::get(DefaultCalendarValidator::class),
207
-						)
208
-					)
209
-				);
210
-			}
211
-			$server->addPlugin(new CopyEtagHeaderPlugin());
177
+            if ($this->userSession->isLoggedIn()) {
178
+                $server->addPlugin(new TagsPlugin($tree, $this->tagManager, $this->eventDispatcher, $this->userSession));
179
+                $server->addPlugin(new SharesPlugin(
180
+                    $tree,
181
+                    $this->userSession,
182
+                    $userFolder,
183
+                    \OCP\Server::get(\OCP\Share\IManager::class)
184
+                ));
185
+                $server->addPlugin(new CommentPropertiesPlugin(\OCP\Server::get(ICommentsManager::class), $this->userSession));
186
+                $server->addPlugin(new FilesReportPlugin(
187
+                    $tree,
188
+                    $view,
189
+                    \OCP\Server::get(ISystemTagManager::class),
190
+                    \OCP\Server::get(ISystemTagObjectMapper::class),
191
+                    \OCP\Server::get(ITagManager::class),
192
+                    $this->userSession,
193
+                    \OCP\Server::get(IGroupManager::class),
194
+                    $userFolder,
195
+                    \OCP\Server::get(IAppManager::class)
196
+                ));
197
+                // custom properties plugin must be the last one
198
+                $server->addPlugin(
199
+                    new \Sabre\DAV\PropertyStorage\Plugin(
200
+                        new CustomPropertiesBackend(
201
+                            $server,
202
+                            $tree,
203
+                            $this->databaseConnection,
204
+                            $this->userSession->getUser(),
205
+                            \OCP\Server::get(PropertyMapper::class),
206
+                            \OCP\Server::get(DefaultCalendarValidator::class),
207
+                        )
208
+                    )
209
+                );
210
+            }
211
+            $server->addPlugin(new CopyEtagHeaderPlugin());
212 212
 
213
-			// Load dav plugins from apps
214
-			$event = new SabrePluginEvent($server);
215
-			$this->eventDispatcher->dispatchTyped($event);
216
-			$pluginManager = new PluginManager(
217
-				\OC::$server,
218
-				\OCP\Server::get(IAppManager::class)
219
-			);
220
-			foreach ($pluginManager->getAppPlugins() as $appPlugin) {
221
-				$server->addPlugin($appPlugin);
222
-			}
223
-		}, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request
224
-		return $server;
225
-	}
213
+            // Load dav plugins from apps
214
+            $event = new SabrePluginEvent($server);
215
+            $this->eventDispatcher->dispatchTyped($event);
216
+            $pluginManager = new PluginManager(
217
+                \OC::$server,
218
+                \OCP\Server::get(IAppManager::class)
219
+            );
220
+            foreach ($pluginManager->getAppPlugins() as $appPlugin) {
221
+                $server->addPlugin($appPlugin);
222
+            }
223
+        }, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request
224
+        return $server;
225
+    }
226 226
 
227
-	/**
228
-	 * Returns a Tree object and, if $useCollection is true, the collection used
229
-	 * as root.
230
-	 *
231
-	 * @param bool $useCollection Whether to use a collection or the legacy
232
-	 *                            ObjectTree, which doesn't use collections.
233
-	 * @return array{0: CachingTree|ObjectTree, 1: SimpleCollection|null}
234
-	 */
235
-	public function getTree(bool $useCollection): array {
236
-		if ($useCollection) {
237
-			$rootCollection = new SimpleCollection('root');
238
-			$tree = new CachingTree($rootCollection);
239
-			return [$tree, $rootCollection];
240
-		}
227
+    /**
228
+     * Returns a Tree object and, if $useCollection is true, the collection used
229
+     * as root.
230
+     *
231
+     * @param bool $useCollection Whether to use a collection or the legacy
232
+     *                            ObjectTree, which doesn't use collections.
233
+     * @return array{0: CachingTree|ObjectTree, 1: SimpleCollection|null}
234
+     */
235
+    public function getTree(bool $useCollection): array {
236
+        if ($useCollection) {
237
+            $rootCollection = new SimpleCollection('root');
238
+            $tree = new CachingTree($rootCollection);
239
+            return [$tree, $rootCollection];
240
+        }
241 241
 
242
-		return [new ObjectTree(), null];
243
-	}
242
+        return [new ObjectTree(), null];
243
+    }
244 244
 
245
-	/**
246
-	 * Adds the user's principal backend to $rootCollection.
247
-	 */
248
-	private function initRootCollection(SimpleCollection $rootCollection, Directory|File $root): void {
249
-		$userPrincipalBackend = new Principal(
250
-			\OCP\Server::get(IUserManager::class),
251
-			\OCP\Server::get(IGroupManager::class),
252
-			\OCP\Server::get(IAccountManager::class),
253
-			\OCP\Server::get(\OCP\Share\IManager::class),
254
-			\OCP\Server::get(IUserSession::class),
255
-			\OCP\Server::get(IAppManager::class),
256
-			\OCP\Server::get(ProxyMapper::class),
257
-			\OCP\Server::get(KnownUserService::class),
258
-			\OCP\Server::get(IConfig::class),
259
-			\OCP\Server::get(IFactory::class),
260
-		);
245
+    /**
246
+     * Adds the user's principal backend to $rootCollection.
247
+     */
248
+    private function initRootCollection(SimpleCollection $rootCollection, Directory|File $root): void {
249
+        $userPrincipalBackend = new Principal(
250
+            \OCP\Server::get(IUserManager::class),
251
+            \OCP\Server::get(IGroupManager::class),
252
+            \OCP\Server::get(IAccountManager::class),
253
+            \OCP\Server::get(\OCP\Share\IManager::class),
254
+            \OCP\Server::get(IUserSession::class),
255
+            \OCP\Server::get(IAppManager::class),
256
+            \OCP\Server::get(ProxyMapper::class),
257
+            \OCP\Server::get(KnownUserService::class),
258
+            \OCP\Server::get(IConfig::class),
259
+            \OCP\Server::get(IFactory::class),
260
+        );
261 261
 
262
-		// Mount the share collection at /public.php/dav/files/<share token>
263
-		$rootCollection->addChild(
264
-			new RootCollection(
265
-				$root,
266
-				$userPrincipalBackend,
267
-				'principals/shares',
268
-			)
269
-		);
262
+        // Mount the share collection at /public.php/dav/files/<share token>
263
+        $rootCollection->addChild(
264
+            new RootCollection(
265
+                $root,
266
+                $userPrincipalBackend,
267
+                'principals/shares',
268
+            )
269
+        );
270 270
 
271
-		// Mount the upload collection at /public.php/dav/uploads/<share token>
272
-		$rootCollection->addChild(
273
-			new \OCA\DAV\Upload\RootCollection(
274
-				$userPrincipalBackend,
275
-				'principals/shares',
276
-				\OCP\Server::get(CleanupService::class),
277
-				\OCP\Server::get(IRootFolder::class),
278
-				\OCP\Server::get(IUserSession::class),
279
-				\OCP\Server::get(\OCP\Share\IManager::class),
280
-			)
281
-		);
282
-	}
271
+        // Mount the upload collection at /public.php/dav/uploads/<share token>
272
+        $rootCollection->addChild(
273
+            new \OCA\DAV\Upload\RootCollection(
274
+                $userPrincipalBackend,
275
+                'principals/shares',
276
+                \OCP\Server::get(CleanupService::class),
277
+                \OCP\Server::get(IRootFolder::class),
278
+                \OCP\Server::get(IUserSession::class),
279
+                \OCP\Server::get(\OCP\Share\IManager::class),
280
+            )
281
+        );
282
+    }
283 283
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
 		}
127 127
 
128 128
 		// wait with registering these until auth is handled and the filesystem is setup
129
-		$server->on('beforeMethod:*', function () use ($server,
129
+		$server->on('beforeMethod:*', function() use ($server,
130 130
 			$tree, $viewCallBack, $isPublicShare, $rootCollection, $debugEnabled): void {
131 131
 			// ensure the skeleton is copied
132 132
 			$userFolder = \OC::$server->getUserFolder();
@@ -245,7 +245,7 @@  discard block
 block discarded – undo
245 245
 	/**
246 246
 	 * Adds the user's principal backend to $rootCollection.
247 247
 	 */
248
-	private function initRootCollection(SimpleCollection $rootCollection, Directory|File $root): void {
248
+	private function initRootCollection(SimpleCollection $rootCollection, Directory | File $root): void {
249 249
 		$userPrincipalBackend = new Principal(
250 250
 			\OCP\Server::get(IUserManager::class),
251 251
 			\OCP\Server::get(IGroupManager::class),
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/Directory.php 1 patch
Indentation   +450 added lines, -450 removed lines patch added patch discarded remove patch
@@ -40,454 +40,454 @@
 block discarded – undo
40 40
 use Sabre\DAV\INode;
41 41
 
42 42
 class Directory extends Node implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota, \Sabre\DAV\IMoveTarget, \Sabre\DAV\ICopyTarget {
43
-	/**
44
-	 * Cached directory content
45
-	 * @var FileInfo[]
46
-	 */
47
-	private ?array $dirContent = null;
48
-
49
-	/** Cached quota info */
50
-	private ?array $quotaInfo = null;
51
-
52
-	/**
53
-	 * Sets up the node, expects a full path name
54
-	 */
55
-	public function __construct(
56
-		View $view,
57
-		FileInfo $info,
58
-		private ?CachingTree $tree = null,
59
-		?IShareManager $shareManager = null,
60
-	) {
61
-		parent::__construct($view, $info, $shareManager);
62
-	}
63
-
64
-	/**
65
-	 * Creates a new file in the directory
66
-	 *
67
-	 * Data will either be supplied as a stream resource, or in certain cases
68
-	 * as a string. Keep in mind that you may have to support either.
69
-	 *
70
-	 * After successful creation of the file, you may choose to return the ETag
71
-	 * of the new file here.
72
-	 *
73
-	 * The returned ETag must be surrounded by double-quotes (The quotes should
74
-	 * be part of the actual string).
75
-	 *
76
-	 * If you cannot accurately determine the ETag, you should not return it.
77
-	 * If you don't store the file exactly as-is (you're transforming it
78
-	 * somehow) you should also not return an ETag.
79
-	 *
80
-	 * This means that if a subsequent GET to this new file does not exactly
81
-	 * return the same contents of what was submitted here, you are strongly
82
-	 * recommended to omit the ETag.
83
-	 *
84
-	 * @param string $name Name of the file
85
-	 * @param resource|string $data Initial payload
86
-	 * @return null|string
87
-	 * @throws Exception\EntityTooLarge
88
-	 * @throws Exception\UnsupportedMediaType
89
-	 * @throws FileLocked
90
-	 * @throws InvalidPath
91
-	 * @throws \Sabre\DAV\Exception
92
-	 * @throws \Sabre\DAV\Exception\BadRequest
93
-	 * @throws \Sabre\DAV\Exception\Forbidden
94
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
95
-	 */
96
-	public function createFile($name, $data = null) {
97
-		try {
98
-			if (!$this->fileView->isCreatable($this->path)) {
99
-				throw new \Sabre\DAV\Exception\Forbidden();
100
-			}
101
-
102
-			$this->fileView->verifyPath($this->path, $name);
103
-
104
-			$path = $this->fileView->getAbsolutePath($this->path) . '/' . $name;
105
-			// in case the file already exists/overwriting
106
-			$info = $this->fileView->getFileInfo($this->path . '/' . $name);
107
-			if (!$info) {
108
-				// use a dummy FileInfo which is acceptable here since it will be refreshed after the put is complete
109
-				$info = new \OC\Files\FileInfo($path, null, null, [
110
-					'type' => FileInfo::TYPE_FILE
111
-				], null);
112
-			}
113
-			$node = new File($this->fileView, $info);
114
-
115
-			// only allow 1 process to upload a file at once but still allow reading the file while writing the part file
116
-			$node->acquireLock(ILockingProvider::LOCK_SHARED);
117
-			$this->fileView->lockFile($this->path . '/' . $name . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
118
-
119
-			$result = $node->put($data);
120
-
121
-			$this->fileView->unlockFile($this->path . '/' . $name . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
122
-			$node->releaseLock(ILockingProvider::LOCK_SHARED);
123
-			return $result;
124
-		} catch (StorageNotAvailableException $e) {
125
-			throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), $e->getCode(), $e);
126
-		} catch (InvalidPathException $ex) {
127
-			throw new InvalidPath($ex->getMessage(), false, $ex);
128
-		} catch (ForbiddenException $ex) {
129
-			throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
130
-		} catch (LockedException $e) {
131
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
132
-		}
133
-	}
134
-
135
-	/**
136
-	 * Creates a new subdirectory
137
-	 *
138
-	 * @param string $name
139
-	 * @throws FileLocked
140
-	 * @throws InvalidPath
141
-	 * @throws \Sabre\DAV\Exception\Forbidden
142
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
143
-	 */
144
-	public function createDirectory($name) {
145
-		try {
146
-			if (!$this->info->isCreatable()) {
147
-				throw new \Sabre\DAV\Exception\Forbidden();
148
-			}
149
-
150
-			$this->fileView->verifyPath($this->path, $name);
151
-			$newPath = $this->path . '/' . $name;
152
-			if (!$this->fileView->mkdir($newPath)) {
153
-				throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath);
154
-			}
155
-		} catch (StorageNotAvailableException $e) {
156
-			throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), 0, $e);
157
-		} catch (InvalidPathException $ex) {
158
-			throw new InvalidPath($ex->getMessage(), false, $ex);
159
-		} catch (ForbiddenException $ex) {
160
-			throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
161
-		} catch (LockedException $e) {
162
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
163
-		}
164
-	}
165
-
166
-	/**
167
-	 * Returns a specific child node, referenced by its name
168
-	 *
169
-	 * @param string $name
170
-	 * @param FileInfo $info
171
-	 * @return \Sabre\DAV\INode
172
-	 * @throws InvalidPath
173
-	 * @throws \Sabre\DAV\Exception\NotFound
174
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
175
-	 */
176
-	public function getChild($name, $info = null, ?IRequest $request = null, ?IL10N $l10n = null) {
177
-		$storage = $this->info->getStorage();
178
-		$allowDirectory = false;
179
-
180
-		// Checking if we're in a file drop
181
-		// If we are, then only PUT and MKCOL are allowed (see plugin)
182
-		// so we are safe to return the directory without a risk of
183
-		// leaking files and folders structure.
184
-		if ($storage->instanceOfStorage(PublicShareWrapper::class)) {
185
-			$share = $storage->getShare();
186
-			$allowDirectory = ($share->getPermissions() & Constants::PERMISSION_READ) !== Constants::PERMISSION_READ;
187
-		}
188
-
189
-		// For file drop we need to be allowed to read the directory with the nickname
190
-		if (!$allowDirectory && !$this->info->isReadable()) {
191
-			// avoid detecting files through this way
192
-			throw new NotFound();
193
-		}
194
-
195
-		$path = $this->path . '/' . $name;
196
-		if (is_null($info)) {
197
-			try {
198
-				$this->fileView->verifyPath($this->path, $name, true);
199
-				$info = $this->fileView->getFileInfo($path);
200
-			} catch (StorageNotAvailableException $e) {
201
-				throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), 0, $e);
202
-			} catch (InvalidPathException $ex) {
203
-				throw new InvalidPath($ex->getMessage(), false, $ex);
204
-			} catch (ForbiddenException $e) {
205
-				throw new \Sabre\DAV\Exception\Forbidden($e->getMessage(), $e->getCode(), $e);
206
-			}
207
-		}
208
-
209
-		if (!$info) {
210
-			throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
211
-		}
212
-
213
-		if ($info->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
214
-			$node = new Directory($this->fileView, $info, $this->tree, $this->shareManager);
215
-		} else {
216
-			// In case reading a directory was allowed but it turns out the node was a not a directory, reject it now.
217
-			if (!$this->info->isReadable()) {
218
-				throw new NotFound();
219
-			}
220
-
221
-			$node = new File($this->fileView, $info, $this->shareManager, $request, $l10n);
222
-		}
223
-		if ($this->tree) {
224
-			$this->tree->cacheNode($node);
225
-		}
226
-		return $node;
227
-	}
228
-
229
-	/**
230
-	 * Returns an array with all the child nodes
231
-	 *
232
-	 * @return \Sabre\DAV\INode[]
233
-	 * @throws \Sabre\DAV\Exception\Locked
234
-	 * @throws Forbidden
235
-	 */
236
-	public function getChildren() {
237
-		if (!is_null($this->dirContent)) {
238
-			return $this->dirContent;
239
-		}
240
-		try {
241
-			if (!$this->info->isReadable()) {
242
-				// return 403 instead of 404 because a 404 would make
243
-				// the caller believe that the collection itself does not exist
244
-				if (Server::get(IAppManager::class)->isEnabledForAnyone('files_accesscontrol')) {
245
-					throw new Forbidden('No read permissions. This might be caused by files_accesscontrol, check your configured rules');
246
-				} else {
247
-					throw new Forbidden('No read permissions');
248
-				}
249
-			}
250
-			$folderContent = $this->getNode()->getDirectoryListing();
251
-		} catch (LockedException $e) {
252
-			throw new Locked();
253
-		}
254
-
255
-		$nodes = [];
256
-		$request = Server::get(IRequest::class);
257
-		$l10nFactory = Server::get(IFactory::class);
258
-		$l10n = $l10nFactory->get(Application::APP_ID);
259
-		foreach ($folderContent as $info) {
260
-			$node = $this->getChild($info->getName(), $info, $request, $l10n);
261
-			$nodes[] = $node;
262
-		}
263
-		$this->dirContent = $nodes;
264
-		return $this->dirContent;
265
-	}
266
-
267
-	/**
268
-	 * Checks if a child exists.
269
-	 *
270
-	 * @param string $name
271
-	 * @return bool
272
-	 */
273
-	public function childExists($name) {
274
-		// note: here we do NOT resolve the chunk file name to the real file name
275
-		// to make sure we return false when checking for file existence with a chunk
276
-		// file name.
277
-		// This is to make sure that "createFile" is still triggered
278
-		// (required old code) instead of "updateFile".
279
-		//
280
-		// TODO: resolve chunk file name here and implement "updateFile"
281
-		$path = $this->path . '/' . $name;
282
-		return $this->fileView->file_exists($path);
283
-	}
284
-
285
-	/**
286
-	 * Deletes all files in this directory, and then itself
287
-	 *
288
-	 * @return void
289
-	 * @throws FileLocked
290
-	 * @throws \Sabre\DAV\Exception\Forbidden
291
-	 */
292
-	public function delete() {
293
-		if ($this->path === '' || $this->path === '/' || !$this->info->isDeletable()) {
294
-			throw new \Sabre\DAV\Exception\Forbidden();
295
-		}
296
-
297
-		try {
298
-			if (!$this->fileView->rmdir($this->path)) {
299
-				// assume it wasn't possible to remove due to permission issue
300
-				throw new \Sabre\DAV\Exception\Forbidden();
301
-			}
302
-		} catch (ForbiddenException $ex) {
303
-			throw new Forbidden($ex->getMessage(), $ex->getRetry());
304
-		} catch (LockedException $e) {
305
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
306
-		}
307
-	}
308
-
309
-	private function getLogger(): LoggerInterface {
310
-		return Server::get(LoggerInterface::class);
311
-	}
312
-
313
-	/**
314
-	 * Returns available diskspace information
315
-	 *
316
-	 * @return array
317
-	 */
318
-	public function getQuotaInfo() {
319
-		if ($this->quotaInfo) {
320
-			return $this->quotaInfo;
321
-		}
322
-		$relativePath = $this->fileView->getRelativePath($this->info->getPath());
323
-		if ($relativePath === null) {
324
-			$this->getLogger()->warning('error while getting quota as the relative path cannot be found');
325
-			return [0, 0];
326
-		}
327
-
328
-		try {
329
-			$storageInfo = \OC_Helper::getStorageInfo($relativePath, $this->info, false);
330
-			if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) {
331
-				$free = FileInfo::SPACE_UNLIMITED;
332
-			} else {
333
-				$free = $storageInfo['free'];
334
-			}
335
-			$this->quotaInfo = [
336
-				$storageInfo['used'],
337
-				$free
338
-			];
339
-			return $this->quotaInfo;
340
-		} catch (NotFoundException $e) {
341
-			$this->getLogger()->warning('error while getting quota into', ['exception' => $e]);
342
-			return [0, 0];
343
-		} catch (StorageNotAvailableException $e) {
344
-			$this->getLogger()->warning('error while getting quota into', ['exception' => $e]);
345
-			return [0, 0];
346
-		} catch (NotPermittedException $e) {
347
-			$this->getLogger()->warning('error while getting quota into', ['exception' => $e]);
348
-			return [0, 0];
349
-		}
350
-	}
351
-
352
-	/**
353
-	 * Moves a node into this collection.
354
-	 *
355
-	 * It is up to the implementors to:
356
-	 *   1. Create the new resource.
357
-	 *   2. Remove the old resource.
358
-	 *   3. Transfer any properties or other data.
359
-	 *
360
-	 * Generally you should make very sure that your collection can easily move
361
-	 * the move.
362
-	 *
363
-	 * If you don't, just return false, which will trigger sabre/dav to handle
364
-	 * the move itself. If you return true from this function, the assumption
365
-	 * is that the move was successful.
366
-	 *
367
-	 * @param string $targetName New local file/collection name.
368
-	 * @param string $fullSourcePath Full path to source node
369
-	 * @param INode $sourceNode Source node itself
370
-	 * @return bool
371
-	 * @throws BadRequest
372
-	 * @throws ServiceUnavailable
373
-	 * @throws Forbidden
374
-	 * @throws FileLocked
375
-	 * @throws \Sabre\DAV\Exception\Forbidden
376
-	 */
377
-	public function moveInto($targetName, $fullSourcePath, INode $sourceNode) {
378
-		if (!$sourceNode instanceof Node) {
379
-			// it's a file of another kind, like FutureFile
380
-			if ($sourceNode instanceof IFile) {
381
-				// fallback to default copy+delete handling
382
-				return false;
383
-			}
384
-			throw new BadRequest('Incompatible node types');
385
-		}
386
-
387
-		$destinationPath = $this->getPath() . '/' . $targetName;
388
-
389
-
390
-		$targetNodeExists = $this->childExists($targetName);
391
-
392
-		// at getNodeForPath we also check the path for isForbiddenFileOrDir
393
-		// with that we have covered both source and destination
394
-		if ($sourceNode instanceof Directory && $targetNodeExists) {
395
-			throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
396
-		}
397
-
398
-		[$sourceDir,] = \Sabre\Uri\split($sourceNode->getPath());
399
-		$destinationDir = $this->getPath();
400
-
401
-		$sourcePath = $sourceNode->getPath();
402
-
403
-		$isMovableMount = false;
404
-		$sourceMount = Server::get(IMountManager::class)->find($this->fileView->getAbsolutePath($sourcePath));
405
-		$internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath));
406
-		if ($sourceMount instanceof MoveableMount && $internalPath === '') {
407
-			$isMovableMount = true;
408
-		}
409
-
410
-		try {
411
-			$sameFolder = ($sourceDir === $destinationDir);
412
-			// if we're overwriting or same folder
413
-			if ($targetNodeExists || $sameFolder) {
414
-				// note that renaming a share mount point is always allowed
415
-				if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) {
416
-					throw new \Sabre\DAV\Exception\Forbidden();
417
-				}
418
-			} else {
419
-				if (!$this->fileView->isCreatable($destinationDir)) {
420
-					throw new \Sabre\DAV\Exception\Forbidden();
421
-				}
422
-			}
423
-
424
-			if (!$sameFolder) {
425
-				// moving to a different folder, source will be gone, like a deletion
426
-				// note that moving a share mount point is always allowed
427
-				if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
428
-					throw new \Sabre\DAV\Exception\Forbidden();
429
-				}
430
-			}
431
-
432
-			$fileName = basename($destinationPath);
433
-			try {
434
-				$this->fileView->verifyPath($destinationDir, $fileName);
435
-			} catch (InvalidPathException $ex) {
436
-				throw new InvalidPath($ex->getMessage());
437
-			}
438
-
439
-			$renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
440
-			if (!$renameOkay) {
441
-				throw new \Sabre\DAV\Exception\Forbidden('');
442
-			}
443
-		} catch (StorageNotAvailableException $e) {
444
-			throw new ServiceUnavailable($e->getMessage(), $e->getCode(), $e);
445
-		} catch (ForbiddenException $ex) {
446
-			throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
447
-		} catch (LockedException $e) {
448
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
449
-		}
450
-
451
-		return true;
452
-	}
453
-
454
-
455
-	public function copyInto($targetName, $sourcePath, INode $sourceNode) {
456
-		if ($sourceNode instanceof File || $sourceNode instanceof Directory) {
457
-			try {
458
-				$destinationPath = $this->getPath() . '/' . $targetName;
459
-				$sourcePath = $sourceNode->getPath();
460
-
461
-				if (!$this->fileView->isCreatable($this->getPath())) {
462
-					throw new \Sabre\DAV\Exception\Forbidden();
463
-				}
464
-
465
-				try {
466
-					$this->fileView->verifyPath($this->getPath(), $targetName);
467
-				} catch (InvalidPathException $ex) {
468
-					throw new InvalidPath($ex->getMessage());
469
-				}
470
-
471
-				$copyOkay = $this->fileView->copy($sourcePath, $destinationPath);
472
-
473
-				if (!$copyOkay) {
474
-					throw new \Sabre\DAV\Exception\Forbidden('Copy did not proceed');
475
-				}
476
-
477
-				return true;
478
-			} catch (StorageNotAvailableException $e) {
479
-				throw new ServiceUnavailable($e->getMessage(), $e->getCode(), $e);
480
-			} catch (ForbiddenException $ex) {
481
-				throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
482
-			} catch (LockedException $e) {
483
-				throw new FileLocked($e->getMessage(), $e->getCode(), $e);
484
-			}
485
-		}
486
-
487
-		return false;
488
-	}
489
-
490
-	public function getNode(): Folder {
491
-		return $this->node;
492
-	}
43
+    /**
44
+     * Cached directory content
45
+     * @var FileInfo[]
46
+     */
47
+    private ?array $dirContent = null;
48
+
49
+    /** Cached quota info */
50
+    private ?array $quotaInfo = null;
51
+
52
+    /**
53
+     * Sets up the node, expects a full path name
54
+     */
55
+    public function __construct(
56
+        View $view,
57
+        FileInfo $info,
58
+        private ?CachingTree $tree = null,
59
+        ?IShareManager $shareManager = null,
60
+    ) {
61
+        parent::__construct($view, $info, $shareManager);
62
+    }
63
+
64
+    /**
65
+     * Creates a new file in the directory
66
+     *
67
+     * Data will either be supplied as a stream resource, or in certain cases
68
+     * as a string. Keep in mind that you may have to support either.
69
+     *
70
+     * After successful creation of the file, you may choose to return the ETag
71
+     * of the new file here.
72
+     *
73
+     * The returned ETag must be surrounded by double-quotes (The quotes should
74
+     * be part of the actual string).
75
+     *
76
+     * If you cannot accurately determine the ETag, you should not return it.
77
+     * If you don't store the file exactly as-is (you're transforming it
78
+     * somehow) you should also not return an ETag.
79
+     *
80
+     * This means that if a subsequent GET to this new file does not exactly
81
+     * return the same contents of what was submitted here, you are strongly
82
+     * recommended to omit the ETag.
83
+     *
84
+     * @param string $name Name of the file
85
+     * @param resource|string $data Initial payload
86
+     * @return null|string
87
+     * @throws Exception\EntityTooLarge
88
+     * @throws Exception\UnsupportedMediaType
89
+     * @throws FileLocked
90
+     * @throws InvalidPath
91
+     * @throws \Sabre\DAV\Exception
92
+     * @throws \Sabre\DAV\Exception\BadRequest
93
+     * @throws \Sabre\DAV\Exception\Forbidden
94
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
95
+     */
96
+    public function createFile($name, $data = null) {
97
+        try {
98
+            if (!$this->fileView->isCreatable($this->path)) {
99
+                throw new \Sabre\DAV\Exception\Forbidden();
100
+            }
101
+
102
+            $this->fileView->verifyPath($this->path, $name);
103
+
104
+            $path = $this->fileView->getAbsolutePath($this->path) . '/' . $name;
105
+            // in case the file already exists/overwriting
106
+            $info = $this->fileView->getFileInfo($this->path . '/' . $name);
107
+            if (!$info) {
108
+                // use a dummy FileInfo which is acceptable here since it will be refreshed after the put is complete
109
+                $info = new \OC\Files\FileInfo($path, null, null, [
110
+                    'type' => FileInfo::TYPE_FILE
111
+                ], null);
112
+            }
113
+            $node = new File($this->fileView, $info);
114
+
115
+            // only allow 1 process to upload a file at once but still allow reading the file while writing the part file
116
+            $node->acquireLock(ILockingProvider::LOCK_SHARED);
117
+            $this->fileView->lockFile($this->path . '/' . $name . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
118
+
119
+            $result = $node->put($data);
120
+
121
+            $this->fileView->unlockFile($this->path . '/' . $name . '.upload.part', ILockingProvider::LOCK_EXCLUSIVE);
122
+            $node->releaseLock(ILockingProvider::LOCK_SHARED);
123
+            return $result;
124
+        } catch (StorageNotAvailableException $e) {
125
+            throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), $e->getCode(), $e);
126
+        } catch (InvalidPathException $ex) {
127
+            throw new InvalidPath($ex->getMessage(), false, $ex);
128
+        } catch (ForbiddenException $ex) {
129
+            throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
130
+        } catch (LockedException $e) {
131
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
132
+        }
133
+    }
134
+
135
+    /**
136
+     * Creates a new subdirectory
137
+     *
138
+     * @param string $name
139
+     * @throws FileLocked
140
+     * @throws InvalidPath
141
+     * @throws \Sabre\DAV\Exception\Forbidden
142
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
143
+     */
144
+    public function createDirectory($name) {
145
+        try {
146
+            if (!$this->info->isCreatable()) {
147
+                throw new \Sabre\DAV\Exception\Forbidden();
148
+            }
149
+
150
+            $this->fileView->verifyPath($this->path, $name);
151
+            $newPath = $this->path . '/' . $name;
152
+            if (!$this->fileView->mkdir($newPath)) {
153
+                throw new \Sabre\DAV\Exception\Forbidden('Could not create directory ' . $newPath);
154
+            }
155
+        } catch (StorageNotAvailableException $e) {
156
+            throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), 0, $e);
157
+        } catch (InvalidPathException $ex) {
158
+            throw new InvalidPath($ex->getMessage(), false, $ex);
159
+        } catch (ForbiddenException $ex) {
160
+            throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
161
+        } catch (LockedException $e) {
162
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
163
+        }
164
+    }
165
+
166
+    /**
167
+     * Returns a specific child node, referenced by its name
168
+     *
169
+     * @param string $name
170
+     * @param FileInfo $info
171
+     * @return \Sabre\DAV\INode
172
+     * @throws InvalidPath
173
+     * @throws \Sabre\DAV\Exception\NotFound
174
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
175
+     */
176
+    public function getChild($name, $info = null, ?IRequest $request = null, ?IL10N $l10n = null) {
177
+        $storage = $this->info->getStorage();
178
+        $allowDirectory = false;
179
+
180
+        // Checking if we're in a file drop
181
+        // If we are, then only PUT and MKCOL are allowed (see plugin)
182
+        // so we are safe to return the directory without a risk of
183
+        // leaking files and folders structure.
184
+        if ($storage->instanceOfStorage(PublicShareWrapper::class)) {
185
+            $share = $storage->getShare();
186
+            $allowDirectory = ($share->getPermissions() & Constants::PERMISSION_READ) !== Constants::PERMISSION_READ;
187
+        }
188
+
189
+        // For file drop we need to be allowed to read the directory with the nickname
190
+        if (!$allowDirectory && !$this->info->isReadable()) {
191
+            // avoid detecting files through this way
192
+            throw new NotFound();
193
+        }
194
+
195
+        $path = $this->path . '/' . $name;
196
+        if (is_null($info)) {
197
+            try {
198
+                $this->fileView->verifyPath($this->path, $name, true);
199
+                $info = $this->fileView->getFileInfo($path);
200
+            } catch (StorageNotAvailableException $e) {
201
+                throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), 0, $e);
202
+            } catch (InvalidPathException $ex) {
203
+                throw new InvalidPath($ex->getMessage(), false, $ex);
204
+            } catch (ForbiddenException $e) {
205
+                throw new \Sabre\DAV\Exception\Forbidden($e->getMessage(), $e->getCode(), $e);
206
+            }
207
+        }
208
+
209
+        if (!$info) {
210
+            throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
211
+        }
212
+
213
+        if ($info->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
214
+            $node = new Directory($this->fileView, $info, $this->tree, $this->shareManager);
215
+        } else {
216
+            // In case reading a directory was allowed but it turns out the node was a not a directory, reject it now.
217
+            if (!$this->info->isReadable()) {
218
+                throw new NotFound();
219
+            }
220
+
221
+            $node = new File($this->fileView, $info, $this->shareManager, $request, $l10n);
222
+        }
223
+        if ($this->tree) {
224
+            $this->tree->cacheNode($node);
225
+        }
226
+        return $node;
227
+    }
228
+
229
+    /**
230
+     * Returns an array with all the child nodes
231
+     *
232
+     * @return \Sabre\DAV\INode[]
233
+     * @throws \Sabre\DAV\Exception\Locked
234
+     * @throws Forbidden
235
+     */
236
+    public function getChildren() {
237
+        if (!is_null($this->dirContent)) {
238
+            return $this->dirContent;
239
+        }
240
+        try {
241
+            if (!$this->info->isReadable()) {
242
+                // return 403 instead of 404 because a 404 would make
243
+                // the caller believe that the collection itself does not exist
244
+                if (Server::get(IAppManager::class)->isEnabledForAnyone('files_accesscontrol')) {
245
+                    throw new Forbidden('No read permissions. This might be caused by files_accesscontrol, check your configured rules');
246
+                } else {
247
+                    throw new Forbidden('No read permissions');
248
+                }
249
+            }
250
+            $folderContent = $this->getNode()->getDirectoryListing();
251
+        } catch (LockedException $e) {
252
+            throw new Locked();
253
+        }
254
+
255
+        $nodes = [];
256
+        $request = Server::get(IRequest::class);
257
+        $l10nFactory = Server::get(IFactory::class);
258
+        $l10n = $l10nFactory->get(Application::APP_ID);
259
+        foreach ($folderContent as $info) {
260
+            $node = $this->getChild($info->getName(), $info, $request, $l10n);
261
+            $nodes[] = $node;
262
+        }
263
+        $this->dirContent = $nodes;
264
+        return $this->dirContent;
265
+    }
266
+
267
+    /**
268
+     * Checks if a child exists.
269
+     *
270
+     * @param string $name
271
+     * @return bool
272
+     */
273
+    public function childExists($name) {
274
+        // note: here we do NOT resolve the chunk file name to the real file name
275
+        // to make sure we return false when checking for file existence with a chunk
276
+        // file name.
277
+        // This is to make sure that "createFile" is still triggered
278
+        // (required old code) instead of "updateFile".
279
+        //
280
+        // TODO: resolve chunk file name here and implement "updateFile"
281
+        $path = $this->path . '/' . $name;
282
+        return $this->fileView->file_exists($path);
283
+    }
284
+
285
+    /**
286
+     * Deletes all files in this directory, and then itself
287
+     *
288
+     * @return void
289
+     * @throws FileLocked
290
+     * @throws \Sabre\DAV\Exception\Forbidden
291
+     */
292
+    public function delete() {
293
+        if ($this->path === '' || $this->path === '/' || !$this->info->isDeletable()) {
294
+            throw new \Sabre\DAV\Exception\Forbidden();
295
+        }
296
+
297
+        try {
298
+            if (!$this->fileView->rmdir($this->path)) {
299
+                // assume it wasn't possible to remove due to permission issue
300
+                throw new \Sabre\DAV\Exception\Forbidden();
301
+            }
302
+        } catch (ForbiddenException $ex) {
303
+            throw new Forbidden($ex->getMessage(), $ex->getRetry());
304
+        } catch (LockedException $e) {
305
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
306
+        }
307
+    }
308
+
309
+    private function getLogger(): LoggerInterface {
310
+        return Server::get(LoggerInterface::class);
311
+    }
312
+
313
+    /**
314
+     * Returns available diskspace information
315
+     *
316
+     * @return array
317
+     */
318
+    public function getQuotaInfo() {
319
+        if ($this->quotaInfo) {
320
+            return $this->quotaInfo;
321
+        }
322
+        $relativePath = $this->fileView->getRelativePath($this->info->getPath());
323
+        if ($relativePath === null) {
324
+            $this->getLogger()->warning('error while getting quota as the relative path cannot be found');
325
+            return [0, 0];
326
+        }
327
+
328
+        try {
329
+            $storageInfo = \OC_Helper::getStorageInfo($relativePath, $this->info, false);
330
+            if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) {
331
+                $free = FileInfo::SPACE_UNLIMITED;
332
+            } else {
333
+                $free = $storageInfo['free'];
334
+            }
335
+            $this->quotaInfo = [
336
+                $storageInfo['used'],
337
+                $free
338
+            ];
339
+            return $this->quotaInfo;
340
+        } catch (NotFoundException $e) {
341
+            $this->getLogger()->warning('error while getting quota into', ['exception' => $e]);
342
+            return [0, 0];
343
+        } catch (StorageNotAvailableException $e) {
344
+            $this->getLogger()->warning('error while getting quota into', ['exception' => $e]);
345
+            return [0, 0];
346
+        } catch (NotPermittedException $e) {
347
+            $this->getLogger()->warning('error while getting quota into', ['exception' => $e]);
348
+            return [0, 0];
349
+        }
350
+    }
351
+
352
+    /**
353
+     * Moves a node into this collection.
354
+     *
355
+     * It is up to the implementors to:
356
+     *   1. Create the new resource.
357
+     *   2. Remove the old resource.
358
+     *   3. Transfer any properties or other data.
359
+     *
360
+     * Generally you should make very sure that your collection can easily move
361
+     * the move.
362
+     *
363
+     * If you don't, just return false, which will trigger sabre/dav to handle
364
+     * the move itself. If you return true from this function, the assumption
365
+     * is that the move was successful.
366
+     *
367
+     * @param string $targetName New local file/collection name.
368
+     * @param string $fullSourcePath Full path to source node
369
+     * @param INode $sourceNode Source node itself
370
+     * @return bool
371
+     * @throws BadRequest
372
+     * @throws ServiceUnavailable
373
+     * @throws Forbidden
374
+     * @throws FileLocked
375
+     * @throws \Sabre\DAV\Exception\Forbidden
376
+     */
377
+    public function moveInto($targetName, $fullSourcePath, INode $sourceNode) {
378
+        if (!$sourceNode instanceof Node) {
379
+            // it's a file of another kind, like FutureFile
380
+            if ($sourceNode instanceof IFile) {
381
+                // fallback to default copy+delete handling
382
+                return false;
383
+            }
384
+            throw new BadRequest('Incompatible node types');
385
+        }
386
+
387
+        $destinationPath = $this->getPath() . '/' . $targetName;
388
+
389
+
390
+        $targetNodeExists = $this->childExists($targetName);
391
+
392
+        // at getNodeForPath we also check the path for isForbiddenFileOrDir
393
+        // with that we have covered both source and destination
394
+        if ($sourceNode instanceof Directory && $targetNodeExists) {
395
+            throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode->getName() . ', target exists');
396
+        }
397
+
398
+        [$sourceDir,] = \Sabre\Uri\split($sourceNode->getPath());
399
+        $destinationDir = $this->getPath();
400
+
401
+        $sourcePath = $sourceNode->getPath();
402
+
403
+        $isMovableMount = false;
404
+        $sourceMount = Server::get(IMountManager::class)->find($this->fileView->getAbsolutePath($sourcePath));
405
+        $internalPath = $sourceMount->getInternalPath($this->fileView->getAbsolutePath($sourcePath));
406
+        if ($sourceMount instanceof MoveableMount && $internalPath === '') {
407
+            $isMovableMount = true;
408
+        }
409
+
410
+        try {
411
+            $sameFolder = ($sourceDir === $destinationDir);
412
+            // if we're overwriting or same folder
413
+            if ($targetNodeExists || $sameFolder) {
414
+                // note that renaming a share mount point is always allowed
415
+                if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) {
416
+                    throw new \Sabre\DAV\Exception\Forbidden();
417
+                }
418
+            } else {
419
+                if (!$this->fileView->isCreatable($destinationDir)) {
420
+                    throw new \Sabre\DAV\Exception\Forbidden();
421
+                }
422
+            }
423
+
424
+            if (!$sameFolder) {
425
+                // moving to a different folder, source will be gone, like a deletion
426
+                // note that moving a share mount point is always allowed
427
+                if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
428
+                    throw new \Sabre\DAV\Exception\Forbidden();
429
+                }
430
+            }
431
+
432
+            $fileName = basename($destinationPath);
433
+            try {
434
+                $this->fileView->verifyPath($destinationDir, $fileName);
435
+            } catch (InvalidPathException $ex) {
436
+                throw new InvalidPath($ex->getMessage());
437
+            }
438
+
439
+            $renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
440
+            if (!$renameOkay) {
441
+                throw new \Sabre\DAV\Exception\Forbidden('');
442
+            }
443
+        } catch (StorageNotAvailableException $e) {
444
+            throw new ServiceUnavailable($e->getMessage(), $e->getCode(), $e);
445
+        } catch (ForbiddenException $ex) {
446
+            throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
447
+        } catch (LockedException $e) {
448
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
449
+        }
450
+
451
+        return true;
452
+    }
453
+
454
+
455
+    public function copyInto($targetName, $sourcePath, INode $sourceNode) {
456
+        if ($sourceNode instanceof File || $sourceNode instanceof Directory) {
457
+            try {
458
+                $destinationPath = $this->getPath() . '/' . $targetName;
459
+                $sourcePath = $sourceNode->getPath();
460
+
461
+                if (!$this->fileView->isCreatable($this->getPath())) {
462
+                    throw new \Sabre\DAV\Exception\Forbidden();
463
+                }
464
+
465
+                try {
466
+                    $this->fileView->verifyPath($this->getPath(), $targetName);
467
+                } catch (InvalidPathException $ex) {
468
+                    throw new InvalidPath($ex->getMessage());
469
+                }
470
+
471
+                $copyOkay = $this->fileView->copy($sourcePath, $destinationPath);
472
+
473
+                if (!$copyOkay) {
474
+                    throw new \Sabre\DAV\Exception\Forbidden('Copy did not proceed');
475
+                }
476
+
477
+                return true;
478
+            } catch (StorageNotAvailableException $e) {
479
+                throw new ServiceUnavailable($e->getMessage(), $e->getCode(), $e);
480
+            } catch (ForbiddenException $ex) {
481
+                throw new Forbidden($ex->getMessage(), $ex->getRetry(), $ex);
482
+            } catch (LockedException $e) {
483
+                throw new FileLocked($e->getMessage(), $e->getCode(), $e);
484
+            }
485
+        }
486
+
487
+        return false;
488
+    }
489
+
490
+    public function getNode(): Folder {
491
+        return $this->node;
492
+    }
493 493
 }
Please login to merge, or discard this patch.