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