Completed
Push — master ( 3f85bc...84be99 )
by Blizzz
35:55
created
apps/dav/appinfo/v2/publicremote.php 2 patches
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -53,27 +53,27 @@  discard block
 block discarded – undo
53 53
 
54 54
 // Backends
55 55
 $authBackend = new PublicAuth(
56
-	$request,
57
-	Server::get(IManager::class),
58
-	$session,
59
-	Server::get(IThrottler::class),
60
-	Server::get(LoggerInterface::class),
61
-	Server::get(IURLGenerator::class),
56
+    $request,
57
+    Server::get(IManager::class),
58
+    $session,
59
+    Server::get(IThrottler::class),
60
+    Server::get(LoggerInterface::class),
61
+    Server::get(IURLGenerator::class),
62 62
 );
63 63
 $authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend);
64 64
 
65 65
 $l10nFactory = Server::get(IFactory::class);
66 66
 $serverFactory = new ServerFactory(
67
-	Server::get(IConfig::class),
68
-	Server::get(LoggerInterface::class),
69
-	Server::get(IDBConnection::class),
70
-	Server::get(IUserSession::class),
71
-	Server::get(IMountManager::class),
72
-	Server::get(ITagManager::class),
73
-	$request,
74
-	Server::get(IPreview::class),
75
-	$eventDispatcher,
76
-	$l10nFactory->get('dav'),
67
+    Server::get(IConfig::class),
68
+    Server::get(LoggerInterface::class),
69
+    Server::get(IDBConnection::class),
70
+    Server::get(IUserSession::class),
71
+    Server::get(IMountManager::class),
72
+    Server::get(ITagManager::class),
73
+    $request,
74
+    Server::get(IPreview::class),
75
+    $eventDispatcher,
76
+    $l10nFactory->get('dav'),
77 77
 );
78 78
 
79 79
 
@@ -82,69 +82,69 @@  discard block
 block discarded – undo
82 82
 
83 83
 /** @var string $baseuri defined in public.php */
84 84
 $server = $serverFactory->createServer(true, $baseuri, $requestUri, $authPlugin, function (\Sabre\DAV\Server $server) use ($baseuri, $requestUri, $authBackend, $linkCheckPlugin, $filesDropPlugin) {
85
-	// GET must be allowed for e.g. showing images and allowing Zip downloads
86
-	if ($server->httpRequest->getMethod() !== 'GET') {
87
-		// If this is *not* a GET request we only allow access to public DAV from AJAX or when Server2Server is allowed
88
-		$isAjax = in_array('XMLHttpRequest', explode(',', $_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''));
89
-		$federatedShareProvider = Server::get(FederatedShareProvider::class);
90
-		if ($federatedShareProvider->isOutgoingServer2serverShareEnabled() === false && $isAjax === false) {
91
-			// this is what is thrown when trying to access a non-existing share
92
-			throw new NotAuthenticated();
93
-		}
94
-	}
95
-
96
-	$share = $authBackend->getShare();
97
-	$owner = $share->getShareOwner();
98
-	$isReadable = $share->getPermissions() & Constants::PERMISSION_READ;
99
-	$fileId = $share->getNodeId();
100
-
101
-	// FIXME: should not add storage wrappers outside of preSetup, need to find a better way
102
-	/** @psalm-suppress InternalMethod */
103
-	$previousLog = Filesystem::logWarningWhenAddingStorageWrapper(false);
104
-
105
-	/** @psalm-suppress MissingClosureParamType */
106
-	Filesystem::addStorageWrapper('sharePermissions', function ($mountPoint, $storage) use ($requestUri, $baseuri, $share) {
107
-		$mask = $share->getPermissions() | Constants::PERMISSION_SHARE;
108
-
109
-		// For chunked uploads it is necessary to have read and delete permission,
110
-		// so the temporary directory, chunks and destination file can be read and delete after the assembly.
111
-		if (str_starts_with(substr($requestUri, strlen($baseuri) - 1), '/uploads/')) {
112
-			$mask |= Constants::PERMISSION_READ | Constants::PERMISSION_DELETE;
113
-		}
114
-
115
-		return new PermissionsMask(['storage' => $storage, 'mask' => $mask]);
116
-	});
117
-
118
-	/** @psalm-suppress MissingClosureParamType */
119
-	Filesystem::addStorageWrapper('shareOwner', function ($mountPoint, $storage) use ($share) {
120
-		return new PublicOwnerWrapper(['storage' => $storage, 'owner' => $share->getShareOwner()]);
121
-	});
122
-
123
-	// Ensure that also private shares have the `getShare` method
124
-	/** @psalm-suppress MissingClosureParamType */
125
-	Filesystem::addStorageWrapper('getShare', function ($mountPoint, $storage) use ($share) {
126
-		return new PublicShareWrapper(['storage' => $storage, 'share' => $share]);
127
-	}, 0);
128
-
129
-	/** @psalm-suppress InternalMethod */
130
-	Filesystem::logWarningWhenAddingStorageWrapper($previousLog);
131
-
132
-	$rootFolder = Server::get(IRootFolder::class);
133
-	$userFolder = $rootFolder->getUserFolder($owner);
134
-	$node = $userFolder->getFirstNodeById($fileId);
135
-	if (!$node) {
136
-		throw new NotFound();
137
-	}
138
-	$linkCheckPlugin->setFileInfo($node);
139
-
140
-	// If not readable (files_drop) enable the filesdrop plugin
141
-	if (!$isReadable) {
142
-		$filesDropPlugin->enable();
143
-	}
144
-	$filesDropPlugin->setShare($share);
145
-
146
-	$view = new View($node->getPath());
147
-	return $view;
85
+    // GET must be allowed for e.g. showing images and allowing Zip downloads
86
+    if ($server->httpRequest->getMethod() !== 'GET') {
87
+        // If this is *not* a GET request we only allow access to public DAV from AJAX or when Server2Server is allowed
88
+        $isAjax = in_array('XMLHttpRequest', explode(',', $_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''));
89
+        $federatedShareProvider = Server::get(FederatedShareProvider::class);
90
+        if ($federatedShareProvider->isOutgoingServer2serverShareEnabled() === false && $isAjax === false) {
91
+            // this is what is thrown when trying to access a non-existing share
92
+            throw new NotAuthenticated();
93
+        }
94
+    }
95
+
96
+    $share = $authBackend->getShare();
97
+    $owner = $share->getShareOwner();
98
+    $isReadable = $share->getPermissions() & Constants::PERMISSION_READ;
99
+    $fileId = $share->getNodeId();
100
+
101
+    // FIXME: should not add storage wrappers outside of preSetup, need to find a better way
102
+    /** @psalm-suppress InternalMethod */
103
+    $previousLog = Filesystem::logWarningWhenAddingStorageWrapper(false);
104
+
105
+    /** @psalm-suppress MissingClosureParamType */
106
+    Filesystem::addStorageWrapper('sharePermissions', function ($mountPoint, $storage) use ($requestUri, $baseuri, $share) {
107
+        $mask = $share->getPermissions() | Constants::PERMISSION_SHARE;
108
+
109
+        // For chunked uploads it is necessary to have read and delete permission,
110
+        // so the temporary directory, chunks and destination file can be read and delete after the assembly.
111
+        if (str_starts_with(substr($requestUri, strlen($baseuri) - 1), '/uploads/')) {
112
+            $mask |= Constants::PERMISSION_READ | Constants::PERMISSION_DELETE;
113
+        }
114
+
115
+        return new PermissionsMask(['storage' => $storage, 'mask' => $mask]);
116
+    });
117
+
118
+    /** @psalm-suppress MissingClosureParamType */
119
+    Filesystem::addStorageWrapper('shareOwner', function ($mountPoint, $storage) use ($share) {
120
+        return new PublicOwnerWrapper(['storage' => $storage, 'owner' => $share->getShareOwner()]);
121
+    });
122
+
123
+    // Ensure that also private shares have the `getShare` method
124
+    /** @psalm-suppress MissingClosureParamType */
125
+    Filesystem::addStorageWrapper('getShare', function ($mountPoint, $storage) use ($share) {
126
+        return new PublicShareWrapper(['storage' => $storage, 'share' => $share]);
127
+    }, 0);
128
+
129
+    /** @psalm-suppress InternalMethod */
130
+    Filesystem::logWarningWhenAddingStorageWrapper($previousLog);
131
+
132
+    $rootFolder = Server::get(IRootFolder::class);
133
+    $userFolder = $rootFolder->getUserFolder($owner);
134
+    $node = $userFolder->getFirstNodeById($fileId);
135
+    if (!$node) {
136
+        throw new NotFound();
137
+    }
138
+    $linkCheckPlugin->setFileInfo($node);
139
+
140
+    // If not readable (files_drop) enable the filesdrop plugin
141
+    if (!$isReadable) {
142
+        $filesDropPlugin->enable();
143
+    }
144
+    $filesDropPlugin->setShare($share);
145
+
146
+    $view = new View($node->getPath());
147
+    return $view;
148 148
 });
149 149
 
150 150
 $server->addPlugin($linkCheckPlugin);
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -81,7 +81,7 @@  discard block
 block discarded – undo
81 81
 $filesDropPlugin = new FilesDropPlugin();
82 82
 
83 83
 /** @var string $baseuri defined in public.php */
84
-$server = $serverFactory->createServer(true, $baseuri, $requestUri, $authPlugin, function (\Sabre\DAV\Server $server) use ($baseuri, $requestUri, $authBackend, $linkCheckPlugin, $filesDropPlugin) {
84
+$server = $serverFactory->createServer(true, $baseuri, $requestUri, $authPlugin, function(\Sabre\DAV\Server $server) use ($baseuri, $requestUri, $authBackend, $linkCheckPlugin, $filesDropPlugin) {
85 85
 	// GET must be allowed for e.g. showing images and allowing Zip downloads
86 86
 	if ($server->httpRequest->getMethod() !== 'GET') {
87 87
 		// If this is *not* a GET request we only allow access to public DAV from AJAX or when Server2Server is allowed
@@ -103,7 +103,7 @@  discard block
 block discarded – undo
103 103
 	$previousLog = Filesystem::logWarningWhenAddingStorageWrapper(false);
104 104
 
105 105
 	/** @psalm-suppress MissingClosureParamType */
106
-	Filesystem::addStorageWrapper('sharePermissions', function ($mountPoint, $storage) use ($requestUri, $baseuri, $share) {
106
+	Filesystem::addStorageWrapper('sharePermissions', function($mountPoint, $storage) use ($requestUri, $baseuri, $share) {
107 107
 		$mask = $share->getPermissions() | Constants::PERMISSION_SHARE;
108 108
 
109 109
 		// For chunked uploads it is necessary to have read and delete permission,
@@ -116,13 +116,13 @@  discard block
 block discarded – undo
116 116
 	});
117 117
 
118 118
 	/** @psalm-suppress MissingClosureParamType */
119
-	Filesystem::addStorageWrapper('shareOwner', function ($mountPoint, $storage) use ($share) {
119
+	Filesystem::addStorageWrapper('shareOwner', function($mountPoint, $storage) use ($share) {
120 120
 		return new PublicOwnerWrapper(['storage' => $storage, 'owner' => $share->getShareOwner()]);
121 121
 	});
122 122
 
123 123
 	// Ensure that also private shares have the `getShare` method
124 124
 	/** @psalm-suppress MissingClosureParamType */
125
-	Filesystem::addStorageWrapper('getShare', function ($mountPoint, $storage) use ($share) {
125
+	Filesystem::addStorageWrapper('getShare', function($mountPoint, $storage) use ($share) {
126 126
 		return new PublicShareWrapper(['storage' => $storage, 'share' => $share]);
127 127
 	}, 0);
128 128
 
Please login to merge, or discard this patch.
apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php 1 patch
Indentation   +202 added lines, -202 removed lines patch added patch discarded remove patch
@@ -20,212 +20,212 @@
 block discarded – undo
20 20
 
21 21
 class FilesDropPluginTest extends TestCase {
22 22
 
23
-	private FilesDropPlugin $plugin;
23
+    private FilesDropPlugin $plugin;
24 24
 
25
-	private Folder&MockObject $node;
26
-	private IShare&MockObject $share;
27
-	private Server&MockObject $server;
28
-	private RequestInterface&MockObject $request;
29
-	private ResponseInterface&MockObject $response;
25
+    private Folder&MockObject $node;
26
+    private IShare&MockObject $share;
27
+    private Server&MockObject $server;
28
+    private RequestInterface&MockObject $request;
29
+    private ResponseInterface&MockObject $response;
30 30
 
31
-	protected function setUp(): void {
32
-		parent::setUp();
31
+    protected function setUp(): void {
32
+        parent::setUp();
33 33
 
34
-		$this->node = $this->createMock(Folder::class);
35
-		$this->node->method('getPath')
36
-			->willReturn('/files/token');
34
+        $this->node = $this->createMock(Folder::class);
35
+        $this->node->method('getPath')
36
+            ->willReturn('/files/token');
37 37
 
38
-		$this->share = $this->createMock(IShare::class);
39
-		$this->share->expects(self::any())
40
-			->method('getNode')
41
-			->willReturn($this->node);
42
-		$this->server = $this->createMock(Server::class);
43
-		$this->plugin = new FilesDropPlugin();
38
+        $this->share = $this->createMock(IShare::class);
39
+        $this->share->expects(self::any())
40
+            ->method('getNode')
41
+            ->willReturn($this->node);
42
+        $this->server = $this->createMock(Server::class);
43
+        $this->plugin = new FilesDropPlugin();
44 44
 
45
-		$this->request = $this->createMock(RequestInterface::class);
46
-		$this->response = $this->createMock(ResponseInterface::class);
45
+        $this->request = $this->createMock(RequestInterface::class);
46
+        $this->response = $this->createMock(ResponseInterface::class);
47 47
 
48
-		$attributes = $this->createMock(IAttributes::class);
49
-		$this->share->expects($this->any())
50
-			->method('getAttributes')
51
-			->willReturn($attributes);
52
-
53
-		$this->share
54
-			->method('getToken')
55
-			->willReturn('token');
56
-	}
57
-
58
-	public function testValid(): void {
59
-		$this->plugin->enable();
60
-		$this->plugin->setShare($this->share);
61
-
62
-		$this->request->method('getMethod')
63
-			->willReturn('PUT');
64
-
65
-		$this->request->method('getPath')
66
-			->willReturn('/files/token/file.txt');
67
-
68
-		$this->request->method('getBaseUrl')
69
-			->willReturn('https://example.com');
70
-
71
-		$this->node->expects(self::once())
72
-			->method('getNonExistingName')
73
-			->with('file.txt')
74
-			->willReturn('file.txt');
75
-
76
-		$this->request->expects($this->once())
77
-			->method('setUrl')
78
-			->with('https://example.com/files/token/file.txt');
79
-
80
-		$this->plugin->beforeMethod($this->request, $this->response);
81
-	}
82
-
83
-	public function testFileAlreadyExistsValid(): void {
84
-		$this->plugin->enable();
85
-		$this->plugin->setShare($this->share);
86
-
87
-		$this->request->method('getMethod')
88
-			->willReturn('PUT');
89
-
90
-		$this->request->method('getPath')
91
-			->willReturn('/files/token/file.txt');
92
-
93
-		$this->request->method('getBaseUrl')
94
-			->willReturn('https://example.com');
95
-
96
-		$this->node->method('getNonExistingName')
97
-			->with('file.txt')
98
-			->willReturn('file (2).txt');
99
-
100
-		$this->request->expects($this->once())
101
-			->method('setUrl')
102
-			->with($this->equalTo('https://example.com/files/token/file (2).txt'));
103
-
104
-		$this->plugin->beforeMethod($this->request, $this->response);
105
-	}
106
-
107
-	public function testMKCOL(): void {
108
-		$this->plugin->enable();
109
-		$this->plugin->setShare($this->share);
110
-
111
-		$this->request->method('getMethod')
112
-			->willReturn('MKCOL');
113
-
114
-		$this->expectNotToPerformAssertions();
115
-
116
-		$this->plugin->beforeMethod($this->request, $this->response);
117
-	}
118
-
119
-	public function testSubdirPut(): void {
120
-		$this->plugin->enable();
121
-		$this->plugin->setShare($this->share);
122
-
123
-		$this->request->method('getMethod')
124
-			->willReturn('PUT');
125
-
126
-		$this->request->method('hasHeader')
127
-			->with('X-NC-Nickname')
128
-			->willReturn(true);
129
-		$this->request->method('getHeader')
130
-			->with('X-NC-Nickname')
131
-			->willReturn('nickname');
132
-
133
-		$this->request->method('getPath')
134
-			->willReturn('/files/token/folder/file.txt');
135
-
136
-		$this->request->method('getBaseUrl')
137
-			->willReturn('https://example.com');
138
-
139
-		$nodeName = $this->createMock(Folder::class);
140
-		$nodeFolder = $this->createMock(Folder::class);
141
-		$nodeFolder->expects(self::once())
142
-			->method('getPath')
143
-			->willReturn('/files/token/nickname/folder');
144
-		$nodeFolder->method('getNonExistingName')
145
-			->with('file.txt')
146
-			->willReturn('file.txt');
147
-		$nodeName->expects(self::once())
148
-			->method('get')
149
-			->with('folder')
150
-			->willThrowException(new NotFoundException());
151
-		$nodeName->expects(self::once())
152
-			->method('newFolder')
153
-			->with('folder')
154
-			->willReturn($nodeFolder);
155
-
156
-		$this->node->expects(self::once())
157
-			->method('get')
158
-			->willThrowException(new NotFoundException());
159
-		$this->node->expects(self::once())
160
-			->method('newFolder')
161
-			->with('nickname')
162
-			->willReturn($nodeName);
163
-
164
-		$this->request->expects($this->once())
165
-			->method('setUrl')
166
-			->with($this->equalTo('https://example.com/files/token/nickname/folder/file.txt'));
167
-
168
-		$this->plugin->beforeMethod($this->request, $this->response);
169
-	}
170
-
171
-	public function testRecursiveFolderCreation(): void {
172
-		$this->plugin->enable();
173
-		$this->plugin->setShare($this->share);
174
-
175
-		$this->request->method('getMethod')
176
-			->willReturn('PUT');
177
-		$this->request->method('hasHeader')
178
-			->with('X-NC-Nickname')
179
-			->willReturn(true);
180
-		$this->request->method('getHeader')
181
-			->with('X-NC-Nickname')
182
-			->willReturn('nickname');
183
-
184
-		$this->request->method('getPath')
185
-			->willReturn('/files/token/folder/subfolder/file.txt');
186
-		$this->request->method('getBaseUrl')
187
-			->willReturn('https://example.com');
188
-
189
-		$this->request->expects($this->once())
190
-			->method('setUrl')
191
-			->with($this->equalTo('https://example.com/files/token/nickname/folder/subfolder/file.txt'));
192
-
193
-		$subfolder = $this->createMock(Folder::class);
194
-		$subfolder->expects(self::once())
195
-			->method('getNonExistingName')
196
-			->with('file.txt')
197
-			->willReturn('file.txt');
198
-		$subfolder->expects(self::once())
199
-			->method('getPath')
200
-			->willReturn('/files/token/nickname/folder/subfolder');
201
-
202
-		$folder = $this->createMock(Folder::class);
203
-		$folder->expects(self::once())
204
-			->method('get')
205
-			->with('subfolder')
206
-			->willReturn($subfolder);
207
-
208
-		$nickname = $this->createMock(Folder::class);
209
-		$nickname->expects(self::once())
210
-			->method('get')
211
-			->with('folder')
212
-			->willReturn($folder);
213
-
214
-		$this->node->method('get')
215
-			->with('nickname')
216
-			->willReturn($nickname);
217
-		$this->plugin->beforeMethod($this->request, $this->response);
218
-	}
219
-
220
-	public function testOnMkcol(): void {
221
-		$this->plugin->enable();
222
-		$this->plugin->setShare($this->share);
223
-
224
-		$this->response->expects($this->once())
225
-			->method('setStatus')
226
-			->with(201);
227
-
228
-		$response = $this->plugin->onMkcol($this->request, $this->response);
229
-		$this->assertFalse($response);
230
-	}
48
+        $attributes = $this->createMock(IAttributes::class);
49
+        $this->share->expects($this->any())
50
+            ->method('getAttributes')
51
+            ->willReturn($attributes);
52
+
53
+        $this->share
54
+            ->method('getToken')
55
+            ->willReturn('token');
56
+    }
57
+
58
+    public function testValid(): void {
59
+        $this->plugin->enable();
60
+        $this->plugin->setShare($this->share);
61
+
62
+        $this->request->method('getMethod')
63
+            ->willReturn('PUT');
64
+
65
+        $this->request->method('getPath')
66
+            ->willReturn('/files/token/file.txt');
67
+
68
+        $this->request->method('getBaseUrl')
69
+            ->willReturn('https://example.com');
70
+
71
+        $this->node->expects(self::once())
72
+            ->method('getNonExistingName')
73
+            ->with('file.txt')
74
+            ->willReturn('file.txt');
75
+
76
+        $this->request->expects($this->once())
77
+            ->method('setUrl')
78
+            ->with('https://example.com/files/token/file.txt');
79
+
80
+        $this->plugin->beforeMethod($this->request, $this->response);
81
+    }
82
+
83
+    public function testFileAlreadyExistsValid(): void {
84
+        $this->plugin->enable();
85
+        $this->plugin->setShare($this->share);
86
+
87
+        $this->request->method('getMethod')
88
+            ->willReturn('PUT');
89
+
90
+        $this->request->method('getPath')
91
+            ->willReturn('/files/token/file.txt');
92
+
93
+        $this->request->method('getBaseUrl')
94
+            ->willReturn('https://example.com');
95
+
96
+        $this->node->method('getNonExistingName')
97
+            ->with('file.txt')
98
+            ->willReturn('file (2).txt');
99
+
100
+        $this->request->expects($this->once())
101
+            ->method('setUrl')
102
+            ->with($this->equalTo('https://example.com/files/token/file (2).txt'));
103
+
104
+        $this->plugin->beforeMethod($this->request, $this->response);
105
+    }
106
+
107
+    public function testMKCOL(): void {
108
+        $this->plugin->enable();
109
+        $this->plugin->setShare($this->share);
110
+
111
+        $this->request->method('getMethod')
112
+            ->willReturn('MKCOL');
113
+
114
+        $this->expectNotToPerformAssertions();
115
+
116
+        $this->plugin->beforeMethod($this->request, $this->response);
117
+    }
118
+
119
+    public function testSubdirPut(): void {
120
+        $this->plugin->enable();
121
+        $this->plugin->setShare($this->share);
122
+
123
+        $this->request->method('getMethod')
124
+            ->willReturn('PUT');
125
+
126
+        $this->request->method('hasHeader')
127
+            ->with('X-NC-Nickname')
128
+            ->willReturn(true);
129
+        $this->request->method('getHeader')
130
+            ->with('X-NC-Nickname')
131
+            ->willReturn('nickname');
132
+
133
+        $this->request->method('getPath')
134
+            ->willReturn('/files/token/folder/file.txt');
135
+
136
+        $this->request->method('getBaseUrl')
137
+            ->willReturn('https://example.com');
138
+
139
+        $nodeName = $this->createMock(Folder::class);
140
+        $nodeFolder = $this->createMock(Folder::class);
141
+        $nodeFolder->expects(self::once())
142
+            ->method('getPath')
143
+            ->willReturn('/files/token/nickname/folder');
144
+        $nodeFolder->method('getNonExistingName')
145
+            ->with('file.txt')
146
+            ->willReturn('file.txt');
147
+        $nodeName->expects(self::once())
148
+            ->method('get')
149
+            ->with('folder')
150
+            ->willThrowException(new NotFoundException());
151
+        $nodeName->expects(self::once())
152
+            ->method('newFolder')
153
+            ->with('folder')
154
+            ->willReturn($nodeFolder);
155
+
156
+        $this->node->expects(self::once())
157
+            ->method('get')
158
+            ->willThrowException(new NotFoundException());
159
+        $this->node->expects(self::once())
160
+            ->method('newFolder')
161
+            ->with('nickname')
162
+            ->willReturn($nodeName);
163
+
164
+        $this->request->expects($this->once())
165
+            ->method('setUrl')
166
+            ->with($this->equalTo('https://example.com/files/token/nickname/folder/file.txt'));
167
+
168
+        $this->plugin->beforeMethod($this->request, $this->response);
169
+    }
170
+
171
+    public function testRecursiveFolderCreation(): void {
172
+        $this->plugin->enable();
173
+        $this->plugin->setShare($this->share);
174
+
175
+        $this->request->method('getMethod')
176
+            ->willReturn('PUT');
177
+        $this->request->method('hasHeader')
178
+            ->with('X-NC-Nickname')
179
+            ->willReturn(true);
180
+        $this->request->method('getHeader')
181
+            ->with('X-NC-Nickname')
182
+            ->willReturn('nickname');
183
+
184
+        $this->request->method('getPath')
185
+            ->willReturn('/files/token/folder/subfolder/file.txt');
186
+        $this->request->method('getBaseUrl')
187
+            ->willReturn('https://example.com');
188
+
189
+        $this->request->expects($this->once())
190
+            ->method('setUrl')
191
+            ->with($this->equalTo('https://example.com/files/token/nickname/folder/subfolder/file.txt'));
192
+
193
+        $subfolder = $this->createMock(Folder::class);
194
+        $subfolder->expects(self::once())
195
+            ->method('getNonExistingName')
196
+            ->with('file.txt')
197
+            ->willReturn('file.txt');
198
+        $subfolder->expects(self::once())
199
+            ->method('getPath')
200
+            ->willReturn('/files/token/nickname/folder/subfolder');
201
+
202
+        $folder = $this->createMock(Folder::class);
203
+        $folder->expects(self::once())
204
+            ->method('get')
205
+            ->with('subfolder')
206
+            ->willReturn($subfolder);
207
+
208
+        $nickname = $this->createMock(Folder::class);
209
+        $nickname->expects(self::once())
210
+            ->method('get')
211
+            ->with('folder')
212
+            ->willReturn($folder);
213
+
214
+        $this->node->method('get')
215
+            ->with('nickname')
216
+            ->willReturn($nickname);
217
+        $this->plugin->beforeMethod($this->request, $this->response);
218
+    }
219
+
220
+    public function testOnMkcol(): void {
221
+        $this->plugin->enable();
222
+        $this->plugin->setShare($this->share);
223
+
224
+        $this->response->expects($this->once())
225
+            ->method('setStatus')
226
+            ->with(201);
227
+
228
+        $response = $this->plugin->onMkcol($this->request, $this->response);
229
+        $this->assertFalse($response);
230
+    }
231 231
 }
Please login to merge, or discard this patch.
apps/dav/lib/Files/Sharing/FilesDropPlugin.php 2 patches
Indentation   +195 added lines, -195 removed lines patch added patch discarded remove patch
@@ -20,199 +20,199 @@
 block discarded – undo
20 20
  */
21 21
 class FilesDropPlugin extends ServerPlugin {
22 22
 
23
-	private ?IShare $share = null;
24
-	private bool $enabled = false;
25
-
26
-	public function setShare(IShare $share): void {
27
-		$this->share = $share;
28
-	}
29
-
30
-	public function enable(): void {
31
-		$this->enabled = true;
32
-	}
33
-
34
-	/**
35
-	 * This initializes the plugin.
36
-	 * It is ONLY initialized by the server on a file drop request.
37
-	 */
38
-	public function initialize(\Sabre\DAV\Server $server): void {
39
-		$server->on('beforeMethod:*', [$this, 'beforeMethod'], 999);
40
-		$server->on('method:MKCOL', [$this, 'onMkcol']);
41
-		$this->enabled = false;
42
-	}
43
-
44
-	public function onMkcol(RequestInterface $request, ResponseInterface $response) {
45
-		if ($this->isChunkedUpload($request)) {
46
-			return;
47
-		}
48
-
49
-		if (!$this->enabled || $this->share === null) {
50
-			return;
51
-		}
52
-
53
-		$node = $this->share->getNode();
54
-		if (!($node instanceof Folder)) {
55
-			return;
56
-		}
57
-
58
-		// If this is a folder creation request we need
59
-		// to fake a success so we can pretend every
60
-		// folder now exists.
61
-		$response->setStatus(201);
62
-		return false;
63
-	}
64
-
65
-	private function isChunkedUpload(RequestInterface $request): bool {
66
-		return str_starts_with(substr($request->getUrl(), strlen($request->getBaseUrl()) - 1), '/uploads/');
67
-	}
68
-
69
-	public function beforeMethod(RequestInterface $request, ResponseInterface $response) {
70
-		$isChunkedUpload = $this->isChunkedUpload($request);
71
-
72
-		// For the final MOVE request of a chunked upload it is necessary to modify the Destination header.
73
-		if ($isChunkedUpload && $request->getMethod() !== 'MOVE') {
74
-			return;
75
-		}
76
-
77
-		if (!$this->enabled || $this->share === null) {
78
-			return;
79
-		}
80
-
81
-		$node = $this->share->getNode();
82
-		if (!($node instanceof Folder)) {
83
-			return;
84
-		}
85
-
86
-		if ($request->getMethod() !== 'PUT' && $request->getMethod() !== 'MKCOL' && (!$isChunkedUpload || $request->getMethod() !== 'MOVE')) {
87
-			throw new MethodNotAllowed('Only PUT, MKCOL and MOVE are allowed on files drop');
88
-		}
89
-
90
-		// If this is a folder creation request
91
-		// let's stop there and let the onMkcol handle it
92
-		if ($request->getMethod() === 'MKCOL') {
93
-			return;
94
-		}
95
-
96
-		// Now if we create a file, we need to create the
97
-		// full path along the way. We'll only handle conflict
98
-		// resolution on file conflicts, but not on folders.
99
-
100
-		if ($isChunkedUpload) {
101
-			$destination = $request->getHeader('destination');
102
-			$baseUrl = $request->getBaseUrl();
103
-			// e.g files/dCP8yn3N86EK9sL/Folder/image.jpg
104
-			$path = substr($destination, strpos($destination, $baseUrl) + strlen($baseUrl));
105
-		} else {
106
-			// e.g files/dCP8yn3N86EK9sL/Folder/image.jpg
107
-			$path = $request->getPath();
108
-		}
109
-
110
-		$token = $this->share->getToken();
111
-
112
-		// e.g files/dCP8yn3N86EK9sL
113
-		$rootPath = substr($path, 0, strpos($path, $token) + strlen($token));
114
-		// e.g /Folder/image.jpg
115
-		$relativePath = substr($path, strlen($rootPath));
116
-		$isRootUpload = substr_count($relativePath, '/') === 1;
117
-
118
-		// Extract the attributes for the file request
119
-		$isFileRequest = false;
120
-		$attributes = $this->share->getAttributes();
121
-		if ($attributes !== null) {
122
-			$isFileRequest = $attributes->getAttribute('fileRequest', 'enabled') === true;
123
-		}
124
-
125
-		// Retrieve the nickname from the request
126
-		$nickname = $request->hasHeader('X-NC-Nickname')
127
-			? trim(urldecode($request->getHeader('X-NC-Nickname')))
128
-			: null;
129
-
130
-		// We need a valid nickname for file requests
131
-		if ($isFileRequest && !$nickname) {
132
-			throw new BadRequest('A nickname header is required for file requests');
133
-		}
134
-
135
-		// We're only allowing the upload of
136
-		// long path with subfolders if a nickname is set.
137
-		// This prevents confusion when uploading files and help
138
-		// classify them by uploaders.
139
-		if (!$nickname && !$isRootUpload) {
140
-			throw new BadRequest('A nickname header is required when uploading subfolders');
141
-		}
142
-
143
-		if ($nickname) {
144
-			try {
145
-				$node->verifyPath($nickname);
146
-			} catch (\Exception $e) {
147
-				// If the path is not valid, we throw an exception
148
-				throw new BadRequest('Invalid nickname: ' . $nickname);
149
-			}
150
-
151
-			// Forbid nicknames starting with a dot
152
-			if (str_starts_with($nickname, '.')) {
153
-				throw new BadRequest('Invalid nickname: ' . $nickname);
154
-			}
155
-
156
-			// If we have a nickname, let's put
157
-			// all files in the subfolder
158
-			$relativePath = '/' . $nickname . '/' . $relativePath;
159
-			$relativePath = str_replace('//', '/', $relativePath);
160
-		}
161
-
162
-		// Create the folders along the way
163
-		$folder = $node;
164
-		$pathSegments = $this->getPathSegments(dirname($relativePath));
165
-		foreach ($pathSegments as $pathSegment) {
166
-			if ($pathSegment === '') {
167
-				continue;
168
-			}
169
-
170
-			try {
171
-				// get the current folder
172
-				$currentFolder = $folder->get($pathSegment);
173
-				// check target is a folder
174
-				if ($currentFolder instanceof Folder) {
175
-					$folder = $currentFolder;
176
-				} else {
177
-					// otherwise look in the parent folder if we already create an unique folder name
178
-					foreach ($folder->getDirectoryListing() as $child) {
179
-						// we look for folders which match "NAME (SUFFIX)"
180
-						if ($child instanceof Folder && str_starts_with($child->getName(), $pathSegment)) {
181
-							$suffix = substr($child->getName(), strlen($pathSegment));
182
-							if (preg_match('/^ \(\d+\)$/', $suffix)) {
183
-								// we found the unique folder name and can use it
184
-								$folder = $child;
185
-								break;
186
-							}
187
-						}
188
-					}
189
-					// no folder found so we need to create a new unique folder name
190
-					if (!isset($child) || $child !== $folder) {
191
-						$folder = $folder->newFolder($folder->getNonExistingName($pathSegment));
192
-					}
193
-				}
194
-			} catch (NotFoundException) {
195
-				// the folder does simply not exist so we create it
196
-				$folder = $folder->newFolder($pathSegment);
197
-			}
198
-		}
199
-
200
-		// Finally handle conflicts on the end files
201
-		$uniqueName = $folder->getNonExistingName(basename($relativePath));
202
-		$relativePath = substr($folder->getPath(), strlen($node->getPath()));
203
-		$path = '/files/' . $token . '/' . $relativePath . '/' . $uniqueName;
204
-		$url = rtrim($request->getBaseUrl(), '/') . str_replace('//', '/', $path);
205
-		if ($isChunkedUpload) {
206
-			$request->setHeader('destination', $url);
207
-		} else {
208
-			$request->setUrl($url);
209
-		}
210
-	}
211
-
212
-	private function getPathSegments(string $path): array {
213
-		// Normalize slashes and remove trailing slash
214
-		$path = trim(str_replace('\\', '/', $path), '/');
215
-
216
-		return explode('/', $path);
217
-	}
23
+    private ?IShare $share = null;
24
+    private bool $enabled = false;
25
+
26
+    public function setShare(IShare $share): void {
27
+        $this->share = $share;
28
+    }
29
+
30
+    public function enable(): void {
31
+        $this->enabled = true;
32
+    }
33
+
34
+    /**
35
+     * This initializes the plugin.
36
+     * It is ONLY initialized by the server on a file drop request.
37
+     */
38
+    public function initialize(\Sabre\DAV\Server $server): void {
39
+        $server->on('beforeMethod:*', [$this, 'beforeMethod'], 999);
40
+        $server->on('method:MKCOL', [$this, 'onMkcol']);
41
+        $this->enabled = false;
42
+    }
43
+
44
+    public function onMkcol(RequestInterface $request, ResponseInterface $response) {
45
+        if ($this->isChunkedUpload($request)) {
46
+            return;
47
+        }
48
+
49
+        if (!$this->enabled || $this->share === null) {
50
+            return;
51
+        }
52
+
53
+        $node = $this->share->getNode();
54
+        if (!($node instanceof Folder)) {
55
+            return;
56
+        }
57
+
58
+        // If this is a folder creation request we need
59
+        // to fake a success so we can pretend every
60
+        // folder now exists.
61
+        $response->setStatus(201);
62
+        return false;
63
+    }
64
+
65
+    private function isChunkedUpload(RequestInterface $request): bool {
66
+        return str_starts_with(substr($request->getUrl(), strlen($request->getBaseUrl()) - 1), '/uploads/');
67
+    }
68
+
69
+    public function beforeMethod(RequestInterface $request, ResponseInterface $response) {
70
+        $isChunkedUpload = $this->isChunkedUpload($request);
71
+
72
+        // For the final MOVE request of a chunked upload it is necessary to modify the Destination header.
73
+        if ($isChunkedUpload && $request->getMethod() !== 'MOVE') {
74
+            return;
75
+        }
76
+
77
+        if (!$this->enabled || $this->share === null) {
78
+            return;
79
+        }
80
+
81
+        $node = $this->share->getNode();
82
+        if (!($node instanceof Folder)) {
83
+            return;
84
+        }
85
+
86
+        if ($request->getMethod() !== 'PUT' && $request->getMethod() !== 'MKCOL' && (!$isChunkedUpload || $request->getMethod() !== 'MOVE')) {
87
+            throw new MethodNotAllowed('Only PUT, MKCOL and MOVE are allowed on files drop');
88
+        }
89
+
90
+        // If this is a folder creation request
91
+        // let's stop there and let the onMkcol handle it
92
+        if ($request->getMethod() === 'MKCOL') {
93
+            return;
94
+        }
95
+
96
+        // Now if we create a file, we need to create the
97
+        // full path along the way. We'll only handle conflict
98
+        // resolution on file conflicts, but not on folders.
99
+
100
+        if ($isChunkedUpload) {
101
+            $destination = $request->getHeader('destination');
102
+            $baseUrl = $request->getBaseUrl();
103
+            // e.g files/dCP8yn3N86EK9sL/Folder/image.jpg
104
+            $path = substr($destination, strpos($destination, $baseUrl) + strlen($baseUrl));
105
+        } else {
106
+            // e.g files/dCP8yn3N86EK9sL/Folder/image.jpg
107
+            $path = $request->getPath();
108
+        }
109
+
110
+        $token = $this->share->getToken();
111
+
112
+        // e.g files/dCP8yn3N86EK9sL
113
+        $rootPath = substr($path, 0, strpos($path, $token) + strlen($token));
114
+        // e.g /Folder/image.jpg
115
+        $relativePath = substr($path, strlen($rootPath));
116
+        $isRootUpload = substr_count($relativePath, '/') === 1;
117
+
118
+        // Extract the attributes for the file request
119
+        $isFileRequest = false;
120
+        $attributes = $this->share->getAttributes();
121
+        if ($attributes !== null) {
122
+            $isFileRequest = $attributes->getAttribute('fileRequest', 'enabled') === true;
123
+        }
124
+
125
+        // Retrieve the nickname from the request
126
+        $nickname = $request->hasHeader('X-NC-Nickname')
127
+            ? trim(urldecode($request->getHeader('X-NC-Nickname')))
128
+            : null;
129
+
130
+        // We need a valid nickname for file requests
131
+        if ($isFileRequest && !$nickname) {
132
+            throw new BadRequest('A nickname header is required for file requests');
133
+        }
134
+
135
+        // We're only allowing the upload of
136
+        // long path with subfolders if a nickname is set.
137
+        // This prevents confusion when uploading files and help
138
+        // classify them by uploaders.
139
+        if (!$nickname && !$isRootUpload) {
140
+            throw new BadRequest('A nickname header is required when uploading subfolders');
141
+        }
142
+
143
+        if ($nickname) {
144
+            try {
145
+                $node->verifyPath($nickname);
146
+            } catch (\Exception $e) {
147
+                // If the path is not valid, we throw an exception
148
+                throw new BadRequest('Invalid nickname: ' . $nickname);
149
+            }
150
+
151
+            // Forbid nicknames starting with a dot
152
+            if (str_starts_with($nickname, '.')) {
153
+                throw new BadRequest('Invalid nickname: ' . $nickname);
154
+            }
155
+
156
+            // If we have a nickname, let's put
157
+            // all files in the subfolder
158
+            $relativePath = '/' . $nickname . '/' . $relativePath;
159
+            $relativePath = str_replace('//', '/', $relativePath);
160
+        }
161
+
162
+        // Create the folders along the way
163
+        $folder = $node;
164
+        $pathSegments = $this->getPathSegments(dirname($relativePath));
165
+        foreach ($pathSegments as $pathSegment) {
166
+            if ($pathSegment === '') {
167
+                continue;
168
+            }
169
+
170
+            try {
171
+                // get the current folder
172
+                $currentFolder = $folder->get($pathSegment);
173
+                // check target is a folder
174
+                if ($currentFolder instanceof Folder) {
175
+                    $folder = $currentFolder;
176
+                } else {
177
+                    // otherwise look in the parent folder if we already create an unique folder name
178
+                    foreach ($folder->getDirectoryListing() as $child) {
179
+                        // we look for folders which match "NAME (SUFFIX)"
180
+                        if ($child instanceof Folder && str_starts_with($child->getName(), $pathSegment)) {
181
+                            $suffix = substr($child->getName(), strlen($pathSegment));
182
+                            if (preg_match('/^ \(\d+\)$/', $suffix)) {
183
+                                // we found the unique folder name and can use it
184
+                                $folder = $child;
185
+                                break;
186
+                            }
187
+                        }
188
+                    }
189
+                    // no folder found so we need to create a new unique folder name
190
+                    if (!isset($child) || $child !== $folder) {
191
+                        $folder = $folder->newFolder($folder->getNonExistingName($pathSegment));
192
+                    }
193
+                }
194
+            } catch (NotFoundException) {
195
+                // the folder does simply not exist so we create it
196
+                $folder = $folder->newFolder($pathSegment);
197
+            }
198
+        }
199
+
200
+        // Finally handle conflicts on the end files
201
+        $uniqueName = $folder->getNonExistingName(basename($relativePath));
202
+        $relativePath = substr($folder->getPath(), strlen($node->getPath()));
203
+        $path = '/files/' . $token . '/' . $relativePath . '/' . $uniqueName;
204
+        $url = rtrim($request->getBaseUrl(), '/') . str_replace('//', '/', $path);
205
+        if ($isChunkedUpload) {
206
+            $request->setHeader('destination', $url);
207
+        } else {
208
+            $request->setUrl($url);
209
+        }
210
+    }
211
+
212
+    private function getPathSegments(string $path): array {
213
+        // Normalize slashes and remove trailing slash
214
+        $path = trim(str_replace('\\', '/', $path), '/');
215
+
216
+        return explode('/', $path);
217
+    }
218 218
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -145,17 +145,17 @@  discard block
 block discarded – undo
145 145
 				$node->verifyPath($nickname);
146 146
 			} catch (\Exception $e) {
147 147
 				// If the path is not valid, we throw an exception
148
-				throw new BadRequest('Invalid nickname: ' . $nickname);
148
+				throw new BadRequest('Invalid nickname: '.$nickname);
149 149
 			}
150 150
 
151 151
 			// Forbid nicknames starting with a dot
152 152
 			if (str_starts_with($nickname, '.')) {
153
-				throw new BadRequest('Invalid nickname: ' . $nickname);
153
+				throw new BadRequest('Invalid nickname: '.$nickname);
154 154
 			}
155 155
 
156 156
 			// If we have a nickname, let's put
157 157
 			// all files in the subfolder
158
-			$relativePath = '/' . $nickname . '/' . $relativePath;
158
+			$relativePath = '/'.$nickname.'/'.$relativePath;
159 159
 			$relativePath = str_replace('//', '/', $relativePath);
160 160
 		}
161 161
 
@@ -200,8 +200,8 @@  discard block
 block discarded – undo
200 200
 		// Finally handle conflicts on the end files
201 201
 		$uniqueName = $folder->getNonExistingName(basename($relativePath));
202 202
 		$relativePath = substr($folder->getPath(), strlen($node->getPath()));
203
-		$path = '/files/' . $token . '/' . $relativePath . '/' . $uniqueName;
204
-		$url = rtrim($request->getBaseUrl(), '/') . str_replace('//', '/', $path);
203
+		$path = '/files/'.$token.'/'.$relativePath.'/'.$uniqueName;
204
+		$url = rtrim($request->getBaseUrl(), '/').str_replace('//', '/', $path);
205 205
 		if ($isChunkedUpload) {
206 206
 			$request->setHeader('destination', $url);
207 207
 		} else {
Please login to merge, or discard this patch.
build/integration/features/bootstrap/FilesDropContext.php 1 patch
Indentation   +68 added lines, -68 removed lines patch added patch discarded remove patch
@@ -11,72 +11,72 @@
 block discarded – undo
11 11
 require __DIR__ . '/../../vendor/autoload.php';
12 12
 
13 13
 class FilesDropContext implements Context, SnippetAcceptingContext {
14
-	use WebDav;
15
-
16
-	/**
17
-	 * @When Dropping file :path with :content
18
-	 */
19
-	public function droppingFileWith($path, $content, $nickname = null) {
20
-		$client = new Client();
21
-		$options = [];
22
-		if (count($this->lastShareData->data->element) > 0) {
23
-			$token = $this->lastShareData->data[0]->token;
24
-		} else {
25
-			$token = $this->lastShareData->data[0]->token;
26
-		}
27
-
28
-		$base = substr($this->baseUrl, 0, -4);
29
-		$fullUrl = str_replace('//', '/', $base . "/public.php/dav/files/$token/$path");
30
-
31
-		$options['headers'] = [
32
-			'X-REQUESTED-WITH' => 'XMLHttpRequest',
33
-		];
34
-
35
-		if ($nickname) {
36
-			$options['headers']['X-NC-NICKNAME'] = $nickname;
37
-		}
38
-
39
-		$options['body'] = \GuzzleHttp\Psr7\Utils::streamFor($content);
40
-
41
-		try {
42
-			$this->response = $client->request('PUT', $fullUrl, $options);
43
-		} catch (\GuzzleHttp\Exception\ClientException $e) {
44
-			$this->response = $e->getResponse();
45
-		}
46
-	}
47
-
48
-
49
-	/**
50
-	 * @When Dropping file :path with :content as :nickName
51
-	 */
52
-	public function droppingFileWithAs($path, $content, $nickname) {
53
-		$this->droppingFileWith($path, $content, $nickname);
54
-	}
55
-
56
-
57
-	/**
58
-	 * @When Creating folder :folder in drop
59
-	 */
60
-	public function creatingFolderInDrop($folder) {
61
-		$client = new Client();
62
-		$options = [];
63
-		if (count($this->lastShareData->data->element) > 0) {
64
-			$token = $this->lastShareData->data[0]->token;
65
-		} else {
66
-			$token = $this->lastShareData->data[0]->token;
67
-		}
68
-
69
-		$base = substr($this->baseUrl, 0, -4);
70
-		$fullUrl = str_replace('//', '/', $base . "/public.php/dav/files/$token/$folder");
71
-
72
-		$options['headers'] = [
73
-			'X-REQUESTED-WITH' => 'XMLHttpRequest',
74
-		];
75
-
76
-		try {
77
-			$this->response = $client->request('MKCOL', $fullUrl, $options);
78
-		} catch (\GuzzleHttp\Exception\ClientException $e) {
79
-			$this->response = $e->getResponse();
80
-		}
81
-	}
14
+    use WebDav;
15
+
16
+    /**
17
+     * @When Dropping file :path with :content
18
+     */
19
+    public function droppingFileWith($path, $content, $nickname = null) {
20
+        $client = new Client();
21
+        $options = [];
22
+        if (count($this->lastShareData->data->element) > 0) {
23
+            $token = $this->lastShareData->data[0]->token;
24
+        } else {
25
+            $token = $this->lastShareData->data[0]->token;
26
+        }
27
+
28
+        $base = substr($this->baseUrl, 0, -4);
29
+        $fullUrl = str_replace('//', '/', $base . "/public.php/dav/files/$token/$path");
30
+
31
+        $options['headers'] = [
32
+            'X-REQUESTED-WITH' => 'XMLHttpRequest',
33
+        ];
34
+
35
+        if ($nickname) {
36
+            $options['headers']['X-NC-NICKNAME'] = $nickname;
37
+        }
38
+
39
+        $options['body'] = \GuzzleHttp\Psr7\Utils::streamFor($content);
40
+
41
+        try {
42
+            $this->response = $client->request('PUT', $fullUrl, $options);
43
+        } catch (\GuzzleHttp\Exception\ClientException $e) {
44
+            $this->response = $e->getResponse();
45
+        }
46
+    }
47
+
48
+
49
+    /**
50
+     * @When Dropping file :path with :content as :nickName
51
+     */
52
+    public function droppingFileWithAs($path, $content, $nickname) {
53
+        $this->droppingFileWith($path, $content, $nickname);
54
+    }
55
+
56
+
57
+    /**
58
+     * @When Creating folder :folder in drop
59
+     */
60
+    public function creatingFolderInDrop($folder) {
61
+        $client = new Client();
62
+        $options = [];
63
+        if (count($this->lastShareData->data->element) > 0) {
64
+            $token = $this->lastShareData->data[0]->token;
65
+        } else {
66
+            $token = $this->lastShareData->data[0]->token;
67
+        }
68
+
69
+        $base = substr($this->baseUrl, 0, -4);
70
+        $fullUrl = str_replace('//', '/', $base . "/public.php/dav/files/$token/$folder");
71
+
72
+        $options['headers'] = [
73
+            'X-REQUESTED-WITH' => 'XMLHttpRequest',
74
+        ];
75
+
76
+        try {
77
+            $this->response = $client->request('MKCOL', $fullUrl, $options);
78
+        } catch (\GuzzleHttp\Exception\ClientException $e) {
79
+            $this->response = $e->getResponse();
80
+        }
81
+    }
82 82
 }
Please login to merge, or discard this patch.