Passed
Pull Request — master (#549)
by Matias
07:06 queued 04:58
created

DavPlugin::getPluginName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 2
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @copyright Copyright (c) 2021 Matias De lellis <[email protected]>
7
 *
8
 * @author Matias De lellis <[email protected]>
9
 *
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
namespace OCA\FaceRecognition\Dav;
28
29
use OCA\DAV\Connector\Sabre\Directory;
0 ignored issues
show
Bug introduced by
The type OCA\DAV\Connector\Sabre\Directory was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
30
31
use Sabre\DAV\INode;
0 ignored issues
show
Bug introduced by
The type Sabre\DAV\INode was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
use Sabre\DAV\PropFind;
0 ignored issues
show
Bug introduced by
The type Sabre\DAV\PropFind was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
use Sabre\DAV\Server;
0 ignored issues
show
Bug introduced by
The type Sabre\DAV\Server was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use Sabre\DAV\ServerPlugin;
0 ignored issues
show
Bug introduced by
The type Sabre\DAV\ServerPlugin was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
35
use Sabre\DAV\Xml\Element\Response;
0 ignored issues
show
Bug introduced by
The type Sabre\DAV\Xml\Element\Response was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
36
use Sabre\DAV\Xml\Response\MultiStatus;
0 ignored issues
show
Bug introduced by
The type Sabre\DAV\Xml\Response\MultiStatus was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
37
38
use Sabre\DAV\Exception\BadRequest;
0 ignored issues
show
Bug introduced by
The type Sabre\DAV\Exception\BadRequest was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
39
40
use OCA\FaceRecognition\AppInfo\Application;
41
use OCA\FaceRecognition\Service\DavService;
42
43
class DavPlugin extends ServerPlugin {
44
45
	/**
46
	 * Reference to main server object
47
	 *
48
	 * @var \Sabre\DAV\Server
49
	 */
50
	private $server;
51
52
	/**
53
	 * Initializes the plugin and registers event handlers
54
	 *
55
	 * @param Server $server
56
	 * @return void
57
	 */
58
	public function initialize(Server $server) {
59
		$server->xml->namespaceMap[Application::DAV_NS_FACE_RECOGNITION] = 'fr';
60
61
		$this->server = $server;
62
		$this->server->on('propFind', [$this, 'onPropFind']);
63
		$this->server->on('report', [$this, 'onReport']);
64
	}
65
66
	/**
67
	 * @param PropFind $propFind
68
	 * @param INode $node
69
	 */
70
	public function onPropFind(PropFind $propFind, INode $node) {
71
		// we instantiate the DavService here to make sure sabre auth backend was triggered
72
		$davService = \OC::$server->get(DavService::class);
73
		$davService->propFind($propFind, $node);
74
	}
75
76
	/**
77
	 * REPORT operations to look for files
78
	 *
79
	 * @param string $reportName
80
	 * @param $report
81
	 * @param string $uri
82
	 * @return bool
83
	 * @throws BadRequest
84
	 * @internal param $ [] $report
85
	 */
86
	public function onReport($reportName, $report, $uri) {
87
		if ($reportName !== Application::DAV_REPORT_FILES) {
88
			return;
89
		}
90
91
		$reportTargetNode = $this->server->tree->getNodeForPath($uri);
92
		if (!$reportTargetNode instanceof Directory) {
93
			return;
94
		}
95
96
		$requestedProps = [];
97
		$filterRules = [];
98
99
		// parse report properties and gather filter info
100
		foreach ($report as $reportProps) {
101
			$name = $reportProps['name'];
102
			if ($name === Application::DAV_REPORT_FILTER_RULES) {
103
				$filterRules = $reportProps['value'];
104
			} elseif ($name === '{DAV:}prop') {
105
				// propfind properties
106
				foreach ($reportProps['value'] as $propVal) {
107
					$requestedProps[] = $propVal['name'];
108
				}
109
			}
110
		}
111
112
		if (empty($filterRules)) {
113
			throw new BadRequest('Missing filter-name block in request');
114
		}
115
116
		// gather all sabre nodes matching filter
117
		$results = $this->processFilterRules($filterRules);
118
119
		$filesUri = $this->getFilesBaseUri($uri, $reportTargetNode->getPath());
120
		$responses = $this->prepareResponses($filesUri, $requestedProps, $results);
121
122
		$xml = $this->server->xml->write(
123
			'{DAV:}multistatus',
124
			new MultiStatus($responses)
125
		);
126
127
		$this->server->httpResponse->setStatus(207);
128
		$this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
129
		$this->server->httpResponse->setBody($xml);
130
131
		return false;
132
	}
133
134
	/**
135
	 * Find sabre nodes matching the given filter rules
136
	 *
137
	 * @param array $filterRules
138
	 * @return array array of unique sabre nodes.
139
	 */
140
	protected function processFilterRules($filterRules): array {
141
		$namedFilter = [];
142
		foreach ($filterRules as $filterRule) {
143
			if ($filterRule['name'] === Application::DAV_REPORT_FILTER_NAME) {
144
				$namedFilter[] = $filterRule['value'];
145
			}
146
		}
147
148
		// we instantiate the DavService here to make sure sabre auth backend was triggered
149
		$davService = \OC::$server->get(DavService::class);
150
		return $davService->getFilesNamedFilter($namedFilter);
151
	}
152
153
	/**
154
	 * Returns a plugin name.
155
	 *
156
	 * Using this name other plugins will be able to access other plugins
157
	 * using \Sabre\DAV\Server::getPlugin
158
	 *
159
	 * @return string
160
	 */
161
	public function getPluginName(): string {
162
		return Application::APP_NAME;
163
	}
164
165
	/**
166
	 * Returns a list of reports this plugin supports.
167
	 *
168
	 * This will be used in the {DAV:}supported-report-set property.
169
	 *
170
	 * @param string $uri
171
	 * @return array
172
	 */
173
	public function getSupportedReportSet($uri) {
174
		return [Application::DAV_REPORT_FILES];
175
	}
176
177
	/**
178
	 * Returns a bunch of meta-data about the plugin.
179
	 *
180
	 * Providing this information is optional, and is mainly displayed by the
181
	 * Browser plugin.
182
	 *
183
	 * The description key in the returned array may contain html and will not
184
	 * be sanitized.
185
	 *
186
	 * @return array
187
	 */
188
	public function getPluginInfo(): array {
189
		return [
190
			'name'        => $this->getPluginName(),
191
			'description' => 'Provides information on Face Recognition in PROPFIND WebDav requests',
192
		];
193
	}
194
195
	/**
196
	 * Returns the base uri of the files root by removing
197
	 * the subpath from the URI
198
	 *
199
	 * @param string $uri URI from this request
200
	 * @param string $subPath subpath to remove from the URI
201
	 *
202
	 * @return string files base uri
203
	 */
204
	private function getFilesBaseUri(string $uri, string $subPath): string {
205
		$uri = trim($uri, '/');
206
		$subPath = trim($subPath, '/');
207
		if (empty($subPath)) {
208
			$filesUri = $uri;
209
		} else {
210
			$filesUri = substr($uri, 0, strlen($uri) - strlen($subPath));
211
		}
212
		$filesUri = trim($filesUri, '/');
213
		if (empty($filesUri)) {
214
			return '';
215
		}
216
		return '/' . $filesUri;
217
	}
218
219
	/**
220
	 * Prepare propfind response for the given nodes
221
	 *
222
	 * @param string $filesUri $filesUri URI leading to root of the files URI,
223
	 * with a leading slash but no trailing slash
224
	 * @param string[] $requestedProps requested properties
225
	 * @param Node[] nodes nodes for which to fetch and prepare responses
0 ignored issues
show
Bug introduced by
The type OCA\FaceRecognition\Dav\nodes was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
226
	 * @return Response[]
227
	 */
228
	private function prepareResponses($filesUri, $requestedProps, $nodes): array {
229
		$responses = [];
230
		foreach ($nodes as $node) {
231
			$propFind = new PropFind($filesUri . $node->getPath(), $requestedProps);
232
233
			$this->server->getPropertiesByNode($propFind, $node);
234
			// copied from Sabre Server's getPropertiesForPath
235
			$result = $propFind->getResultForMultiStatus();
236
			$result['href'] = $propFind->getPath();
237
238
			$resourceType = $this->server->getResourceTypeForNode($node);
239
			if (in_array('{DAV:}collection', $resourceType) || in_array('{DAV:}principal', $resourceType)) {
240
				$result['href'] .= '/';
241
			}
242
243
			$responses[] = new Response(
244
				rtrim($this->server->getBaseUri(), '/') . $filesUri . $node->getPath(),
245
				$result,
246
				200
247
			);
248
		}
249
		return $responses;
250
	}
251
252
}
253