Completed
Pull Request — master (#5124)
by Joas
18:17
created
apps/dav/lib/Connector/Sabre/FilesPlugin.php 1 patch
Indentation   +438 added lines, -438 removed lines patch added patch discarded remove patch
@@ -49,447 +49,447 @@
 block discarded – undo
49 49
 
50 50
 class FilesPlugin extends ServerPlugin {
51 51
 
52
-	// namespace
53
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
54
-	const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
55
-	const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
56
-	const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
57
-	const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
58
-	const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
59
-	const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
60
-	const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
61
-	const GETETAG_PROPERTYNAME = '{DAV:}getetag';
62
-	const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
63
-	const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
64
-	const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
65
-	const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
66
-	const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
67
-	const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
68
-	const MOUNT_TYPE_PROPERTYNAME = '{http://nextcloud.org/ns}mount-type';
69
-
70
-	/**
71
-	 * Reference to main server object
72
-	 *
73
-	 * @var \Sabre\DAV\Server
74
-	 */
75
-	private $server;
76
-
77
-	/**
78
-	 * @var Tree
79
-	 */
80
-	private $tree;
81
-
82
-	/**
83
-	 * Whether this is public webdav.
84
-	 * If true, some returned information will be stripped off.
85
-	 *
86
-	 * @var bool
87
-	 */
88
-	private $isPublic;
89
-
90
-	/**
91
-	 * @var View
92
-	 */
93
-	private $fileView;
94
-
95
-	/**
96
-	 * @var bool
97
-	 */
98
-	private $downloadAttachment;
99
-
100
-	/**
101
-	 * @var IConfig
102
-	 */
103
-	private $config;
104
-
105
-	/**
106
-	 * @var IRequest
107
-	 */
108
-	private $request;
109
-
110
-	/**
111
-	 * @var IPreview
112
-	 */
113
-	private $previewManager;
114
-
115
-	/**
116
-	 * @param Tree $tree
117
-	 * @param IConfig $config
118
-	 * @param IRequest $request
119
-	 * @param IPreview $previewManager
120
-	 * @param bool $isPublic
121
-	 * @param bool $downloadAttachment
122
-	 */
123
-	public function __construct(Tree $tree,
124
-								IConfig $config,
125
-								IRequest $request,
126
-								IPreview $previewManager,
127
-								$isPublic = false,
128
-								$downloadAttachment = true) {
129
-		$this->tree = $tree;
130
-		$this->config = $config;
131
-		$this->request = $request;
132
-		$this->isPublic = $isPublic;
133
-		$this->downloadAttachment = $downloadAttachment;
134
-		$this->previewManager = $previewManager;
135
-	}
136
-
137
-	/**
138
-	 * This initializes the plugin.
139
-	 *
140
-	 * This function is called by \Sabre\DAV\Server, after
141
-	 * addPlugin is called.
142
-	 *
143
-	 * This method should set up the required event subscriptions.
144
-	 *
145
-	 * @param \Sabre\DAV\Server $server
146
-	 * @return void
147
-	 */
148
-	public function initialize(\Sabre\DAV\Server $server) {
149
-
150
-		$server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
151
-		$server->xml->namespaceMap[self::NS_NEXTCLOUD] = 'nc';
152
-		$server->protectedProperties[] = self::FILEID_PROPERTYNAME;
153
-		$server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
154
-		$server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
155
-		$server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
156
-		$server->protectedProperties[] = self::SIZE_PROPERTYNAME;
157
-		$server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
158
-		$server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
159
-		$server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
160
-		$server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
161
-		$server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
162
-		$server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
163
-		$server->protectedProperties[] = self::MOUNT_TYPE_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
-		$this->server->on('beforeMove', [$this, 'beforeMoveFutureFile']);
184
-	}
185
-
186
-	/**
187
-	 * Plugin that checks if a move can actually be performed.
188
-	 *
189
-	 * @param string $source source path
190
-	 * @param string $destination destination path
191
-	 * @throws Forbidden
192
-	 * @throws NotFound
193
-	 */
194
-	function checkMove($source, $destination) {
195
-		$sourceNode = $this->tree->getNodeForPath($source);
196
-		if (!$sourceNode instanceof Node) {
197
-			return;
198
-		}
199
-		list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($source);
200
-		list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destination);
201
-
202
-		if ($sourceDir !== $destinationDir) {
203
-			$sourceNodeFileInfo = $sourceNode->getFileInfo();
204
-			if (is_null($sourceNodeFileInfo)) {
205
-				throw new NotFound($source . ' does not exist');
206
-			}
207
-
208
-			if (!$sourceNodeFileInfo->isDeletable()) {
209
-				throw new Forbidden($source . " cannot be deleted");
210
-			}
211
-		}
212
-	}
213
-
214
-	/**
215
-	 * This sets a cookie to be able to recognize the start of the download
216
-	 * the content must not be longer than 32 characters and must only contain
217
-	 * alphanumeric characters
218
-	 *
219
-	 * @param RequestInterface $request
220
-	 * @param ResponseInterface $response
221
-	 */
222
-	function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
223
-		$queryParams = $request->getQueryParameters();
224
-
225
-		/**
226
-		 * this sets a cookie to be able to recognize the start of the download
227
-		 * the content must not be longer than 32 characters and must only contain
228
-		 * alphanumeric characters
229
-		 */
230
-		if (isset($queryParams['downloadStartSecret'])) {
231
-			$token = $queryParams['downloadStartSecret'];
232
-			if (!isset($token[32])
233
-				&& preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
234
-				// FIXME: use $response->setHeader() instead
235
-				setcookie('ocDownloadStarted', $token, time() + 20, '/');
236
-			}
237
-		}
238
-	}
239
-
240
-	/**
241
-	 * Add headers to file download
242
-	 *
243
-	 * @param RequestInterface $request
244
-	 * @param ResponseInterface $response
245
-	 */
246
-	function httpGet(RequestInterface $request, ResponseInterface $response) {
247
-		// Only handle valid files
248
-		$node = $this->tree->getNodeForPath($request->getPath());
249
-		if (!($node instanceof IFile)) return;
250
-
251
-		// adds a 'Content-Disposition: attachment' header in case no disposition
252
-		// header has been set before
253
-		if ($this->downloadAttachment &&
254
-			$response->getHeader('Content-Disposition') === null) {
255
-			$filename = $node->getName();
256
-			if ($this->request->isUserAgent(
257
-				[
258
-					\OC\AppFramework\Http\Request::USER_AGENT_IE,
259
-					\OC\AppFramework\Http\Request::USER_AGENT_ANDROID_MOBILE_CHROME,
260
-					\OC\AppFramework\Http\Request::USER_AGENT_FREEBOX,
261
-				])) {
262
-				$response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
263
-			} else {
264
-				$response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
265
-													 . '; filename="' . rawurlencode($filename) . '"');
266
-			}
267
-		}
268
-
269
-		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
270
-			//Add OC-Checksum header
271
-			/** @var $node File */
272
-			$checksum = $node->getChecksum();
273
-			if ($checksum !== null && $checksum !== '') {
274
-				$response->addHeader('OC-Checksum', $checksum);
275
-			}
276
-		}
277
-	}
278
-
279
-	/**
280
-	 * Adds all ownCloud-specific properties
281
-	 *
282
-	 * @param PropFind $propFind
283
-	 * @param \Sabre\DAV\INode $node
284
-	 * @return void
285
-	 */
286
-	public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
287
-
288
-		$httpRequest = $this->server->httpRequest;
289
-
290
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
291
-			/**
292
-			 * This was disabled, because it made dir listing throw an exception,
293
-			 * so users were unable to navigate into folders where one subitem
294
-			 * is blocked by the files_accesscontrol app, see:
295
-			 * https://github.com/nextcloud/files_accesscontrol/issues/65
52
+    // namespace
53
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
54
+    const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
55
+    const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
56
+    const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
57
+    const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
58
+    const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
59
+    const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
60
+    const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
61
+    const GETETAG_PROPERTYNAME = '{DAV:}getetag';
62
+    const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
63
+    const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
64
+    const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
65
+    const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
66
+    const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
67
+    const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
68
+    const MOUNT_TYPE_PROPERTYNAME = '{http://nextcloud.org/ns}mount-type';
69
+
70
+    /**
71
+     * Reference to main server object
72
+     *
73
+     * @var \Sabre\DAV\Server
74
+     */
75
+    private $server;
76
+
77
+    /**
78
+     * @var Tree
79
+     */
80
+    private $tree;
81
+
82
+    /**
83
+     * Whether this is public webdav.
84
+     * If true, some returned information will be stripped off.
85
+     *
86
+     * @var bool
87
+     */
88
+    private $isPublic;
89
+
90
+    /**
91
+     * @var View
92
+     */
93
+    private $fileView;
94
+
95
+    /**
96
+     * @var bool
97
+     */
98
+    private $downloadAttachment;
99
+
100
+    /**
101
+     * @var IConfig
102
+     */
103
+    private $config;
104
+
105
+    /**
106
+     * @var IRequest
107
+     */
108
+    private $request;
109
+
110
+    /**
111
+     * @var IPreview
112
+     */
113
+    private $previewManager;
114
+
115
+    /**
116
+     * @param Tree $tree
117
+     * @param IConfig $config
118
+     * @param IRequest $request
119
+     * @param IPreview $previewManager
120
+     * @param bool $isPublic
121
+     * @param bool $downloadAttachment
122
+     */
123
+    public function __construct(Tree $tree,
124
+                                IConfig $config,
125
+                                IRequest $request,
126
+                                IPreview $previewManager,
127
+                                $isPublic = false,
128
+                                $downloadAttachment = true) {
129
+        $this->tree = $tree;
130
+        $this->config = $config;
131
+        $this->request = $request;
132
+        $this->isPublic = $isPublic;
133
+        $this->downloadAttachment = $downloadAttachment;
134
+        $this->previewManager = $previewManager;
135
+    }
136
+
137
+    /**
138
+     * This initializes the plugin.
139
+     *
140
+     * This function is called by \Sabre\DAV\Server, after
141
+     * addPlugin is called.
142
+     *
143
+     * This method should set up the required event subscriptions.
144
+     *
145
+     * @param \Sabre\DAV\Server $server
146
+     * @return void
147
+     */
148
+    public function initialize(\Sabre\DAV\Server $server) {
149
+
150
+        $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
151
+        $server->xml->namespaceMap[self::NS_NEXTCLOUD] = 'nc';
152
+        $server->protectedProperties[] = self::FILEID_PROPERTYNAME;
153
+        $server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
154
+        $server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
155
+        $server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
156
+        $server->protectedProperties[] = self::SIZE_PROPERTYNAME;
157
+        $server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
158
+        $server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
159
+        $server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
160
+        $server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
161
+        $server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
162
+        $server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
163
+        $server->protectedProperties[] = self::MOUNT_TYPE_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
+        $this->server->on('beforeMove', [$this, 'beforeMoveFutureFile']);
184
+    }
185
+
186
+    /**
187
+     * Plugin that checks if a move can actually be performed.
188
+     *
189
+     * @param string $source source path
190
+     * @param string $destination destination path
191
+     * @throws Forbidden
192
+     * @throws NotFound
193
+     */
194
+    function checkMove($source, $destination) {
195
+        $sourceNode = $this->tree->getNodeForPath($source);
196
+        if (!$sourceNode instanceof Node) {
197
+            return;
198
+        }
199
+        list($sourceDir,) = \Sabre\HTTP\URLUtil::splitPath($source);
200
+        list($destinationDir,) = \Sabre\HTTP\URLUtil::splitPath($destination);
201
+
202
+        if ($sourceDir !== $destinationDir) {
203
+            $sourceNodeFileInfo = $sourceNode->getFileInfo();
204
+            if (is_null($sourceNodeFileInfo)) {
205
+                throw new NotFound($source . ' does not exist');
206
+            }
207
+
208
+            if (!$sourceNodeFileInfo->isDeletable()) {
209
+                throw new Forbidden($source . " cannot be deleted");
210
+            }
211
+        }
212
+    }
213
+
214
+    /**
215
+     * This sets a cookie to be able to recognize the start of the download
216
+     * the content must not be longer than 32 characters and must only contain
217
+     * alphanumeric characters
218
+     *
219
+     * @param RequestInterface $request
220
+     * @param ResponseInterface $response
221
+     */
222
+    function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
223
+        $queryParams = $request->getQueryParameters();
224
+
225
+        /**
226
+         * this sets a cookie to be able to recognize the start of the download
227
+         * the content must not be longer than 32 characters and must only contain
228
+         * alphanumeric characters
229
+         */
230
+        if (isset($queryParams['downloadStartSecret'])) {
231
+            $token = $queryParams['downloadStartSecret'];
232
+            if (!isset($token[32])
233
+                && preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
234
+                // FIXME: use $response->setHeader() instead
235
+                setcookie('ocDownloadStarted', $token, time() + 20, '/');
236
+            }
237
+        }
238
+    }
239
+
240
+    /**
241
+     * Add headers to file download
242
+     *
243
+     * @param RequestInterface $request
244
+     * @param ResponseInterface $response
245
+     */
246
+    function httpGet(RequestInterface $request, ResponseInterface $response) {
247
+        // Only handle valid files
248
+        $node = $this->tree->getNodeForPath($request->getPath());
249
+        if (!($node instanceof IFile)) return;
250
+
251
+        // adds a 'Content-Disposition: attachment' header in case no disposition
252
+        // header has been set before
253
+        if ($this->downloadAttachment &&
254
+            $response->getHeader('Content-Disposition') === null) {
255
+            $filename = $node->getName();
256
+            if ($this->request->isUserAgent(
257
+                [
258
+                    \OC\AppFramework\Http\Request::USER_AGENT_IE,
259
+                    \OC\AppFramework\Http\Request::USER_AGENT_ANDROID_MOBILE_CHROME,
260
+                    \OC\AppFramework\Http\Request::USER_AGENT_FREEBOX,
261
+                ])) {
262
+                $response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
263
+            } else {
264
+                $response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
265
+                                                        . '; filename="' . rawurlencode($filename) . '"');
266
+            }
267
+        }
268
+
269
+        if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
270
+            //Add OC-Checksum header
271
+            /** @var $node File */
272
+            $checksum = $node->getChecksum();
273
+            if ($checksum !== null && $checksum !== '') {
274
+                $response->addHeader('OC-Checksum', $checksum);
275
+            }
276
+        }
277
+    }
278
+
279
+    /**
280
+     * Adds all ownCloud-specific properties
281
+     *
282
+     * @param PropFind $propFind
283
+     * @param \Sabre\DAV\INode $node
284
+     * @return void
285
+     */
286
+    public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
287
+
288
+        $httpRequest = $this->server->httpRequest;
289
+
290
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
291
+            /**
292
+             * This was disabled, because it made dir listing throw an exception,
293
+             * so users were unable to navigate into folders where one subitem
294
+             * is blocked by the files_accesscontrol app, see:
295
+             * https://github.com/nextcloud/files_accesscontrol/issues/65
296 296
 			if (!$node->getFileInfo()->isReadable()) {
297 297
 				// avoid detecting files through this means
298 298
 				throw new NotFound();
299 299
 			}
300
-			 */
301
-
302
-			$propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) {
303
-				return $node->getFileId();
304
-			});
305
-
306
-			$propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) {
307
-				return $node->getInternalFileId();
308
-			});
309
-
310
-			$propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) {
311
-				$perms = $node->getDavPermissions();
312
-				if ($this->isPublic) {
313
-					// remove mount information
314
-					$perms = str_replace(['S', 'M'], '', $perms);
315
-				}
316
-				return $perms;
317
-			});
318
-
319
-			$propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
320
-				return $node->getSharePermissions(
321
-					$httpRequest->getRawServerValue('PHP_AUTH_USER')
322
-				);
323
-			});
324
-
325
-			$propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) {
326
-				return $node->getETag();
327
-			});
328
-
329
-			$propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) {
330
-				$owner = $node->getOwner();
331
-				if (!$owner) {
332
-					return null;
333
-				} else {
334
-					return $owner->getUID();
335
-				}
336
-			});
337
-			$propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) {
338
-				$owner = $node->getOwner();
339
-				if (!$owner) {
340
-					return null;
341
-				} else {
342
-					return $owner->getDisplayName();
343
-				}
344
-			});
345
-
346
-			$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
347
-				return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
348
-			});
349
-			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
350
-				return $node->getSize();
351
-			});
352
-			$propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) {
353
-				return $node->getFileInfo()->getMountPoint()->getMountType();
354
-			});
355
-		}
356
-
357
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
358
-			$propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
359
-				return $this->config->getSystemValue('data-fingerprint', '');
360
-			});
361
-		}
362
-
363
-		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
364
-			$propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
365
-				/** @var $node \OCA\DAV\Connector\Sabre\File */
366
-				try {
367
-					$directDownloadUrl = $node->getDirectDownload();
368
-					if (isset($directDownloadUrl['url'])) {
369
-						return $directDownloadUrl['url'];
370
-					}
371
-				} catch (StorageNotAvailableException $e) {
372
-					return false;
373
-				} catch (ForbiddenException $e) {
374
-					return false;
375
-				}
376
-				return false;
377
-			});
378
-
379
-			$propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
380
-				$checksum = $node->getChecksum();
381
-				if ($checksum === NULL || $checksum === '') {
382
-					return null;
383
-				}
384
-
385
-				return new ChecksumList($checksum);
386
-			});
387
-
388
-		}
389
-
390
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
391
-			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
392
-				return $node->getSize();
393
-			});
394
-		}
395
-	}
396
-
397
-	/**
398
-	 * Update ownCloud-specific properties
399
-	 *
400
-	 * @param string $path
401
-	 * @param PropPatch $propPatch
402
-	 *
403
-	 * @return void
404
-	 */
405
-	public function handleUpdateProperties($path, PropPatch $propPatch) {
406
-		$node = $this->tree->getNodeForPath($path);
407
-		if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
408
-			return;
409
-		}
410
-
411
-		$propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function($time) use ($node) {
412
-			if (empty($time)) {
413
-				return false;
414
-			}
415
-			$node->touch($time);
416
-			return true;
417
-		});
418
-		$propPatch->handle(self::GETETAG_PROPERTYNAME, function($etag) use ($node) {
419
-			if (empty($etag)) {
420
-				return false;
421
-			}
422
-			if ($node->setEtag($etag) !== -1) {
423
-				return true;
424
-			}
425
-			return false;
426
-		});
427
-	}
428
-
429
-	/**
430
-	 * @param string $filePath
431
-	 * @param \Sabre\DAV\INode $node
432
-	 * @throws \Sabre\DAV\Exception\BadRequest
433
-	 */
434
-	public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
435
-		// chunked upload handling
436
-		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
437
-			list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath);
438
-			$info = \OC_FileChunking::decodeName($name);
439
-			if (!empty($info)) {
440
-				$filePath = $path . '/' . $info['name'];
441
-			}
442
-		}
443
-
444
-		// we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
445
-		if (!$this->server->tree->nodeExists($filePath)) {
446
-			return;
447
-		}
448
-		$node = $this->server->tree->getNodeForPath($filePath);
449
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
450
-			$fileId = $node->getFileId();
451
-			if (!is_null($fileId)) {
452
-				$this->server->httpResponse->setHeader('OC-FileId', $fileId);
453
-			}
454
-		}
455
-	}
456
-
457
-	/**
458
-	 * Move handler for future file.
459
-	 *
460
-	 * This overrides the default move behavior to prevent Sabre
461
-	 * to delete the target file before moving. Because deleting would
462
-	 * lose the file id and metadata.
463
-	 *
464
-	 * @param string $path source path
465
-	 * @param string $destination destination path
466
-	 * @return bool|void false to stop handling, void to skip this handler
467
-	 */
468
-	public function beforeMoveFutureFile($path, $destination) {
469
-		$sourceNode = $this->tree->getNodeForPath($path);
470
-		if (!$sourceNode instanceof FutureFile) {
471
-			// skip handling as the source is not a chunked FutureFile
472
-			return;
473
-		}
474
-
475
-		if (!$this->tree->nodeExists($destination)) {
476
-			// skip and let the default handler do its work
477
-			return;
478
-		}
479
-
480
-		// do a move manually, skipping Sabre's default "delete" for existing nodes
481
-		$this->tree->move($path, $destination);
482
-
483
-		// trigger all default events (copied from CorePlugin::move)
484
-		$this->server->emit('afterMove', [$path, $destination]);
485
-		$this->server->emit('afterUnbind', [$path]);
486
-		$this->server->emit('afterBind', [$destination]);
487
-
488
-		$response = $this->server->httpResponse;
489
-		$response->setHeader('Content-Length', '0');
490
-		$response->setStatus(204);
491
-
492
-		return false;
493
-	}
300
+             */
301
+
302
+            $propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) {
303
+                return $node->getFileId();
304
+            });
305
+
306
+            $propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) {
307
+                return $node->getInternalFileId();
308
+            });
309
+
310
+            $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) {
311
+                $perms = $node->getDavPermissions();
312
+                if ($this->isPublic) {
313
+                    // remove mount information
314
+                    $perms = str_replace(['S', 'M'], '', $perms);
315
+                }
316
+                return $perms;
317
+            });
318
+
319
+            $propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
320
+                return $node->getSharePermissions(
321
+                    $httpRequest->getRawServerValue('PHP_AUTH_USER')
322
+                );
323
+            });
324
+
325
+            $propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) {
326
+                return $node->getETag();
327
+            });
328
+
329
+            $propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) {
330
+                $owner = $node->getOwner();
331
+                if (!$owner) {
332
+                    return null;
333
+                } else {
334
+                    return $owner->getUID();
335
+                }
336
+            });
337
+            $propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) {
338
+                $owner = $node->getOwner();
339
+                if (!$owner) {
340
+                    return null;
341
+                } else {
342
+                    return $owner->getDisplayName();
343
+                }
344
+            });
345
+
346
+            $propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
347
+                return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
348
+            });
349
+            $propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
350
+                return $node->getSize();
351
+            });
352
+            $propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) {
353
+                return $node->getFileInfo()->getMountPoint()->getMountType();
354
+            });
355
+        }
356
+
357
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
358
+            $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
359
+                return $this->config->getSystemValue('data-fingerprint', '');
360
+            });
361
+        }
362
+
363
+        if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
364
+            $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
365
+                /** @var $node \OCA\DAV\Connector\Sabre\File */
366
+                try {
367
+                    $directDownloadUrl = $node->getDirectDownload();
368
+                    if (isset($directDownloadUrl['url'])) {
369
+                        return $directDownloadUrl['url'];
370
+                    }
371
+                } catch (StorageNotAvailableException $e) {
372
+                    return false;
373
+                } catch (ForbiddenException $e) {
374
+                    return false;
375
+                }
376
+                return false;
377
+            });
378
+
379
+            $propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
380
+                $checksum = $node->getChecksum();
381
+                if ($checksum === NULL || $checksum === '') {
382
+                    return null;
383
+                }
384
+
385
+                return new ChecksumList($checksum);
386
+            });
387
+
388
+        }
389
+
390
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
391
+            $propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
392
+                return $node->getSize();
393
+            });
394
+        }
395
+    }
396
+
397
+    /**
398
+     * Update ownCloud-specific properties
399
+     *
400
+     * @param string $path
401
+     * @param PropPatch $propPatch
402
+     *
403
+     * @return void
404
+     */
405
+    public function handleUpdateProperties($path, PropPatch $propPatch) {
406
+        $node = $this->tree->getNodeForPath($path);
407
+        if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
408
+            return;
409
+        }
410
+
411
+        $propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function($time) use ($node) {
412
+            if (empty($time)) {
413
+                return false;
414
+            }
415
+            $node->touch($time);
416
+            return true;
417
+        });
418
+        $propPatch->handle(self::GETETAG_PROPERTYNAME, function($etag) use ($node) {
419
+            if (empty($etag)) {
420
+                return false;
421
+            }
422
+            if ($node->setEtag($etag) !== -1) {
423
+                return true;
424
+            }
425
+            return false;
426
+        });
427
+    }
428
+
429
+    /**
430
+     * @param string $filePath
431
+     * @param \Sabre\DAV\INode $node
432
+     * @throws \Sabre\DAV\Exception\BadRequest
433
+     */
434
+    public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
435
+        // chunked upload handling
436
+        if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
437
+            list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($filePath);
438
+            $info = \OC_FileChunking::decodeName($name);
439
+            if (!empty($info)) {
440
+                $filePath = $path . '/' . $info['name'];
441
+            }
442
+        }
443
+
444
+        // we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
445
+        if (!$this->server->tree->nodeExists($filePath)) {
446
+            return;
447
+        }
448
+        $node = $this->server->tree->getNodeForPath($filePath);
449
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
450
+            $fileId = $node->getFileId();
451
+            if (!is_null($fileId)) {
452
+                $this->server->httpResponse->setHeader('OC-FileId', $fileId);
453
+            }
454
+        }
455
+    }
456
+
457
+    /**
458
+     * Move handler for future file.
459
+     *
460
+     * This overrides the default move behavior to prevent Sabre
461
+     * to delete the target file before moving. Because deleting would
462
+     * lose the file id and metadata.
463
+     *
464
+     * @param string $path source path
465
+     * @param string $destination destination path
466
+     * @return bool|void false to stop handling, void to skip this handler
467
+     */
468
+    public function beforeMoveFutureFile($path, $destination) {
469
+        $sourceNode = $this->tree->getNodeForPath($path);
470
+        if (!$sourceNode instanceof FutureFile) {
471
+            // skip handling as the source is not a chunked FutureFile
472
+            return;
473
+        }
474
+
475
+        if (!$this->tree->nodeExists($destination)) {
476
+            // skip and let the default handler do its work
477
+            return;
478
+        }
479
+
480
+        // do a move manually, skipping Sabre's default "delete" for existing nodes
481
+        $this->tree->move($path, $destination);
482
+
483
+        // trigger all default events (copied from CorePlugin::move)
484
+        $this->server->emit('afterMove', [$path, $destination]);
485
+        $this->server->emit('afterUnbind', [$path]);
486
+        $this->server->emit('afterBind', [$destination]);
487
+
488
+        $response = $this->server->httpResponse;
489
+        $response->setHeader('Content-Length', '0');
490
+        $response->setStatus(204);
491
+
492
+        return false;
493
+    }
494 494
 
495 495
 }
Please login to merge, or discard this patch.