Completed
Pull Request — master (#3681)
by Robin
19:24
created
apps/dav/lib/Connector/Sabre/FilesPlugin.php 2 patches
Indentation   +391 added lines, -391 removed lines patch added patch discarded remove patch
@@ -51,395 +51,395 @@
 block discarded – undo
51 51
 
52 52
 class FilesPlugin extends ServerPlugin {
53 53
 
54
-	// namespace
55
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
56
-	const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
57
-	const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
58
-	const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
59
-	const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
60
-	const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
61
-	const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
62
-	const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
63
-	const GETETAG_PROPERTYNAME = '{DAV:}getetag';
64
-	const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
65
-	const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
66
-	const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
67
-	const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
68
-	const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
69
-	const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
70
-
71
-	/**
72
-	 * Reference to main server object
73
-	 *
74
-	 * @var \Sabre\DAV\Server
75
-	 */
76
-	private $server;
77
-
78
-	/**
79
-	 * @var Tree
80
-	 */
81
-	private $tree;
82
-
83
-	/**
84
-	 * Whether this is public webdav.
85
-	 * If true, some returned information will be stripped off.
86
-	 *
87
-	 * @var bool
88
-	 */
89
-	private $isPublic;
90
-
91
-	/**
92
-	 * @var View
93
-	 */
94
-	private $fileView;
95
-
96
-	/**
97
-	 * @var bool
98
-	 */
99
-	private $downloadAttachment;
100
-
101
-	/**
102
-	 * @var IConfig
103
-	 */
104
-	private $config;
105
-
106
-	/**
107
-	 * @var IRequest
108
-	 */
109
-	private $request;
110
-
111
-	/**
112
-	 * @var IPreview
113
-	 */
114
-	private $previewManager;
115
-
116
-	/**
117
-	 * @param Tree $tree
118
-	 * @param IConfig $config
119
-	 * @param IRequest $request
120
-	 * @param IPreview $previewManager
121
-	 * @param bool $isPublic
122
-	 * @param bool $downloadAttachment
123
-	 */
124
-	public function __construct(Tree $tree,
125
-								IConfig $config,
126
-								IRequest $request,
127
-								IPreview $previewManager,
128
-								$isPublic = false,
129
-								$downloadAttachment = true) {
130
-		$this->tree = $tree;
131
-		$this->config = $config;
132
-		$this->request = $request;
133
-		$this->isPublic = $isPublic;
134
-		$this->downloadAttachment = $downloadAttachment;
135
-		$this->previewManager = $previewManager;
136
-	}
137
-
138
-	/**
139
-	 * This initializes the plugin.
140
-	 *
141
-	 * This function is called by \Sabre\DAV\Server, after
142
-	 * addPlugin is called.
143
-	 *
144
-	 * This method should set up the required event subscriptions.
145
-	 *
146
-	 * @param \Sabre\DAV\Server $server
147
-	 * @return void
148
-	 */
149
-	public function initialize(\Sabre\DAV\Server $server) {
150
-
151
-		$server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
152
-		$server->xml->namespaceMap[self::NS_NEXTCLOUD] = 'nc';
153
-		$server->protectedProperties[] = self::FILEID_PROPERTYNAME;
154
-		$server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
155
-		$server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
156
-		$server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
157
-		$server->protectedProperties[] = self::SIZE_PROPERTYNAME;
158
-		$server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
159
-		$server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
160
-		$server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
161
-		$server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
162
-		$server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
163
-		$server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
164
-
165
-		// normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
166
-		$allowedProperties = ['{DAV:}getetag'];
167
-		$server->protectedProperties = array_diff($server->protectedProperties, $allowedProperties);
168
-
169
-		$this->server = $server;
170
-		$this->server->on('propFind', array($this, 'handleGetProperties'));
171
-		$this->server->on('propPatch', array($this, 'handleUpdateProperties'));
172
-		$this->server->on('afterBind', array($this, 'sendFileIdHeader'));
173
-		$this->server->on('afterWriteContent', array($this, 'sendFileIdHeader'));
174
-		$this->server->on('afterMethod:GET', [$this,'httpGet']);
175
-		$this->server->on('afterMethod:GET', array($this, 'handleDownloadToken'));
176
-		$this->server->on('afterResponse', function($request, ResponseInterface $response) {
177
-			$body = $response->getBody();
178
-			if (is_resource($body)) {
179
-				fclose($body);
180
-			}
181
-		});
182
-		$this->server->on('beforeMove', [$this, 'checkMove']);
183
-	}
184
-
185
-	/**
186
-	 * Plugin that checks if a move can actually be performed.
187
-	 *
188
-	 * @param string $source source path
189
-	 * @param string $destination destination path
190
-	 * @throws Forbidden
191
-	 * @throws NotFound
192
-	 */
193
-	function checkMove($source, $destination) {
194
-		$sourceNode = $this->tree->getNodeForPath($source);
195
-		if (!$sourceNode instanceof Node) {
196
-			return;
197
-		}
198
-		list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($source);
199
-		list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destination);
200
-
201
-		if ($sourceDir !== $destinationDir) {
202
-			$sourceNodeFileInfo = $sourceNode->getFileInfo();
203
-			if (is_null($sourceNodeFileInfo)) {
204
-				throw new NotFound($source . ' does not exist');
205
-			}
206
-
207
-			if (!$sourceNodeFileInfo->isDeletable()) {
208
-				throw new Forbidden($source . " cannot be deleted");
209
-			}
210
-		}
211
-	}
212
-
213
-	/**
214
-	 * This sets a cookie to be able to recognize the start of the download
215
-	 * the content must not be longer than 32 characters and must only contain
216
-	 * alphanumeric characters
217
-	 *
218
-	 * @param RequestInterface $request
219
-	 * @param ResponseInterface $response
220
-	 */
221
-	function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
222
-		$queryParams = $request->getQueryParameters();
223
-
224
-		/**
225
-		 * this sets a cookie to be able to recognize the start of the download
226
-		 * the content must not be longer than 32 characters and must only contain
227
-		 * alphanumeric characters
228
-		 */
229
-		if (isset($queryParams['downloadStartSecret'])) {
230
-			$token = $queryParams['downloadStartSecret'];
231
-			if (!isset($token[32])
232
-				&& preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
233
-				// FIXME: use $response->setHeader() instead
234
-				setcookie('ocDownloadStarted', $token, time() + 20, '/');
235
-			}
236
-		}
237
-	}
238
-
239
-	/**
240
-	 * Add headers to file download
241
-	 *
242
-	 * @param RequestInterface $request
243
-	 * @param ResponseInterface $response
244
-	 */
245
-	function httpGet(RequestInterface $request, ResponseInterface $response) {
246
-		// Only handle valid files
247
-		$node = $this->tree->getNodeForPath($request->getPath());
248
-		if (!($node instanceof IFile)) return;
249
-
250
-		// adds a 'Content-Disposition: attachment' header in case no disposition
251
-		// header has been set before
252
-		if ($this->downloadAttachment &&
253
-			$response->getHeader('Content-Disposition') === null) {
254
-			$filename = $node->getName();
255
-			if ($this->request->isUserAgent(
256
-				[
257
-					\OC\AppFramework\Http\Request::USER_AGENT_IE,
258
-					\OC\AppFramework\Http\Request::USER_AGENT_ANDROID_MOBILE_CHROME,
259
-					\OC\AppFramework\Http\Request::USER_AGENT_FREEBOX,
260
-				])) {
261
-				$response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
262
-			} else {
263
-				$response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
264
-													 . '; filename="' . rawurlencode($filename) . '"');
265
-			}
266
-		}
267
-
268
-		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
269
-			//Add OC-Checksum header
270
-			/** @var $node File */
271
-			$checksum = $node->getChecksum();
272
-			if ($checksum !== null && $checksum !== '') {
273
-				$response->addHeader('OC-Checksum', $checksum);
274
-			}
275
-		}
276
-	}
277
-
278
-	/**
279
-	 * Adds all ownCloud-specific properties
280
-	 *
281
-	 * @param PropFind $propFind
282
-	 * @param \Sabre\DAV\INode $node
283
-	 * @return void
284
-	 */
285
-	public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
286
-
287
-		$httpRequest = $this->server->httpRequest;
288
-
289
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
290
-
291
-			$propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) {
292
-				return $node->getFileId();
293
-			});
294
-
295
-			$propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) {
296
-				return $node->getInternalFileId();
297
-			});
298
-
299
-			$propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) {
300
-				$perms = $node->getDavPermissions();
301
-				if ($this->isPublic) {
302
-					// remove mount information
303
-					$perms = str_replace(['S', 'M'], '', $perms);
304
-				}
305
-				return $perms;
306
-			});
307
-
308
-			$propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
309
-				return $node->getSharePermissions(
310
-					$httpRequest->getRawServerValue('PHP_AUTH_USER')
311
-				);
312
-			});
313
-
314
-			$propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) {
315
-				return $node->getETag();
316
-			});
317
-
318
-			$propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) {
319
-				$owner = $node->getOwner();
320
-				if (!$owner) {
321
-					return null;
322
-				} else {
323
-					return $owner->getUID();
324
-				}
325
-			});
326
-			$propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) {
327
-				$owner = $node->getOwner();
328
-				if (!$owner) {
329
-					return null;
330
-				} else {
331
-					return $owner->getDisplayName();
332
-				}
333
-			});
334
-
335
-			$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
336
-				return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
337
-			});
338
-			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
339
-				return $node->getSize();
340
-			});
341
-		}
342
-
343
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
344
-			$propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
345
-				return $this->config->getSystemValue('data-fingerprint', '');
346
-			});
347
-		}
348
-
349
-		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
350
-			$propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
351
-				/** @var $node \OCA\DAV\Connector\Sabre\File */
352
-				try {
353
-					$directDownloadUrl = $node->getDirectDownload();
354
-					if (isset($directDownloadUrl['url'])) {
355
-						return $directDownloadUrl['url'];
356
-					}
357
-				} catch (StorageNotAvailableException $e) {
358
-					return false;
359
-				} catch (ForbiddenException $e) {
360
-					return false;
361
-				}
362
-				return false;
363
-			});
364
-
365
-			$propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
366
-				$checksum = $node->getChecksum();
367
-				if ($checksum === NULL || $checksum === '') {
368
-					return null;
369
-				}
370
-
371
-				return new ChecksumList($checksum);
372
-			});
373
-
374
-		}
375
-
376
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
377
-			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
378
-				return $node->getSize();
379
-			});
380
-		}
381
-	}
382
-
383
-	/**
384
-	 * Update ownCloud-specific properties
385
-	 *
386
-	 * @param string $path
387
-	 * @param PropPatch $propPatch
388
-	 *
389
-	 * @return void
390
-	 */
391
-	public function handleUpdateProperties($path, PropPatch $propPatch) {
392
-		$propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function($time) use ($path) {
393
-			if (empty($time)) {
394
-				return false;
395
-			}
396
-			$node = $this->tree->getNodeForPath($path);
397
-			if (is_null($node)) {
398
-				return 404;
399
-			}
400
-			$node->touch($time);
401
-			return true;
402
-		});
403
-		$propPatch->handle(self::GETETAG_PROPERTYNAME, function($etag) use ($path) {
404
-			if (empty($etag)) {
405
-				return false;
406
-			}
407
-			$node = $this->tree->getNodeForPath($path);
408
-			if (is_null($node)) {
409
-				return 404;
410
-			}
411
-			if ($node->setEtag($etag) !== -1) {
412
-				return true;
413
-			}
414
-			return false;
415
-		});
416
-	}
417
-
418
-	/**
419
-	 * @param string $filePath
420
-	 * @param \Sabre\DAV\INode $node
421
-	 * @throws \Sabre\DAV\Exception\BadRequest
422
-	 */
423
-	public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
424
-		// chunked upload handling
425
-		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
426
-			list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath);
427
-			$info = \OC_FileChunking::decodeName($name);
428
-			if (!empty($info)) {
429
-				$filePath = $path . '/' . $info['name'];
430
-			}
431
-		}
432
-
433
-		// we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
434
-		if (!$this->server->tree->nodeExists($filePath)) {
435
-			return;
436
-		}
437
-		$node = $this->server->tree->getNodeForPath($filePath);
438
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
439
-			$fileId = $node->getFileId();
440
-			if (!is_null($fileId)) {
441
-				$this->server->httpResponse->setHeader('OC-FileId', $fileId);
442
-			}
443
-		}
444
-	}
54
+    // namespace
55
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
56
+    const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
57
+    const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
58
+    const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
59
+    const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
60
+    const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
61
+    const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
62
+    const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
63
+    const GETETAG_PROPERTYNAME = '{DAV:}getetag';
64
+    const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
65
+    const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
66
+    const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
67
+    const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
68
+    const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
69
+    const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
70
+
71
+    /**
72
+     * Reference to main server object
73
+     *
74
+     * @var \Sabre\DAV\Server
75
+     */
76
+    private $server;
77
+
78
+    /**
79
+     * @var Tree
80
+     */
81
+    private $tree;
82
+
83
+    /**
84
+     * Whether this is public webdav.
85
+     * If true, some returned information will be stripped off.
86
+     *
87
+     * @var bool
88
+     */
89
+    private $isPublic;
90
+
91
+    /**
92
+     * @var View
93
+     */
94
+    private $fileView;
95
+
96
+    /**
97
+     * @var bool
98
+     */
99
+    private $downloadAttachment;
100
+
101
+    /**
102
+     * @var IConfig
103
+     */
104
+    private $config;
105
+
106
+    /**
107
+     * @var IRequest
108
+     */
109
+    private $request;
110
+
111
+    /**
112
+     * @var IPreview
113
+     */
114
+    private $previewManager;
115
+
116
+    /**
117
+     * @param Tree $tree
118
+     * @param IConfig $config
119
+     * @param IRequest $request
120
+     * @param IPreview $previewManager
121
+     * @param bool $isPublic
122
+     * @param bool $downloadAttachment
123
+     */
124
+    public function __construct(Tree $tree,
125
+                                IConfig $config,
126
+                                IRequest $request,
127
+                                IPreview $previewManager,
128
+                                $isPublic = false,
129
+                                $downloadAttachment = true) {
130
+        $this->tree = $tree;
131
+        $this->config = $config;
132
+        $this->request = $request;
133
+        $this->isPublic = $isPublic;
134
+        $this->downloadAttachment = $downloadAttachment;
135
+        $this->previewManager = $previewManager;
136
+    }
137
+
138
+    /**
139
+     * This initializes the plugin.
140
+     *
141
+     * This function is called by \Sabre\DAV\Server, after
142
+     * addPlugin is called.
143
+     *
144
+     * This method should set up the required event subscriptions.
145
+     *
146
+     * @param \Sabre\DAV\Server $server
147
+     * @return void
148
+     */
149
+    public function initialize(\Sabre\DAV\Server $server) {
150
+
151
+        $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
152
+        $server->xml->namespaceMap[self::NS_NEXTCLOUD] = 'nc';
153
+        $server->protectedProperties[] = self::FILEID_PROPERTYNAME;
154
+        $server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
155
+        $server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
156
+        $server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
157
+        $server->protectedProperties[] = self::SIZE_PROPERTYNAME;
158
+        $server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
159
+        $server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
160
+        $server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
161
+        $server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
162
+        $server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
163
+        $server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
164
+
165
+        // normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
166
+        $allowedProperties = ['{DAV:}getetag'];
167
+        $server->protectedProperties = array_diff($server->protectedProperties, $allowedProperties);
168
+
169
+        $this->server = $server;
170
+        $this->server->on('propFind', array($this, 'handleGetProperties'));
171
+        $this->server->on('propPatch', array($this, 'handleUpdateProperties'));
172
+        $this->server->on('afterBind', array($this, 'sendFileIdHeader'));
173
+        $this->server->on('afterWriteContent', array($this, 'sendFileIdHeader'));
174
+        $this->server->on('afterMethod:GET', [$this,'httpGet']);
175
+        $this->server->on('afterMethod:GET', array($this, 'handleDownloadToken'));
176
+        $this->server->on('afterResponse', function($request, ResponseInterface $response) {
177
+            $body = $response->getBody();
178
+            if (is_resource($body)) {
179
+                fclose($body);
180
+            }
181
+        });
182
+        $this->server->on('beforeMove', [$this, 'checkMove']);
183
+    }
184
+
185
+    /**
186
+     * Plugin that checks if a move can actually be performed.
187
+     *
188
+     * @param string $source source path
189
+     * @param string $destination destination path
190
+     * @throws Forbidden
191
+     * @throws NotFound
192
+     */
193
+    function checkMove($source, $destination) {
194
+        $sourceNode = $this->tree->getNodeForPath($source);
195
+        if (!$sourceNode instanceof Node) {
196
+            return;
197
+        }
198
+        list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($source);
199
+        list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destination);
200
+
201
+        if ($sourceDir !== $destinationDir) {
202
+            $sourceNodeFileInfo = $sourceNode->getFileInfo();
203
+            if (is_null($sourceNodeFileInfo)) {
204
+                throw new NotFound($source . ' does not exist');
205
+            }
206
+
207
+            if (!$sourceNodeFileInfo->isDeletable()) {
208
+                throw new Forbidden($source . " cannot be deleted");
209
+            }
210
+        }
211
+    }
212
+
213
+    /**
214
+     * This sets a cookie to be able to recognize the start of the download
215
+     * the content must not be longer than 32 characters and must only contain
216
+     * alphanumeric characters
217
+     *
218
+     * @param RequestInterface $request
219
+     * @param ResponseInterface $response
220
+     */
221
+    function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
222
+        $queryParams = $request->getQueryParameters();
223
+
224
+        /**
225
+         * this sets a cookie to be able to recognize the start of the download
226
+         * the content must not be longer than 32 characters and must only contain
227
+         * alphanumeric characters
228
+         */
229
+        if (isset($queryParams['downloadStartSecret'])) {
230
+            $token = $queryParams['downloadStartSecret'];
231
+            if (!isset($token[32])
232
+                && preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
233
+                // FIXME: use $response->setHeader() instead
234
+                setcookie('ocDownloadStarted', $token, time() + 20, '/');
235
+            }
236
+        }
237
+    }
238
+
239
+    /**
240
+     * Add headers to file download
241
+     *
242
+     * @param RequestInterface $request
243
+     * @param ResponseInterface $response
244
+     */
245
+    function httpGet(RequestInterface $request, ResponseInterface $response) {
246
+        // Only handle valid files
247
+        $node = $this->tree->getNodeForPath($request->getPath());
248
+        if (!($node instanceof IFile)) return;
249
+
250
+        // adds a 'Content-Disposition: attachment' header in case no disposition
251
+        // header has been set before
252
+        if ($this->downloadAttachment &&
253
+            $response->getHeader('Content-Disposition') === null) {
254
+            $filename = $node->getName();
255
+            if ($this->request->isUserAgent(
256
+                [
257
+                    \OC\AppFramework\Http\Request::USER_AGENT_IE,
258
+                    \OC\AppFramework\Http\Request::USER_AGENT_ANDROID_MOBILE_CHROME,
259
+                    \OC\AppFramework\Http\Request::USER_AGENT_FREEBOX,
260
+                ])) {
261
+                $response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
262
+            } else {
263
+                $response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
264
+                                                        . '; filename="' . rawurlencode($filename) . '"');
265
+            }
266
+        }
267
+
268
+        if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
269
+            //Add OC-Checksum header
270
+            /** @var $node File */
271
+            $checksum = $node->getChecksum();
272
+            if ($checksum !== null && $checksum !== '') {
273
+                $response->addHeader('OC-Checksum', $checksum);
274
+            }
275
+        }
276
+    }
277
+
278
+    /**
279
+     * Adds all ownCloud-specific properties
280
+     *
281
+     * @param PropFind $propFind
282
+     * @param \Sabre\DAV\INode $node
283
+     * @return void
284
+     */
285
+    public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
286
+
287
+        $httpRequest = $this->server->httpRequest;
288
+
289
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
290
+
291
+            $propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) {
292
+                return $node->getFileId();
293
+            });
294
+
295
+            $propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) {
296
+                return $node->getInternalFileId();
297
+            });
298
+
299
+            $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) {
300
+                $perms = $node->getDavPermissions();
301
+                if ($this->isPublic) {
302
+                    // remove mount information
303
+                    $perms = str_replace(['S', 'M'], '', $perms);
304
+                }
305
+                return $perms;
306
+            });
307
+
308
+            $propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
309
+                return $node->getSharePermissions(
310
+                    $httpRequest->getRawServerValue('PHP_AUTH_USER')
311
+                );
312
+            });
313
+
314
+            $propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) {
315
+                return $node->getETag();
316
+            });
317
+
318
+            $propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) {
319
+                $owner = $node->getOwner();
320
+                if (!$owner) {
321
+                    return null;
322
+                } else {
323
+                    return $owner->getUID();
324
+                }
325
+            });
326
+            $propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) {
327
+                $owner = $node->getOwner();
328
+                if (!$owner) {
329
+                    return null;
330
+                } else {
331
+                    return $owner->getDisplayName();
332
+                }
333
+            });
334
+
335
+            $propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
336
+                return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
337
+            });
338
+            $propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
339
+                return $node->getSize();
340
+            });
341
+        }
342
+
343
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
344
+            $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
345
+                return $this->config->getSystemValue('data-fingerprint', '');
346
+            });
347
+        }
348
+
349
+        if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
350
+            $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
351
+                /** @var $node \OCA\DAV\Connector\Sabre\File */
352
+                try {
353
+                    $directDownloadUrl = $node->getDirectDownload();
354
+                    if (isset($directDownloadUrl['url'])) {
355
+                        return $directDownloadUrl['url'];
356
+                    }
357
+                } catch (StorageNotAvailableException $e) {
358
+                    return false;
359
+                } catch (ForbiddenException $e) {
360
+                    return false;
361
+                }
362
+                return false;
363
+            });
364
+
365
+            $propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
366
+                $checksum = $node->getChecksum();
367
+                if ($checksum === NULL || $checksum === '') {
368
+                    return null;
369
+                }
370
+
371
+                return new ChecksumList($checksum);
372
+            });
373
+
374
+        }
375
+
376
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
377
+            $propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
378
+                return $node->getSize();
379
+            });
380
+        }
381
+    }
382
+
383
+    /**
384
+     * Update ownCloud-specific properties
385
+     *
386
+     * @param string $path
387
+     * @param PropPatch $propPatch
388
+     *
389
+     * @return void
390
+     */
391
+    public function handleUpdateProperties($path, PropPatch $propPatch) {
392
+        $propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function($time) use ($path) {
393
+            if (empty($time)) {
394
+                return false;
395
+            }
396
+            $node = $this->tree->getNodeForPath($path);
397
+            if (is_null($node)) {
398
+                return 404;
399
+            }
400
+            $node->touch($time);
401
+            return true;
402
+        });
403
+        $propPatch->handle(self::GETETAG_PROPERTYNAME, function($etag) use ($path) {
404
+            if (empty($etag)) {
405
+                return false;
406
+            }
407
+            $node = $this->tree->getNodeForPath($path);
408
+            if (is_null($node)) {
409
+                return 404;
410
+            }
411
+            if ($node->setEtag($etag) !== -1) {
412
+                return true;
413
+            }
414
+            return false;
415
+        });
416
+    }
417
+
418
+    /**
419
+     * @param string $filePath
420
+     * @param \Sabre\DAV\INode $node
421
+     * @throws \Sabre\DAV\Exception\BadRequest
422
+     */
423
+    public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
424
+        // chunked upload handling
425
+        if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
426
+            list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath);
427
+            $info = \OC_FileChunking::decodeName($name);
428
+            if (!empty($info)) {
429
+                $filePath = $path . '/' . $info['name'];
430
+            }
431
+        }
432
+
433
+        // we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
434
+        if (!$this->server->tree->nodeExists($filePath)) {
435
+            return;
436
+        }
437
+        $node = $this->server->tree->getNodeForPath($filePath);
438
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
439
+            $fileId = $node->getFileId();
440
+            if (!is_null($fileId)) {
441
+                $this->server->httpResponse->setHeader('OC-FileId', $fileId);
442
+            }
443
+        }
444
+    }
445 445
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
 		$this->server->on('propPatch', array($this, 'handleUpdateProperties'));
172 172
 		$this->server->on('afterBind', array($this, 'sendFileIdHeader'));
173 173
 		$this->server->on('afterWriteContent', array($this, 'sendFileIdHeader'));
174
-		$this->server->on('afterMethod:GET', [$this,'httpGet']);
174
+		$this->server->on('afterMethod:GET', [$this, 'httpGet']);
175 175
 		$this->server->on('afterMethod:GET', array($this, 'handleDownloadToken'));
176 176
 		$this->server->on('afterResponse', function($request, ResponseInterface $response) {
177 177
 			$body = $response->getBody();
@@ -201,11 +201,11 @@  discard block
 block discarded – undo
201 201
 		if ($sourceDir !== $destinationDir) {
202 202
 			$sourceNodeFileInfo = $sourceNode->getFileInfo();
203 203
 			if (is_null($sourceNodeFileInfo)) {
204
-				throw new NotFound($source . ' does not exist');
204
+				throw new NotFound($source.' does not exist');
205 205
 			}
206 206
 
207 207
 			if (!$sourceNodeFileInfo->isDeletable()) {
208
-				throw new Forbidden($source . " cannot be deleted");
208
+				throw new Forbidden($source." cannot be deleted");
209 209
 			}
210 210
 		}
211 211
 	}
@@ -258,10 +258,10 @@  discard block
 block discarded – undo
258 258
 					\OC\AppFramework\Http\Request::USER_AGENT_ANDROID_MOBILE_CHROME,
259 259
 					\OC\AppFramework\Http\Request::USER_AGENT_FREEBOX,
260 260
 				])) {
261
-				$response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
261
+				$response->addHeader('Content-Disposition', 'attachment; filename="'.rawurlencode($filename).'"');
262 262
 			} else {
263
-				$response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
264
-													 . '; filename="' . rawurlencode($filename) . '"');
263
+				$response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\''.rawurlencode($filename)
264
+													 . '; filename="'.rawurlencode($filename).'"');
265 265
 			}
266 266
 		}
267 267
 
@@ -332,7 +332,7 @@  discard block
 block discarded – undo
332 332
 				}
333 333
 			});
334 334
 
335
-			$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
335
+			$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function() use ($node) {
336 336
 				return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
337 337
 			});
338 338
 			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
@@ -426,7 +426,7 @@  discard block
 block discarded – undo
426 426
 			list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath);
427 427
 			$info = \OC_FileChunking::decodeName($name);
428 428
 			if (!empty($info)) {
429
-				$filePath = $path . '/' . $info['name'];
429
+				$filePath = $path.'/'.$info['name'];
430 430
 			}
431 431
 		}
432 432
 
Please login to merge, or discard this patch.