Completed
Pull Request — master (#4500)
by Joas
58:15 queued 44:40
created
apps/dav/lib/Connector/Sabre/FilesPlugin.php 1 patch
Indentation   +388 added lines, -388 removed lines patch added patch discarded remove patch
@@ -48,392 +48,392 @@
 block discarded – undo
48 48
 
49 49
 class FilesPlugin extends ServerPlugin {
50 50
 
51
-	// namespace
52
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
53
-	const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
54
-	const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
55
-	const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
56
-	const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
57
-	const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
58
-	const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
59
-	const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
60
-	const GETETAG_PROPERTYNAME = '{DAV:}getetag';
61
-	const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
62
-	const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
63
-	const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
64
-	const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
65
-	const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
66
-	const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
67
-
68
-	/**
69
-	 * Reference to main server object
70
-	 *
71
-	 * @var \Sabre\DAV\Server
72
-	 */
73
-	private $server;
74
-
75
-	/**
76
-	 * @var Tree
77
-	 */
78
-	private $tree;
79
-
80
-	/**
81
-	 * Whether this is public webdav.
82
-	 * If true, some returned information will be stripped off.
83
-	 *
84
-	 * @var bool
85
-	 */
86
-	private $isPublic;
87
-
88
-	/**
89
-	 * @var View
90
-	 */
91
-	private $fileView;
92
-
93
-	/**
94
-	 * @var bool
95
-	 */
96
-	private $downloadAttachment;
97
-
98
-	/**
99
-	 * @var IConfig
100
-	 */
101
-	private $config;
102
-
103
-	/**
104
-	 * @var IRequest
105
-	 */
106
-	private $request;
107
-
108
-	/**
109
-	 * @var IPreview
110
-	 */
111
-	private $previewManager;
112
-
113
-	/**
114
-	 * @param Tree $tree
115
-	 * @param IConfig $config
116
-	 * @param IRequest $request
117
-	 * @param IPreview $previewManager
118
-	 * @param bool $isPublic
119
-	 * @param bool $downloadAttachment
120
-	 */
121
-	public function __construct(Tree $tree,
122
-								IConfig $config,
123
-								IRequest $request,
124
-								IPreview $previewManager,
125
-								$isPublic = false,
126
-								$downloadAttachment = true) {
127
-		$this->tree = $tree;
128
-		$this->config = $config;
129
-		$this->request = $request;
130
-		$this->isPublic = $isPublic;
131
-		$this->downloadAttachment = $downloadAttachment;
132
-		$this->previewManager = $previewManager;
133
-	}
134
-
135
-	/**
136
-	 * This initializes the plugin.
137
-	 *
138
-	 * This function is called by \Sabre\DAV\Server, after
139
-	 * addPlugin is called.
140
-	 *
141
-	 * This method should set up the required event subscriptions.
142
-	 *
143
-	 * @param \Sabre\DAV\Server $server
144
-	 * @return void
145
-	 */
146
-	public function initialize(\Sabre\DAV\Server $server) {
147
-
148
-		$server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
149
-		$server->xml->namespaceMap[self::NS_NEXTCLOUD] = 'nc';
150
-		$server->protectedProperties[] = self::FILEID_PROPERTYNAME;
151
-		$server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
152
-		$server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
153
-		$server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
154
-		$server->protectedProperties[] = self::SIZE_PROPERTYNAME;
155
-		$server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
156
-		$server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
157
-		$server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
158
-		$server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
159
-		$server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
160
-		$server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
161
-
162
-		// normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
163
-		$allowedProperties = ['{DAV:}getetag'];
164
-		$server->protectedProperties = array_diff($server->protectedProperties, $allowedProperties);
165
-
166
-		$this->server = $server;
167
-		$this->server->on('propFind', array($this, 'handleGetProperties'));
168
-		$this->server->on('propPatch', array($this, 'handleUpdateProperties'));
169
-		$this->server->on('afterBind', array($this, 'sendFileIdHeader'));
170
-		$this->server->on('afterWriteContent', array($this, 'sendFileIdHeader'));
171
-		$this->server->on('afterMethod:GET', [$this,'httpGet']);
172
-		$this->server->on('afterMethod:GET', array($this, 'handleDownloadToken'));
173
-		$this->server->on('afterResponse', function($request, ResponseInterface $response) {
174
-			$body = $response->getBody();
175
-			if (is_resource($body)) {
176
-				fclose($body);
177
-			}
178
-		});
179
-		$this->server->on('beforeMove', [$this, 'checkMove']);
180
-	}
181
-
182
-	/**
183
-	 * Plugin that checks if a move can actually be performed.
184
-	 *
185
-	 * @param string $source source path
186
-	 * @param string $destination destination path
187
-	 * @throws Forbidden
188
-	 * @throws NotFound
189
-	 */
190
-	function checkMove($source, $destination) {
191
-		$sourceNode = $this->tree->getNodeForPath($source);
192
-		if (!$sourceNode instanceof Node) {
193
-			return;
194
-		}
195
-		list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($source);
196
-		list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destination);
197
-
198
-		if ($sourceDir !== $destinationDir) {
199
-			$sourceNodeFileInfo = $sourceNode->getFileInfo();
200
-			if (is_null($sourceNodeFileInfo)) {
201
-				throw new NotFound($source . ' does not exist');
202
-			}
203
-
204
-			if (!$sourceNodeFileInfo->isDeletable()) {
205
-				throw new Forbidden($source . " cannot be deleted");
206
-			}
207
-		}
208
-	}
209
-
210
-	/**
211
-	 * This sets a cookie to be able to recognize the start of the download
212
-	 * the content must not be longer than 32 characters and must only contain
213
-	 * alphanumeric characters
214
-	 *
215
-	 * @param RequestInterface $request
216
-	 * @param ResponseInterface $response
217
-	 */
218
-	function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
219
-		$queryParams = $request->getQueryParameters();
220
-
221
-		/**
222
-		 * this sets a cookie to be able to recognize the start of the download
223
-		 * the content must not be longer than 32 characters and must only contain
224
-		 * alphanumeric characters
225
-		 */
226
-		if (isset($queryParams['downloadStartSecret'])) {
227
-			$token = $queryParams['downloadStartSecret'];
228
-			if (!isset($token[32])
229
-				&& preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
230
-				// FIXME: use $response->setHeader() instead
231
-				setcookie('ocDownloadStarted', $token, time() + 20, '/');
232
-			}
233
-		}
234
-	}
235
-
236
-	/**
237
-	 * Add headers to file download
238
-	 *
239
-	 * @param RequestInterface $request
240
-	 * @param ResponseInterface $response
241
-	 */
242
-	function httpGet(RequestInterface $request, ResponseInterface $response) {
243
-		// Only handle valid files
244
-		$node = $this->tree->getNodeForPath($request->getPath());
245
-		if (!($node instanceof IFile)) return;
246
-
247
-		// adds a 'Content-Disposition: attachment' header in case no disposition
248
-		// header has been set before
249
-		if ($this->downloadAttachment &&
250
-			$response->getHeader('Content-Disposition') === null) {
251
-			$filename = $node->getName();
252
-			if ($this->request->isUserAgent(
253
-				[
254
-					\OC\AppFramework\Http\Request::USER_AGENT_IE,
255
-					\OC\AppFramework\Http\Request::USER_AGENT_ANDROID_MOBILE_CHROME,
256
-					\OC\AppFramework\Http\Request::USER_AGENT_FREEBOX,
257
-				])) {
258
-				$response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
259
-			} else {
260
-				$response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
261
-													 . '; filename="' . rawurlencode($filename) . '"');
262
-			}
263
-		}
264
-
265
-		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
266
-			//Add OC-Checksum header
267
-			/** @var $node File */
268
-			$checksum = $node->getChecksum();
269
-			if ($checksum !== null && $checksum !== '') {
270
-				$response->addHeader('OC-Checksum', $checksum);
271
-			}
272
-		}
273
-	}
274
-
275
-	/**
276
-	 * Adds all ownCloud-specific properties
277
-	 *
278
-	 * @param PropFind $propFind
279
-	 * @param \Sabre\DAV\INode $node
280
-	 * @return void
281
-	 */
282
-	public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
283
-
284
-		$httpRequest = $this->server->httpRequest;
285
-
286
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
287
-
288
-			$propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) {
289
-				return $node->getFileId();
290
-			});
291
-
292
-			$propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) {
293
-				return $node->getInternalFileId();
294
-			});
295
-
296
-			$propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) {
297
-				$perms = $node->getDavPermissions();
298
-				if ($this->isPublic) {
299
-					// remove mount information
300
-					$perms = str_replace(['S', 'M'], '', $perms);
301
-				}
302
-				return $perms;
303
-			});
304
-
305
-			$propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
306
-				return $node->getSharePermissions(
307
-					$httpRequest->getRawServerValue('PHP_AUTH_USER')
308
-				);
309
-			});
310
-
311
-			$propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) {
312
-				return $node->getETag();
313
-			});
314
-
315
-			$propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) {
316
-				$owner = $node->getOwner();
317
-				if (!$owner) {
318
-					return null;
319
-				} else {
320
-					return $owner->getUID();
321
-				}
322
-			});
323
-			$propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) {
324
-				$owner = $node->getOwner();
325
-				if (!$owner) {
326
-					return null;
327
-				} else {
328
-					return $owner->getDisplayName();
329
-				}
330
-			});
331
-
332
-			$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
333
-				return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
334
-			});
335
-			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
336
-				return $node->getSize();
337
-			});
338
-		}
339
-
340
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
341
-			$propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
342
-				return $this->config->getSystemValue('data-fingerprint', '');
343
-			});
344
-		}
345
-
346
-		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
347
-			$propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
348
-				/** @var $node \OCA\DAV\Connector\Sabre\File */
349
-				try {
350
-					$directDownloadUrl = $node->getDirectDownload();
351
-					if (isset($directDownloadUrl['url'])) {
352
-						return $directDownloadUrl['url'];
353
-					}
354
-				} catch (StorageNotAvailableException $e) {
355
-					return false;
356
-				} catch (ForbiddenException $e) {
357
-					return false;
358
-				}
359
-				return false;
360
-			});
361
-
362
-			$propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
363
-				$checksum = $node->getChecksum();
364
-				if ($checksum === NULL || $checksum === '') {
365
-					return null;
366
-				}
367
-
368
-				return new ChecksumList($checksum);
369
-			});
370
-
371
-		}
372
-
373
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
374
-			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
375
-				return $node->getSize();
376
-			});
377
-		}
378
-	}
379
-
380
-	/**
381
-	 * Update ownCloud-specific properties
382
-	 *
383
-	 * @param string $path
384
-	 * @param PropPatch $propPatch
385
-	 *
386
-	 * @return void
387
-	 */
388
-	public function handleUpdateProperties($path, PropPatch $propPatch) {
389
-		$node = $this->tree->getNodeForPath($path);
390
-		if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
391
-			return;
392
-		}
393
-
394
-		$propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function($time) use ($node) {
395
-			if (empty($time)) {
396
-				return false;
397
-			}
398
-			$node->touch($time);
399
-			return true;
400
-		});
401
-		$propPatch->handle(self::GETETAG_PROPERTYNAME, function($etag) use ($node) {
402
-			if (empty($etag)) {
403
-				return false;
404
-			}
405
-			if ($node->setEtag($etag) !== -1) {
406
-				return true;
407
-			}
408
-			return false;
409
-		});
410
-	}
411
-
412
-	/**
413
-	 * @param string $filePath
414
-	 * @param \Sabre\DAV\INode $node
415
-	 * @throws \Sabre\DAV\Exception\BadRequest
416
-	 */
417
-	public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
418
-		// chunked upload handling
419
-		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
420
-			list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath);
421
-			$info = \OC_FileChunking::decodeName($name);
422
-			if (!empty($info)) {
423
-				$filePath = $path . '/' . $info['name'];
424
-			}
425
-		}
426
-
427
-		// we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
428
-		if (!$this->server->tree->nodeExists($filePath)) {
429
-			return;
430
-		}
431
-		$node = $this->server->tree->getNodeForPath($filePath);
432
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
433
-			$fileId = $node->getFileId();
434
-			if (!is_null($fileId)) {
435
-				$this->server->httpResponse->setHeader('OC-FileId', $fileId);
436
-			}
437
-		}
438
-	}
51
+    // namespace
52
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
53
+    const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
54
+    const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
55
+    const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
56
+    const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
57
+    const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
58
+    const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
59
+    const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
60
+    const GETETAG_PROPERTYNAME = '{DAV:}getetag';
61
+    const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
62
+    const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
63
+    const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
64
+    const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
65
+    const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
66
+    const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
67
+
68
+    /**
69
+     * Reference to main server object
70
+     *
71
+     * @var \Sabre\DAV\Server
72
+     */
73
+    private $server;
74
+
75
+    /**
76
+     * @var Tree
77
+     */
78
+    private $tree;
79
+
80
+    /**
81
+     * Whether this is public webdav.
82
+     * If true, some returned information will be stripped off.
83
+     *
84
+     * @var bool
85
+     */
86
+    private $isPublic;
87
+
88
+    /**
89
+     * @var View
90
+     */
91
+    private $fileView;
92
+
93
+    /**
94
+     * @var bool
95
+     */
96
+    private $downloadAttachment;
97
+
98
+    /**
99
+     * @var IConfig
100
+     */
101
+    private $config;
102
+
103
+    /**
104
+     * @var IRequest
105
+     */
106
+    private $request;
107
+
108
+    /**
109
+     * @var IPreview
110
+     */
111
+    private $previewManager;
112
+
113
+    /**
114
+     * @param Tree $tree
115
+     * @param IConfig $config
116
+     * @param IRequest $request
117
+     * @param IPreview $previewManager
118
+     * @param bool $isPublic
119
+     * @param bool $downloadAttachment
120
+     */
121
+    public function __construct(Tree $tree,
122
+                                IConfig $config,
123
+                                IRequest $request,
124
+                                IPreview $previewManager,
125
+                                $isPublic = false,
126
+                                $downloadAttachment = true) {
127
+        $this->tree = $tree;
128
+        $this->config = $config;
129
+        $this->request = $request;
130
+        $this->isPublic = $isPublic;
131
+        $this->downloadAttachment = $downloadAttachment;
132
+        $this->previewManager = $previewManager;
133
+    }
134
+
135
+    /**
136
+     * This initializes the plugin.
137
+     *
138
+     * This function is called by \Sabre\DAV\Server, after
139
+     * addPlugin is called.
140
+     *
141
+     * This method should set up the required event subscriptions.
142
+     *
143
+     * @param \Sabre\DAV\Server $server
144
+     * @return void
145
+     */
146
+    public function initialize(\Sabre\DAV\Server $server) {
147
+
148
+        $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
149
+        $server->xml->namespaceMap[self::NS_NEXTCLOUD] = 'nc';
150
+        $server->protectedProperties[] = self::FILEID_PROPERTYNAME;
151
+        $server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
152
+        $server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
153
+        $server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
154
+        $server->protectedProperties[] = self::SIZE_PROPERTYNAME;
155
+        $server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
156
+        $server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
157
+        $server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
158
+        $server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
159
+        $server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
160
+        $server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
161
+
162
+        // normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
163
+        $allowedProperties = ['{DAV:}getetag'];
164
+        $server->protectedProperties = array_diff($server->protectedProperties, $allowedProperties);
165
+
166
+        $this->server = $server;
167
+        $this->server->on('propFind', array($this, 'handleGetProperties'));
168
+        $this->server->on('propPatch', array($this, 'handleUpdateProperties'));
169
+        $this->server->on('afterBind', array($this, 'sendFileIdHeader'));
170
+        $this->server->on('afterWriteContent', array($this, 'sendFileIdHeader'));
171
+        $this->server->on('afterMethod:GET', [$this,'httpGet']);
172
+        $this->server->on('afterMethod:GET', array($this, 'handleDownloadToken'));
173
+        $this->server->on('afterResponse', function($request, ResponseInterface $response) {
174
+            $body = $response->getBody();
175
+            if (is_resource($body)) {
176
+                fclose($body);
177
+            }
178
+        });
179
+        $this->server->on('beforeMove', [$this, 'checkMove']);
180
+    }
181
+
182
+    /**
183
+     * Plugin that checks if a move can actually be performed.
184
+     *
185
+     * @param string $source source path
186
+     * @param string $destination destination path
187
+     * @throws Forbidden
188
+     * @throws NotFound
189
+     */
190
+    function checkMove($source, $destination) {
191
+        $sourceNode = $this->tree->getNodeForPath($source);
192
+        if (!$sourceNode instanceof Node) {
193
+            return;
194
+        }
195
+        list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($source);
196
+        list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destination);
197
+
198
+        if ($sourceDir !== $destinationDir) {
199
+            $sourceNodeFileInfo = $sourceNode->getFileInfo();
200
+            if (is_null($sourceNodeFileInfo)) {
201
+                throw new NotFound($source . ' does not exist');
202
+            }
203
+
204
+            if (!$sourceNodeFileInfo->isDeletable()) {
205
+                throw new Forbidden($source . " cannot be deleted");
206
+            }
207
+        }
208
+    }
209
+
210
+    /**
211
+     * This sets a cookie to be able to recognize the start of the download
212
+     * the content must not be longer than 32 characters and must only contain
213
+     * alphanumeric characters
214
+     *
215
+     * @param RequestInterface $request
216
+     * @param ResponseInterface $response
217
+     */
218
+    function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
219
+        $queryParams = $request->getQueryParameters();
220
+
221
+        /**
222
+         * this sets a cookie to be able to recognize the start of the download
223
+         * the content must not be longer than 32 characters and must only contain
224
+         * alphanumeric characters
225
+         */
226
+        if (isset($queryParams['downloadStartSecret'])) {
227
+            $token = $queryParams['downloadStartSecret'];
228
+            if (!isset($token[32])
229
+                && preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
230
+                // FIXME: use $response->setHeader() instead
231
+                setcookie('ocDownloadStarted', $token, time() + 20, '/');
232
+            }
233
+        }
234
+    }
235
+
236
+    /**
237
+     * Add headers to file download
238
+     *
239
+     * @param RequestInterface $request
240
+     * @param ResponseInterface $response
241
+     */
242
+    function httpGet(RequestInterface $request, ResponseInterface $response) {
243
+        // Only handle valid files
244
+        $node = $this->tree->getNodeForPath($request->getPath());
245
+        if (!($node instanceof IFile)) return;
246
+
247
+        // adds a 'Content-Disposition: attachment' header in case no disposition
248
+        // header has been set before
249
+        if ($this->downloadAttachment &&
250
+            $response->getHeader('Content-Disposition') === null) {
251
+            $filename = $node->getName();
252
+            if ($this->request->isUserAgent(
253
+                [
254
+                    \OC\AppFramework\Http\Request::USER_AGENT_IE,
255
+                    \OC\AppFramework\Http\Request::USER_AGENT_ANDROID_MOBILE_CHROME,
256
+                    \OC\AppFramework\Http\Request::USER_AGENT_FREEBOX,
257
+                ])) {
258
+                $response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
259
+            } else {
260
+                $response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
261
+                                                        . '; filename="' . rawurlencode($filename) . '"');
262
+            }
263
+        }
264
+
265
+        if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
266
+            //Add OC-Checksum header
267
+            /** @var $node File */
268
+            $checksum = $node->getChecksum();
269
+            if ($checksum !== null && $checksum !== '') {
270
+                $response->addHeader('OC-Checksum', $checksum);
271
+            }
272
+        }
273
+    }
274
+
275
+    /**
276
+     * Adds all ownCloud-specific properties
277
+     *
278
+     * @param PropFind $propFind
279
+     * @param \Sabre\DAV\INode $node
280
+     * @return void
281
+     */
282
+    public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
283
+
284
+        $httpRequest = $this->server->httpRequest;
285
+
286
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
287
+
288
+            $propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) {
289
+                return $node->getFileId();
290
+            });
291
+
292
+            $propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) {
293
+                return $node->getInternalFileId();
294
+            });
295
+
296
+            $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) {
297
+                $perms = $node->getDavPermissions();
298
+                if ($this->isPublic) {
299
+                    // remove mount information
300
+                    $perms = str_replace(['S', 'M'], '', $perms);
301
+                }
302
+                return $perms;
303
+            });
304
+
305
+            $propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
306
+                return $node->getSharePermissions(
307
+                    $httpRequest->getRawServerValue('PHP_AUTH_USER')
308
+                );
309
+            });
310
+
311
+            $propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) {
312
+                return $node->getETag();
313
+            });
314
+
315
+            $propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) {
316
+                $owner = $node->getOwner();
317
+                if (!$owner) {
318
+                    return null;
319
+                } else {
320
+                    return $owner->getUID();
321
+                }
322
+            });
323
+            $propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) {
324
+                $owner = $node->getOwner();
325
+                if (!$owner) {
326
+                    return null;
327
+                } else {
328
+                    return $owner->getDisplayName();
329
+                }
330
+            });
331
+
332
+            $propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
333
+                return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
334
+            });
335
+            $propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
336
+                return $node->getSize();
337
+            });
338
+        }
339
+
340
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
341
+            $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
342
+                return $this->config->getSystemValue('data-fingerprint', '');
343
+            });
344
+        }
345
+
346
+        if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
347
+            $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
348
+                /** @var $node \OCA\DAV\Connector\Sabre\File */
349
+                try {
350
+                    $directDownloadUrl = $node->getDirectDownload();
351
+                    if (isset($directDownloadUrl['url'])) {
352
+                        return $directDownloadUrl['url'];
353
+                    }
354
+                } catch (StorageNotAvailableException $e) {
355
+                    return false;
356
+                } catch (ForbiddenException $e) {
357
+                    return false;
358
+                }
359
+                return false;
360
+            });
361
+
362
+            $propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
363
+                $checksum = $node->getChecksum();
364
+                if ($checksum === NULL || $checksum === '') {
365
+                    return null;
366
+                }
367
+
368
+                return new ChecksumList($checksum);
369
+            });
370
+
371
+        }
372
+
373
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
374
+            $propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
375
+                return $node->getSize();
376
+            });
377
+        }
378
+    }
379
+
380
+    /**
381
+     * Update ownCloud-specific properties
382
+     *
383
+     * @param string $path
384
+     * @param PropPatch $propPatch
385
+     *
386
+     * @return void
387
+     */
388
+    public function handleUpdateProperties($path, PropPatch $propPatch) {
389
+        $node = $this->tree->getNodeForPath($path);
390
+        if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
391
+            return;
392
+        }
393
+
394
+        $propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function($time) use ($node) {
395
+            if (empty($time)) {
396
+                return false;
397
+            }
398
+            $node->touch($time);
399
+            return true;
400
+        });
401
+        $propPatch->handle(self::GETETAG_PROPERTYNAME, function($etag) use ($node) {
402
+            if (empty($etag)) {
403
+                return false;
404
+            }
405
+            if ($node->setEtag($etag) !== -1) {
406
+                return true;
407
+            }
408
+            return false;
409
+        });
410
+    }
411
+
412
+    /**
413
+     * @param string $filePath
414
+     * @param \Sabre\DAV\INode $node
415
+     * @throws \Sabre\DAV\Exception\BadRequest
416
+     */
417
+    public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
418
+        // chunked upload handling
419
+        if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
420
+            list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath);
421
+            $info = \OC_FileChunking::decodeName($name);
422
+            if (!empty($info)) {
423
+                $filePath = $path . '/' . $info['name'];
424
+            }
425
+        }
426
+
427
+        // we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
428
+        if (!$this->server->tree->nodeExists($filePath)) {
429
+            return;
430
+        }
431
+        $node = $this->server->tree->getNodeForPath($filePath);
432
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
433
+            $fileId = $node->getFileId();
434
+            if (!is_null($fileId)) {
435
+                $this->server->httpResponse->setHeader('OC-FileId', $fileId);
436
+            }
437
+        }
438
+    }
439 439
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/TagsPlugin.php 2 patches
Indentation   +218 added lines, -218 removed lines patch added patch discarded remove patch
@@ -49,247 +49,247 @@
 block discarded – undo
49 49
 class TagsPlugin extends \Sabre\DAV\ServerPlugin
50 50
 {
51 51
 
52
-	// namespace
53
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
54
-	const TAGS_PROPERTYNAME = '{http://owncloud.org/ns}tags';
55
-	const FAVORITE_PROPERTYNAME = '{http://owncloud.org/ns}favorite';
56
-	const TAG_FAVORITE = '_$!<Favorite>!$_';
52
+    // namespace
53
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
54
+    const TAGS_PROPERTYNAME = '{http://owncloud.org/ns}tags';
55
+    const FAVORITE_PROPERTYNAME = '{http://owncloud.org/ns}favorite';
56
+    const TAG_FAVORITE = '_$!<Favorite>!$_';
57 57
 
58
-	/**
59
-	 * Reference to main server object
60
-	 *
61
-	 * @var \Sabre\DAV\Server
62
-	 */
63
-	private $server;
58
+    /**
59
+     * Reference to main server object
60
+     *
61
+     * @var \Sabre\DAV\Server
62
+     */
63
+    private $server;
64 64
 
65
-	/**
66
-	 * @var \OCP\ITagManager
67
-	 */
68
-	private $tagManager;
65
+    /**
66
+     * @var \OCP\ITagManager
67
+     */
68
+    private $tagManager;
69 69
 
70
-	/**
71
-	 * @var \OCP\ITags
72
-	 */
73
-	private $tagger;
70
+    /**
71
+     * @var \OCP\ITags
72
+     */
73
+    private $tagger;
74 74
 
75
-	/**
76
-	 * Array of file id to tags array
77
-	 * The null value means the cache wasn't initialized.
78
-	 *
79
-	 * @var array
80
-	 */
81
-	private $cachedTags;
75
+    /**
76
+     * Array of file id to tags array
77
+     * The null value means the cache wasn't initialized.
78
+     *
79
+     * @var array
80
+     */
81
+    private $cachedTags;
82 82
 
83
-	/**
84
-	 * @var \Sabre\DAV\Tree
85
-	 */
86
-	private $tree;
83
+    /**
84
+     * @var \Sabre\DAV\Tree
85
+     */
86
+    private $tree;
87 87
 
88
-	/**
89
-	 * @param \Sabre\DAV\Tree $tree tree
90
-	 * @param \OCP\ITagManager $tagManager tag manager
91
-	 */
92
-	public function __construct(\Sabre\DAV\Tree $tree, \OCP\ITagManager $tagManager) {
93
-		$this->tree = $tree;
94
-		$this->tagManager = $tagManager;
95
-		$this->tagger = null;
96
-		$this->cachedTags = array();
97
-	}
88
+    /**
89
+     * @param \Sabre\DAV\Tree $tree tree
90
+     * @param \OCP\ITagManager $tagManager tag manager
91
+     */
92
+    public function __construct(\Sabre\DAV\Tree $tree, \OCP\ITagManager $tagManager) {
93
+        $this->tree = $tree;
94
+        $this->tagManager = $tagManager;
95
+        $this->tagger = null;
96
+        $this->cachedTags = array();
97
+    }
98 98
 
99
-	/**
100
-	 * This initializes the plugin.
101
-	 *
102
-	 * This function is called by \Sabre\DAV\Server, after
103
-	 * addPlugin is called.
104
-	 *
105
-	 * This method should set up the required event subscriptions.
106
-	 *
107
-	 * @param \Sabre\DAV\Server $server
108
-	 * @return void
109
-	 */
110
-	public function initialize(\Sabre\DAV\Server $server) {
99
+    /**
100
+     * This initializes the plugin.
101
+     *
102
+     * This function is called by \Sabre\DAV\Server, after
103
+     * addPlugin is called.
104
+     *
105
+     * This method should set up the required event subscriptions.
106
+     *
107
+     * @param \Sabre\DAV\Server $server
108
+     * @return void
109
+     */
110
+    public function initialize(\Sabre\DAV\Server $server) {
111 111
 
112
-		$server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
113
-		$server->xml->elementMap[self::TAGS_PROPERTYNAME] = 'OCA\\DAV\\Connector\\Sabre\\TagList';
112
+        $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
113
+        $server->xml->elementMap[self::TAGS_PROPERTYNAME] = 'OCA\\DAV\\Connector\\Sabre\\TagList';
114 114
 
115
-		$this->server = $server;
116
-		$this->server->on('propFind', array($this, 'handleGetProperties'));
117
-		$this->server->on('propPatch', array($this, 'handleUpdateProperties'));
118
-	}
115
+        $this->server = $server;
116
+        $this->server->on('propFind', array($this, 'handleGetProperties'));
117
+        $this->server->on('propPatch', array($this, 'handleUpdateProperties'));
118
+    }
119 119
 
120
-	/**
121
-	 * Returns the tagger
122
-	 *
123
-	 * @return \OCP\ITags tagger
124
-	 */
125
-	private function getTagger() {
126
-		if (!$this->tagger) {
127
-			$this->tagger = $this->tagManager->load('files');
128
-		}
129
-		return $this->tagger;
130
-	}
120
+    /**
121
+     * Returns the tagger
122
+     *
123
+     * @return \OCP\ITags tagger
124
+     */
125
+    private function getTagger() {
126
+        if (!$this->tagger) {
127
+            $this->tagger = $this->tagManager->load('files');
128
+        }
129
+        return $this->tagger;
130
+    }
131 131
 
132
-	/**
133
-	 * Returns tags and favorites.
134
-	 *
135
-	 * @param integer $fileId file id
136
-	 * @return array list($tags, $favorite) with $tags as tag array
137
-	 * and $favorite is a boolean whether the file was favorited
138
-	 */
139
-	private function getTagsAndFav($fileId) {
140
-		$isFav = false;
141
-		$tags = $this->getTags($fileId);
142
-		if ($tags) {
143
-			$favPos = array_search(self::TAG_FAVORITE, $tags);
144
-			if ($favPos !== false) {
145
-				$isFav = true;
146
-				unset($tags[$favPos]);
147
-			}
148
-		}
149
-		return array($tags, $isFav);
150
-	}
132
+    /**
133
+     * Returns tags and favorites.
134
+     *
135
+     * @param integer $fileId file id
136
+     * @return array list($tags, $favorite) with $tags as tag array
137
+     * and $favorite is a boolean whether the file was favorited
138
+     */
139
+    private function getTagsAndFav($fileId) {
140
+        $isFav = false;
141
+        $tags = $this->getTags($fileId);
142
+        if ($tags) {
143
+            $favPos = array_search(self::TAG_FAVORITE, $tags);
144
+            if ($favPos !== false) {
145
+                $isFav = true;
146
+                unset($tags[$favPos]);
147
+            }
148
+        }
149
+        return array($tags, $isFav);
150
+    }
151 151
 
152
-	/**
153
-	 * Returns tags for the given file id
154
-	 *
155
-	 * @param integer $fileId file id
156
-	 * @return array list of tags for that file
157
-	 */
158
-	private function getTags($fileId) {
159
-		if (isset($this->cachedTags[$fileId])) {
160
-			return $this->cachedTags[$fileId];
161
-		} else {
162
-			$tags = $this->getTagger()->getTagsForObjects(array($fileId));
163
-			if ($tags !== false) {
164
-				if (empty($tags)) {
165
-					return array();
166
-				}
167
-				return current($tags);
168
-			}
169
-		}
170
-		return null;
171
-	}
152
+    /**
153
+     * Returns tags for the given file id
154
+     *
155
+     * @param integer $fileId file id
156
+     * @return array list of tags for that file
157
+     */
158
+    private function getTags($fileId) {
159
+        if (isset($this->cachedTags[$fileId])) {
160
+            return $this->cachedTags[$fileId];
161
+        } else {
162
+            $tags = $this->getTagger()->getTagsForObjects(array($fileId));
163
+            if ($tags !== false) {
164
+                if (empty($tags)) {
165
+                    return array();
166
+                }
167
+                return current($tags);
168
+            }
169
+        }
170
+        return null;
171
+    }
172 172
 
173
-	/**
174
-	 * Updates the tags of the given file id
175
-	 *
176
-	 * @param int $fileId
177
-	 * @param array $tags array of tag strings
178
-	 */
179
-	private function updateTags($fileId, $tags) {
180
-		$tagger = $this->getTagger();
181
-		$currentTags = $this->getTags($fileId);
173
+    /**
174
+     * Updates the tags of the given file id
175
+     *
176
+     * @param int $fileId
177
+     * @param array $tags array of tag strings
178
+     */
179
+    private function updateTags($fileId, $tags) {
180
+        $tagger = $this->getTagger();
181
+        $currentTags = $this->getTags($fileId);
182 182
 
183
-		$newTags = array_diff($tags, $currentTags);
184
-		foreach ($newTags as $tag) {
185
-			if ($tag === self::TAG_FAVORITE) {
186
-				continue;
187
-			}
188
-			$tagger->tagAs($fileId, $tag);
189
-		}
190
-		$deletedTags = array_diff($currentTags, $tags);
191
-		foreach ($deletedTags as $tag) {
192
-			if ($tag === self::TAG_FAVORITE) {
193
-				continue;
194
-			}
195
-			$tagger->unTag($fileId, $tag);
196
-		}
197
-	}
183
+        $newTags = array_diff($tags, $currentTags);
184
+        foreach ($newTags as $tag) {
185
+            if ($tag === self::TAG_FAVORITE) {
186
+                continue;
187
+            }
188
+            $tagger->tagAs($fileId, $tag);
189
+        }
190
+        $deletedTags = array_diff($currentTags, $tags);
191
+        foreach ($deletedTags as $tag) {
192
+            if ($tag === self::TAG_FAVORITE) {
193
+                continue;
194
+            }
195
+            $tagger->unTag($fileId, $tag);
196
+        }
197
+    }
198 198
 
199
-	/**
200
-	 * Adds tags and favorites properties to the response,
201
-	 * if requested.
202
-	 *
203
-	 * @param PropFind $propFind
204
-	 * @param \Sabre\DAV\INode $node
205
-	 * @return void
206
-	 */
207
-	public function handleGetProperties(
208
-		PropFind $propFind,
209
-		\Sabre\DAV\INode $node
210
-	) {
211
-		if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
212
-			return;
213
-		}
199
+    /**
200
+     * Adds tags and favorites properties to the response,
201
+     * if requested.
202
+     *
203
+     * @param PropFind $propFind
204
+     * @param \Sabre\DAV\INode $node
205
+     * @return void
206
+     */
207
+    public function handleGetProperties(
208
+        PropFind $propFind,
209
+        \Sabre\DAV\INode $node
210
+    ) {
211
+        if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
212
+            return;
213
+        }
214 214
 
215
-		// need prefetch ?
216
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Directory
217
-			&& $propFind->getDepth() !== 0
218
-			&& (!is_null($propFind->getStatus(self::TAGS_PROPERTYNAME))
219
-			|| !is_null($propFind->getStatus(self::FAVORITE_PROPERTYNAME))
220
-		)) {
221
-			// note: pre-fetching only supported for depth <= 1
222
-			$folderContent = $node->getChildren();
223
-			$fileIds[] = (int)$node->getId();
224
-			foreach ($folderContent as $info) {
225
-				$fileIds[] = (int)$info->getId();
226
-			}
227
-			$tags = $this->getTagger()->getTagsForObjects($fileIds);
228
-			if ($tags === false) {
229
-				// the tags API returns false on error...
230
-				$tags = array();
231
-			}
215
+        // need prefetch ?
216
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Directory
217
+            && $propFind->getDepth() !== 0
218
+            && (!is_null($propFind->getStatus(self::TAGS_PROPERTYNAME))
219
+            || !is_null($propFind->getStatus(self::FAVORITE_PROPERTYNAME))
220
+        )) {
221
+            // note: pre-fetching only supported for depth <= 1
222
+            $folderContent = $node->getChildren();
223
+            $fileIds[] = (int)$node->getId();
224
+            foreach ($folderContent as $info) {
225
+                $fileIds[] = (int)$info->getId();
226
+            }
227
+            $tags = $this->getTagger()->getTagsForObjects($fileIds);
228
+            if ($tags === false) {
229
+                // the tags API returns false on error...
230
+                $tags = array();
231
+            }
232 232
 
233
-			$this->cachedTags = $this->cachedTags + $tags;
234
-			$emptyFileIds = array_diff($fileIds, array_keys($tags));
235
-			// also cache the ones that were not found
236
-			foreach ($emptyFileIds as $fileId) {
237
-				$this->cachedTags[$fileId] = [];
238
-			}
239
-		}
233
+            $this->cachedTags = $this->cachedTags + $tags;
234
+            $emptyFileIds = array_diff($fileIds, array_keys($tags));
235
+            // also cache the ones that were not found
236
+            foreach ($emptyFileIds as $fileId) {
237
+                $this->cachedTags[$fileId] = [];
238
+            }
239
+        }
240 240
 
241
-		$tags = null;
242
-		$isFav = null;
241
+        $tags = null;
242
+        $isFav = null;
243 243
 
244
-		$propFind->handle(self::TAGS_PROPERTYNAME, function() use ($tags, &$isFav, $node) {
245
-			list($tags, $isFav) = $this->getTagsAndFav($node->getId());
246
-			return new TagList($tags);
247
-		});
244
+        $propFind->handle(self::TAGS_PROPERTYNAME, function() use ($tags, &$isFav, $node) {
245
+            list($tags, $isFav) = $this->getTagsAndFav($node->getId());
246
+            return new TagList($tags);
247
+        });
248 248
 
249
-		$propFind->handle(self::FAVORITE_PROPERTYNAME, function() use ($isFav, $node) {
250
-			if (is_null($isFav)) {
251
-				list(, $isFav) = $this->getTagsAndFav($node->getId());
252
-			}
253
-			if ($isFav) {
254
-				return 1;
255
-			} else {
256
-				return 0;
257
-			}
258
-		});
259
-	}
249
+        $propFind->handle(self::FAVORITE_PROPERTYNAME, function() use ($isFav, $node) {
250
+            if (is_null($isFav)) {
251
+                list(, $isFav) = $this->getTagsAndFav($node->getId());
252
+            }
253
+            if ($isFav) {
254
+                return 1;
255
+            } else {
256
+                return 0;
257
+            }
258
+        });
259
+    }
260 260
 
261
-	/**
262
-	 * Updates tags and favorites properties, if applicable.
263
-	 *
264
-	 * @param string $path
265
-	 * @param PropPatch $propPatch
266
-	 *
267
-	 * @return void
268
-	 */
269
-	public function handleUpdateProperties($path, PropPatch $propPatch) {
270
-		$node = $this->tree->getNodeForPath($path);
271
-		if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
272
-			return;
273
-		}
261
+    /**
262
+     * Updates tags and favorites properties, if applicable.
263
+     *
264
+     * @param string $path
265
+     * @param PropPatch $propPatch
266
+     *
267
+     * @return void
268
+     */
269
+    public function handleUpdateProperties($path, PropPatch $propPatch) {
270
+        $node = $this->tree->getNodeForPath($path);
271
+        if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
272
+            return;
273
+        }
274 274
 
275
-		$propPatch->handle(self::TAGS_PROPERTYNAME, function($tagList) use ($node) {
276
-			$this->updateTags($node->getId(), $tagList->getTags());
277
-			return true;
278
-		});
275
+        $propPatch->handle(self::TAGS_PROPERTYNAME, function($tagList) use ($node) {
276
+            $this->updateTags($node->getId(), $tagList->getTags());
277
+            return true;
278
+        });
279 279
 
280
-		$propPatch->handle(self::FAVORITE_PROPERTYNAME, function($favState) use ($node) {
281
-			if ((int)$favState === 1 || $favState === 'true') {
282
-				$this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE);
283
-			} else {
284
-				$this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE);
285
-			}
280
+        $propPatch->handle(self::FAVORITE_PROPERTYNAME, function($favState) use ($node) {
281
+            if ((int)$favState === 1 || $favState === 'true') {
282
+                $this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE);
283
+            } else {
284
+                $this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE);
285
+            }
286 286
 
287
-			if (is_null($favState)) {
288
-				// confirm deletion
289
-				return 204;
290
-			}
287
+            if (is_null($favState)) {
288
+                // confirm deletion
289
+                return 204;
290
+            }
291 291
 
292
-			return 200;
293
-		});
294
-	}
292
+            return 200;
293
+        });
294
+    }
295 295
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -220,9 +220,9 @@  discard block
 block discarded – undo
220 220
 		)) {
221 221
 			// note: pre-fetching only supported for depth <= 1
222 222
 			$folderContent = $node->getChildren();
223
-			$fileIds[] = (int)$node->getId();
223
+			$fileIds[] = (int) $node->getId();
224 224
 			foreach ($folderContent as $info) {
225
-				$fileIds[] = (int)$info->getId();
225
+				$fileIds[] = (int) $info->getId();
226 226
 			}
227 227
 			$tags = $this->getTagger()->getTagsForObjects($fileIds);
228 228
 			if ($tags === false) {
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
 		});
279 279
 
280 280
 		$propPatch->handle(self::FAVORITE_PROPERTYNAME, function($favState) use ($node) {
281
-			if ((int)$favState === 1 || $favState === 'true') {
281
+			if ((int) $favState === 1 || $favState === 'true') {
282 282
 				$this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE);
283 283
 			} else {
284 284
 				$this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE);
Please login to merge, or discard this patch.
apps/dav/lib/SystemTag/SystemTagPlugin.php 1 patch
Indentation   +276 added lines, -276 removed lines patch added patch discarded remove patch
@@ -46,280 +46,280 @@
 block discarded – undo
46 46
  */
47 47
 class SystemTagPlugin extends \Sabre\DAV\ServerPlugin {
48 48
 
49
-	// namespace
50
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
51
-	const ID_PROPERTYNAME = '{http://owncloud.org/ns}id';
52
-	const DISPLAYNAME_PROPERTYNAME = '{http://owncloud.org/ns}display-name';
53
-	const USERVISIBLE_PROPERTYNAME = '{http://owncloud.org/ns}user-visible';
54
-	const USERASSIGNABLE_PROPERTYNAME = '{http://owncloud.org/ns}user-assignable';
55
-	const GROUPS_PROPERTYNAME = '{http://owncloud.org/ns}groups';
56
-	const CANASSIGN_PROPERTYNAME = '{http://owncloud.org/ns}can-assign';
57
-
58
-	/**
59
-	 * @var \Sabre\DAV\Server $server
60
-	 */
61
-	private $server;
62
-
63
-	/**
64
-	 * @var ISystemTagManager
65
-	 */
66
-	protected $tagManager;
67
-
68
-	/**
69
-	 * @var IUserSession
70
-	 */
71
-	protected $userSession;
72
-
73
-	/**
74
-	 * @var IGroupManager
75
-	 */
76
-	protected $groupManager;
77
-
78
-	/**
79
-	 * @param ISystemTagManager $tagManager tag manager
80
-	 * @param IGroupManager $groupManager
81
-	 * @param IUserSession $userSession
82
-	 */
83
-	public function __construct(ISystemTagManager $tagManager,
84
-								IGroupManager $groupManager,
85
-								IUserSession $userSession) {
86
-		$this->tagManager = $tagManager;
87
-		$this->userSession = $userSession;
88
-		$this->groupManager = $groupManager;
89
-	}
90
-
91
-	/**
92
-	 * This initializes the plugin.
93
-	 *
94
-	 * This function is called by \Sabre\DAV\Server, after
95
-	 * addPlugin is called.
96
-	 *
97
-	 * This method should set up the required event subscriptions.
98
-	 *
99
-	 * @param \Sabre\DAV\Server $server
100
-	 * @return void
101
-	 */
102
-	public function initialize(\Sabre\DAV\Server $server) {
103
-
104
-		$server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
105
-
106
-		$server->protectedProperties[] = self::ID_PROPERTYNAME;
107
-
108
-		$server->on('propFind', array($this, 'handleGetProperties'));
109
-		$server->on('propPatch', array($this, 'handleUpdateProperties'));
110
-		$server->on('method:POST', [$this, 'httpPost']);
111
-
112
-		$this->server = $server;
113
-	}
114
-
115
-	/**
116
-	 * POST operation on system tag collections
117
-	 *
118
-	 * @param RequestInterface $request request object
119
-	 * @param ResponseInterface $response response object
120
-	 * @return null|false
121
-	 */
122
-	public function httpPost(RequestInterface $request, ResponseInterface $response) {
123
-		$path = $request->getPath();
124
-
125
-		// Making sure the node exists
126
-		$node = $this->server->tree->getNodeForPath($path);
127
-		if ($node instanceof SystemTagsByIdCollection || $node instanceof SystemTagsObjectMappingCollection) {
128
-			$data = $request->getBodyAsString();
129
-
130
-			$tag = $this->createTag($data, $request->getHeader('Content-Type'));
131
-
132
-			if ($node instanceof SystemTagsObjectMappingCollection) {
133
-				// also add to collection
134
-				$node->createFile($tag->getId());
135
-				$url = $request->getBaseUrl() . 'systemtags/';
136
-			} else {
137
-				$url = $request->getUrl();
138
-			}
139
-
140
-			if ($url[strlen($url) - 1] !== '/') {
141
-				$url .= '/';
142
-			}
143
-
144
-			$response->setHeader('Content-Location', $url . $tag->getId());
145
-
146
-			// created
147
-			$response->setStatus(201);
148
-			return false;
149
-		}
150
-	}
151
-
152
-	/**
153
-	 * Creates a new tag
154
-	 *
155
-	 * @param string $data JSON encoded string containing the properties of the tag to create
156
-	 * @param string $contentType content type of the data
157
-	 * @return ISystemTag newly created system tag
158
-	 *
159
-	 * @throws BadRequest if a field was missing
160
-	 * @throws Conflict if a tag with the same properties already exists
161
-	 * @throws UnsupportedMediaType if the content type is not supported
162
-	 */
163
-	private function createTag($data, $contentType = 'application/json') {
164
-		if (explode(';', $contentType)[0] === 'application/json') {
165
-			$data = json_decode($data, true);
166
-		} else {
167
-			throw new UnsupportedMediaType();
168
-		}
169
-
170
-		if (!isset($data['name'])) {
171
-			throw new BadRequest('Missing "name" attribute');
172
-		}
173
-
174
-		$tagName = $data['name'];
175
-		$userVisible = true;
176
-		$userAssignable = true;
177
-
178
-		if (isset($data['userVisible'])) {
179
-			$userVisible = (bool)$data['userVisible'];
180
-		}
181
-
182
-		if (isset($data['userAssignable'])) {
183
-			$userAssignable = (bool)$data['userAssignable'];
184
-		}
185
-
186
-		$groups = [];
187
-		if (isset($data['groups'])) {
188
-			$groups = $data['groups'];
189
-			if (is_string($groups)) {
190
-				$groups = explode('|', $groups);
191
-			}
192
-		}
193
-
194
-		if($userVisible === false || $userAssignable === false || !empty($groups)) {
195
-			if(!$this->userSession->isLoggedIn() || !$this->groupManager->isAdmin($this->userSession->getUser()->getUID())) {
196
-				throw new BadRequest('Not sufficient permissions');
197
-			}
198
-		}
199
-
200
-		try {
201
-			$tag = $this->tagManager->createTag($tagName, $userVisible, $userAssignable);
202
-			if (!empty($groups)) {
203
-				$this->tagManager->setTagGroups($tag, $groups);
204
-			}
205
-			return $tag;
206
-		} catch (TagAlreadyExistsException $e) {
207
-			throw new Conflict('Tag already exists', 0, $e);
208
-		}
209
-	}
210
-
211
-
212
-	/**
213
-	 * Retrieves system tag properties
214
-	 *
215
-	 * @param PropFind $propFind
216
-	 * @param \Sabre\DAV\INode $node
217
-	 */
218
-	public function handleGetProperties(
219
-		PropFind $propFind,
220
-		\Sabre\DAV\INode $node
221
-	) {
222
-		if (!($node instanceof SystemTagNode) && !($node instanceof SystemTagMappingNode)) {
223
-			return;
224
-		}
225
-
226
-		$propFind->handle(self::ID_PROPERTYNAME, function() use ($node) {
227
-			return $node->getSystemTag()->getId();
228
-		});
229
-
230
-		$propFind->handle(self::DISPLAYNAME_PROPERTYNAME, function() use ($node) {
231
-			return $node->getSystemTag()->getName();
232
-		});
233
-
234
-		$propFind->handle(self::USERVISIBLE_PROPERTYNAME, function() use ($node) {
235
-			return $node->getSystemTag()->isUserVisible() ? 'true' : 'false';
236
-		});
237
-
238
-		$propFind->handle(self::USERASSIGNABLE_PROPERTYNAME, function() use ($node) {
239
-			// this is the tag's inherent property "is user assignable"
240
-			return $node->getSystemTag()->isUserAssignable() ? 'true' : 'false';
241
-		});
242
-
243
-		$propFind->handle(self::CANASSIGN_PROPERTYNAME, function() use ($node) {
244
-			// this is the effective permission for the current user
245
-			return $this->tagManager->canUserAssignTag($node->getSystemTag(), $this->userSession->getUser()) ? 'true' : 'false';
246
-		});
247
-
248
-		$propFind->handle(self::GROUPS_PROPERTYNAME, function() use ($node) {
249
-			if (!$this->groupManager->isAdmin($this->userSession->getUser()->getUID())) {
250
-				// property only available for admins
251
-				throw new Forbidden();
252
-			}
253
-			$groups = [];
254
-			// no need to retrieve groups for namespaces that don't qualify
255
-			if ($node->getSystemTag()->isUserVisible() && !$node->getSystemTag()->isUserAssignable()) {
256
-				$groups = $this->tagManager->getTagGroups($node->getSystemTag());
257
-			}
258
-			return implode('|', $groups);
259
-		});
260
-	}
261
-
262
-	/**
263
-	 * Updates tag attributes
264
-	 *
265
-	 * @param string $path
266
-	 * @param PropPatch $propPatch
267
-	 *
268
-	 * @return void
269
-	 */
270
-	public function handleUpdateProperties($path, PropPatch $propPatch) {
271
-		$node = $this->server->tree->getNodeForPath($path);
272
-		if (!($node instanceof SystemTagNode)) {
273
-			return;
274
-		}
275
-
276
-		$propPatch->handle([
277
-			self::DISPLAYNAME_PROPERTYNAME,
278
-			self::USERVISIBLE_PROPERTYNAME,
279
-			self::USERASSIGNABLE_PROPERTYNAME,
280
-			self::GROUPS_PROPERTYNAME,
281
-		], function($props) use ($node) {
282
-			$tag = $node->getSystemTag();
283
-			$name = $tag->getName();
284
-			$userVisible = $tag->isUserVisible();
285
-			$userAssignable = $tag->isUserAssignable();
286
-
287
-			$updateTag = false;
288
-
289
-			if (isset($props[self::DISPLAYNAME_PROPERTYNAME])) {
290
-				$name = $props[self::DISPLAYNAME_PROPERTYNAME];
291
-				$updateTag = true;
292
-			}
293
-
294
-			if (isset($props[self::USERVISIBLE_PROPERTYNAME])) {
295
-				$propValue = $props[self::USERVISIBLE_PROPERTYNAME];
296
-				$userVisible = ($propValue !== 'false' && $propValue !== '0');
297
-				$updateTag = true;
298
-			}
299
-
300
-			if (isset($props[self::USERASSIGNABLE_PROPERTYNAME])) {
301
-				$propValue = $props[self::USERASSIGNABLE_PROPERTYNAME];
302
-				$userAssignable = ($propValue !== 'false' && $propValue !== '0');
303
-				$updateTag = true;
304
-			}
305
-
306
-			if (isset($props[self::GROUPS_PROPERTYNAME])) {
307
-				if (!$this->groupManager->isAdmin($this->userSession->getUser()->getUID())) {
308
-					// property only available for admins
309
-					throw new Forbidden();
310
-				}
311
-
312
-				$propValue = $props[self::GROUPS_PROPERTYNAME];
313
-				$groupIds = explode('|', $propValue);
314
-				$this->tagManager->setTagGroups($tag, $groupIds);
315
-			}
316
-
317
-			if ($updateTag) {
318
-				$node->update($name, $userVisible, $userAssignable);
319
-			}
320
-
321
-			return true;
322
-		});
323
-
324
-	}
49
+    // namespace
50
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
51
+    const ID_PROPERTYNAME = '{http://owncloud.org/ns}id';
52
+    const DISPLAYNAME_PROPERTYNAME = '{http://owncloud.org/ns}display-name';
53
+    const USERVISIBLE_PROPERTYNAME = '{http://owncloud.org/ns}user-visible';
54
+    const USERASSIGNABLE_PROPERTYNAME = '{http://owncloud.org/ns}user-assignable';
55
+    const GROUPS_PROPERTYNAME = '{http://owncloud.org/ns}groups';
56
+    const CANASSIGN_PROPERTYNAME = '{http://owncloud.org/ns}can-assign';
57
+
58
+    /**
59
+     * @var \Sabre\DAV\Server $server
60
+     */
61
+    private $server;
62
+
63
+    /**
64
+     * @var ISystemTagManager
65
+     */
66
+    protected $tagManager;
67
+
68
+    /**
69
+     * @var IUserSession
70
+     */
71
+    protected $userSession;
72
+
73
+    /**
74
+     * @var IGroupManager
75
+     */
76
+    protected $groupManager;
77
+
78
+    /**
79
+     * @param ISystemTagManager $tagManager tag manager
80
+     * @param IGroupManager $groupManager
81
+     * @param IUserSession $userSession
82
+     */
83
+    public function __construct(ISystemTagManager $tagManager,
84
+                                IGroupManager $groupManager,
85
+                                IUserSession $userSession) {
86
+        $this->tagManager = $tagManager;
87
+        $this->userSession = $userSession;
88
+        $this->groupManager = $groupManager;
89
+    }
90
+
91
+    /**
92
+     * This initializes the plugin.
93
+     *
94
+     * This function is called by \Sabre\DAV\Server, after
95
+     * addPlugin is called.
96
+     *
97
+     * This method should set up the required event subscriptions.
98
+     *
99
+     * @param \Sabre\DAV\Server $server
100
+     * @return void
101
+     */
102
+    public function initialize(\Sabre\DAV\Server $server) {
103
+
104
+        $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
105
+
106
+        $server->protectedProperties[] = self::ID_PROPERTYNAME;
107
+
108
+        $server->on('propFind', array($this, 'handleGetProperties'));
109
+        $server->on('propPatch', array($this, 'handleUpdateProperties'));
110
+        $server->on('method:POST', [$this, 'httpPost']);
111
+
112
+        $this->server = $server;
113
+    }
114
+
115
+    /**
116
+     * POST operation on system tag collections
117
+     *
118
+     * @param RequestInterface $request request object
119
+     * @param ResponseInterface $response response object
120
+     * @return null|false
121
+     */
122
+    public function httpPost(RequestInterface $request, ResponseInterface $response) {
123
+        $path = $request->getPath();
124
+
125
+        // Making sure the node exists
126
+        $node = $this->server->tree->getNodeForPath($path);
127
+        if ($node instanceof SystemTagsByIdCollection || $node instanceof SystemTagsObjectMappingCollection) {
128
+            $data = $request->getBodyAsString();
129
+
130
+            $tag = $this->createTag($data, $request->getHeader('Content-Type'));
131
+
132
+            if ($node instanceof SystemTagsObjectMappingCollection) {
133
+                // also add to collection
134
+                $node->createFile($tag->getId());
135
+                $url = $request->getBaseUrl() . 'systemtags/';
136
+            } else {
137
+                $url = $request->getUrl();
138
+            }
139
+
140
+            if ($url[strlen($url) - 1] !== '/') {
141
+                $url .= '/';
142
+            }
143
+
144
+            $response->setHeader('Content-Location', $url . $tag->getId());
145
+
146
+            // created
147
+            $response->setStatus(201);
148
+            return false;
149
+        }
150
+    }
151
+
152
+    /**
153
+     * Creates a new tag
154
+     *
155
+     * @param string $data JSON encoded string containing the properties of the tag to create
156
+     * @param string $contentType content type of the data
157
+     * @return ISystemTag newly created system tag
158
+     *
159
+     * @throws BadRequest if a field was missing
160
+     * @throws Conflict if a tag with the same properties already exists
161
+     * @throws UnsupportedMediaType if the content type is not supported
162
+     */
163
+    private function createTag($data, $contentType = 'application/json') {
164
+        if (explode(';', $contentType)[0] === 'application/json') {
165
+            $data = json_decode($data, true);
166
+        } else {
167
+            throw new UnsupportedMediaType();
168
+        }
169
+
170
+        if (!isset($data['name'])) {
171
+            throw new BadRequest('Missing "name" attribute');
172
+        }
173
+
174
+        $tagName = $data['name'];
175
+        $userVisible = true;
176
+        $userAssignable = true;
177
+
178
+        if (isset($data['userVisible'])) {
179
+            $userVisible = (bool)$data['userVisible'];
180
+        }
181
+
182
+        if (isset($data['userAssignable'])) {
183
+            $userAssignable = (bool)$data['userAssignable'];
184
+        }
185
+
186
+        $groups = [];
187
+        if (isset($data['groups'])) {
188
+            $groups = $data['groups'];
189
+            if (is_string($groups)) {
190
+                $groups = explode('|', $groups);
191
+            }
192
+        }
193
+
194
+        if($userVisible === false || $userAssignable === false || !empty($groups)) {
195
+            if(!$this->userSession->isLoggedIn() || !$this->groupManager->isAdmin($this->userSession->getUser()->getUID())) {
196
+                throw new BadRequest('Not sufficient permissions');
197
+            }
198
+        }
199
+
200
+        try {
201
+            $tag = $this->tagManager->createTag($tagName, $userVisible, $userAssignable);
202
+            if (!empty($groups)) {
203
+                $this->tagManager->setTagGroups($tag, $groups);
204
+            }
205
+            return $tag;
206
+        } catch (TagAlreadyExistsException $e) {
207
+            throw new Conflict('Tag already exists', 0, $e);
208
+        }
209
+    }
210
+
211
+
212
+    /**
213
+     * Retrieves system tag properties
214
+     *
215
+     * @param PropFind $propFind
216
+     * @param \Sabre\DAV\INode $node
217
+     */
218
+    public function handleGetProperties(
219
+        PropFind $propFind,
220
+        \Sabre\DAV\INode $node
221
+    ) {
222
+        if (!($node instanceof SystemTagNode) && !($node instanceof SystemTagMappingNode)) {
223
+            return;
224
+        }
225
+
226
+        $propFind->handle(self::ID_PROPERTYNAME, function() use ($node) {
227
+            return $node->getSystemTag()->getId();
228
+        });
229
+
230
+        $propFind->handle(self::DISPLAYNAME_PROPERTYNAME, function() use ($node) {
231
+            return $node->getSystemTag()->getName();
232
+        });
233
+
234
+        $propFind->handle(self::USERVISIBLE_PROPERTYNAME, function() use ($node) {
235
+            return $node->getSystemTag()->isUserVisible() ? 'true' : 'false';
236
+        });
237
+
238
+        $propFind->handle(self::USERASSIGNABLE_PROPERTYNAME, function() use ($node) {
239
+            // this is the tag's inherent property "is user assignable"
240
+            return $node->getSystemTag()->isUserAssignable() ? 'true' : 'false';
241
+        });
242
+
243
+        $propFind->handle(self::CANASSIGN_PROPERTYNAME, function() use ($node) {
244
+            // this is the effective permission for the current user
245
+            return $this->tagManager->canUserAssignTag($node->getSystemTag(), $this->userSession->getUser()) ? 'true' : 'false';
246
+        });
247
+
248
+        $propFind->handle(self::GROUPS_PROPERTYNAME, function() use ($node) {
249
+            if (!$this->groupManager->isAdmin($this->userSession->getUser()->getUID())) {
250
+                // property only available for admins
251
+                throw new Forbidden();
252
+            }
253
+            $groups = [];
254
+            // no need to retrieve groups for namespaces that don't qualify
255
+            if ($node->getSystemTag()->isUserVisible() && !$node->getSystemTag()->isUserAssignable()) {
256
+                $groups = $this->tagManager->getTagGroups($node->getSystemTag());
257
+            }
258
+            return implode('|', $groups);
259
+        });
260
+    }
261
+
262
+    /**
263
+     * Updates tag attributes
264
+     *
265
+     * @param string $path
266
+     * @param PropPatch $propPatch
267
+     *
268
+     * @return void
269
+     */
270
+    public function handleUpdateProperties($path, PropPatch $propPatch) {
271
+        $node = $this->server->tree->getNodeForPath($path);
272
+        if (!($node instanceof SystemTagNode)) {
273
+            return;
274
+        }
275
+
276
+        $propPatch->handle([
277
+            self::DISPLAYNAME_PROPERTYNAME,
278
+            self::USERVISIBLE_PROPERTYNAME,
279
+            self::USERASSIGNABLE_PROPERTYNAME,
280
+            self::GROUPS_PROPERTYNAME,
281
+        ], function($props) use ($node) {
282
+            $tag = $node->getSystemTag();
283
+            $name = $tag->getName();
284
+            $userVisible = $tag->isUserVisible();
285
+            $userAssignable = $tag->isUserAssignable();
286
+
287
+            $updateTag = false;
288
+
289
+            if (isset($props[self::DISPLAYNAME_PROPERTYNAME])) {
290
+                $name = $props[self::DISPLAYNAME_PROPERTYNAME];
291
+                $updateTag = true;
292
+            }
293
+
294
+            if (isset($props[self::USERVISIBLE_PROPERTYNAME])) {
295
+                $propValue = $props[self::USERVISIBLE_PROPERTYNAME];
296
+                $userVisible = ($propValue !== 'false' && $propValue !== '0');
297
+                $updateTag = true;
298
+            }
299
+
300
+            if (isset($props[self::USERASSIGNABLE_PROPERTYNAME])) {
301
+                $propValue = $props[self::USERASSIGNABLE_PROPERTYNAME];
302
+                $userAssignable = ($propValue !== 'false' && $propValue !== '0');
303
+                $updateTag = true;
304
+            }
305
+
306
+            if (isset($props[self::GROUPS_PROPERTYNAME])) {
307
+                if (!$this->groupManager->isAdmin($this->userSession->getUser()->getUID())) {
308
+                    // property only available for admins
309
+                    throw new Forbidden();
310
+                }
311
+
312
+                $propValue = $props[self::GROUPS_PROPERTYNAME];
313
+                $groupIds = explode('|', $propValue);
314
+                $this->tagManager->setTagGroups($tag, $groupIds);
315
+            }
316
+
317
+            if ($updateTag) {
318
+                $node->update($name, $userVisible, $userAssignable);
319
+            }
320
+
321
+            return true;
322
+        });
323
+
324
+    }
325 325
 }
Please login to merge, or discard this patch.