Completed
Push — stable10 ( 8b490e...c03b88 )
by Morris
14:15 queued 13:47
created
apps/dav/lib/Connector/Sabre/ChecksumList.php 3 patches
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -21,7 +21,6 @@
 block discarded – undo
21 21
 namespace OCA\DAV\Connector\Sabre;
22 22
 
23 23
 use Sabre\Xml\XmlSerializable;
24
-use Sabre\Xml\Element;
25 24
 use Sabre\Xml\Writer;
26 25
 
27 26
 /**
Please login to merge, or discard this patch.
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -32,41 +32,41 @@
 block discarded – undo
32 32
  * checksum name.
33 33
  */
34 34
 class ChecksumList implements XmlSerializable {
35
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
35
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
36 36
 
37
-	/** @var string[] of TYPE:CHECKSUM */
38
-	private $checksums;
37
+    /** @var string[] of TYPE:CHECKSUM */
38
+    private $checksums;
39 39
 
40
-	/**
41
-	 * @param string $checksum
42
-	 */
43
-	public function __construct($checksum) {
44
-		$this->checksums = explode(',', $checksum);
45
-	}
40
+    /**
41
+     * @param string $checksum
42
+     */
43
+    public function __construct($checksum) {
44
+        $this->checksums = explode(',', $checksum);
45
+    }
46 46
 
47
-	/**
48
-	 * The xmlSerialize metod is called during xml writing.
49
-	 *
50
-	 * Use the $writer argument to write its own xml serialization.
51
-	 *
52
-	 * An important note: do _not_ create a parent element. Any element
53
-	 * implementing XmlSerializble should only ever write what's considered
54
-	 * its 'inner xml'.
55
-	 *
56
-	 * The parent of the current element is responsible for writing a
57
-	 * containing element.
58
-	 *
59
-	 * This allows serializers to be re-used for different element names.
60
-	 *
61
-	 * If you are opening new elements, you must also close them again.
62
-	 *
63
-	 * @param Writer $writer
64
-	 * @return void
65
-	 */
66
-	function xmlSerialize(Writer $writer) {
47
+    /**
48
+     * The xmlSerialize metod is called during xml writing.
49
+     *
50
+     * Use the $writer argument to write its own xml serialization.
51
+     *
52
+     * An important note: do _not_ create a parent element. Any element
53
+     * implementing XmlSerializble should only ever write what's considered
54
+     * its 'inner xml'.
55
+     *
56
+     * The parent of the current element is responsible for writing a
57
+     * containing element.
58
+     *
59
+     * This allows serializers to be re-used for different element names.
60
+     *
61
+     * If you are opening new elements, you must also close them again.
62
+     *
63
+     * @param Writer $writer
64
+     * @return void
65
+     */
66
+    function xmlSerialize(Writer $writer) {
67 67
 
68
-		foreach ($this->checksums as $checksum) {
69
-			$writer->writeElement('{' . self::NS_OWNCLOUD . '}checksum', $checksum);
70
-		}
71
-	}
68
+        foreach ($this->checksums as $checksum) {
69
+            $writer->writeElement('{' . self::NS_OWNCLOUD . '}checksum', $checksum);
70
+        }
71
+    }
72 72
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -66,7 +66,7 @@
 block discarded – undo
66 66
 	function xmlSerialize(Writer $writer) {
67 67
 
68 68
 		foreach ($this->checksums as $checksum) {
69
-			$writer->writeElement('{' . self::NS_OWNCLOUD . '}checksum', $checksum);
69
+			$writer->writeElement('{'.self::NS_OWNCLOUD.'}checksum', $checksum);
70 70
 		}
71 71
 	}
72 72
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/CustomPropertiesBackend.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -75,7 +75,7 @@
 block discarded – undo
75 75
 	private $cache = [];
76 76
 
77 77
 	/**
78
-	 * @param Tree $tree node tree
78
+	 * @param ObjectTree $tree node tree
79 79
 	 * @param IDBConnection $connection database connection
80 80
 	 * @param IUser $user owner of the tree and properties
81 81
 	 */
Please login to merge, or discard this patch.
Indentation   +317 added lines, -317 removed lines patch added patch discarded remove patch
@@ -36,322 +36,322 @@
 block discarded – undo
36 36
 
37 37
 class CustomPropertiesBackend implements BackendInterface {
38 38
 
39
-	/**
40
-	 * Ignored properties
41
-	 *
42
-	 * @var array
43
-	 */
44
-	private $ignoredProperties = array(
45
-		'{DAV:}getcontentlength',
46
-		'{DAV:}getcontenttype',
47
-		'{DAV:}getetag',
48
-		'{DAV:}quota-used-bytes',
49
-		'{DAV:}quota-available-bytes',
50
-		'{DAV:}quota-available-bytes',
51
-		'{http://owncloud.org/ns}permissions',
52
-		'{http://owncloud.org/ns}downloadURL',
53
-		'{http://owncloud.org/ns}dDC',
54
-		'{http://owncloud.org/ns}size',
55
-	);
56
-
57
-	/**
58
-	 * @var Tree
59
-	 */
60
-	private $tree;
61
-
62
-	/**
63
-	 * @var IDBConnection
64
-	 */
65
-	private $connection;
66
-
67
-	/**
68
-	 * @var IUser
69
-	 */
70
-	private $user;
71
-
72
-	/**
73
-	 * Properties cache
74
-	 *
75
-	 * @var array
76
-	 */
77
-	private $cache = [];
78
-
79
-	/**
80
-	 * @param Tree $tree node tree
81
-	 * @param IDBConnection $connection database connection
82
-	 * @param IUser $user owner of the tree and properties
83
-	 */
84
-	public function __construct(
85
-		Tree $tree,
86
-		IDBConnection $connection,
87
-		IUser $user) {
88
-		$this->tree = $tree;
89
-		$this->connection = $connection;
90
-		$this->user = $user->getUID();
91
-	}
92
-
93
-	/**
94
-	 * Fetches properties for a path.
95
-	 *
96
-	 * @param string $path
97
-	 * @param PropFind $propFind
98
-	 * @return void
99
-	 */
100
-	public function propFind($path, PropFind $propFind) {
101
-		try {
102
-			$node = $this->tree->getNodeForPath($path);
103
-			if (!($node instanceof Node)) {
104
-				return;
105
-			}
106
-		} catch (ServiceUnavailable $e) {
107
-			// might happen for unavailable mount points, skip
108
-			return;
109
-		} catch (NotFound $e) {
110
-			// in some rare (buggy) cases the node might not be found,
111
-			// we catch the exception to prevent breaking the whole list with a 404
112
-			// (soft fail)
113
-			\OC::$server->getLogger()->warning(
114
-				'Could not get node for path: \"' . $path . '\" : ' . $e->getMessage(),
115
-				array('app' => 'files')
116
-			);
117
-			return;
118
-		}
119
-
120
-		$requestedProps = $propFind->get404Properties();
121
-
122
-		// these might appear
123
-		$requestedProps = array_diff(
124
-			$requestedProps,
125
-			$this->ignoredProperties
126
-		);
127
-
128
-		if (empty($requestedProps)) {
129
-			return;
130
-		}
131
-
132
-		if ($node instanceof Directory
133
-			&& $propFind->getDepth() !== 0
134
-		) {
135
-			// note: pre-fetching only supported for depth <= 1
136
-			$this->loadChildrenProperties($node, $requestedProps);
137
-		}
138
-
139
-		$props = $this->getProperties($node, $requestedProps);
140
-		foreach ($props as $propName => $propValue) {
141
-			$propFind->set($propName, $propValue);
142
-		}
143
-	}
144
-
145
-	/**
146
-	 * Updates properties for a path
147
-	 *
148
-	 * @param string $path
149
-	 * @param PropPatch $propPatch
150
-	 *
151
-	 * @return void
152
-	 */
153
-	public function propPatch($path, PropPatch $propPatch) {
154
-		$node = $this->tree->getNodeForPath($path);
155
-		if (!($node instanceof Node)) {
156
-			return;
157
-		}
158
-
159
-		$propPatch->handleRemaining(function($changedProps) use ($node) {
160
-			return $this->updateProperties($node, $changedProps);
161
-		});
162
-	}
163
-
164
-	/**
165
-	 * This method is called after a node is deleted.
166
-	 *
167
-	 * @param string $path path of node for which to delete properties
168
-	 */
169
-	public function delete($path) {
170
-		$statement = $this->connection->prepare(
171
-			'DELETE FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?'
172
-		);
173
-		$statement->execute(array($this->user, '/' . $path));
174
-		$statement->closeCursor();
175
-
176
-		unset($this->cache[$path]);
177
-	}
178
-
179
-	/**
180
-	 * This method is called after a successful MOVE
181
-	 *
182
-	 * @param string $source
183
-	 * @param string $destination
184
-	 *
185
-	 * @return void
186
-	 */
187
-	public function move($source, $destination) {
188
-		$statement = $this->connection->prepare(
189
-			'UPDATE `*PREFIX*properties` SET `propertypath` = ?' .
190
-			' WHERE `userid` = ? AND `propertypath` = ?'
191
-		);
192
-		$statement->execute(array('/' . $destination, $this->user, '/' . $source));
193
-		$statement->closeCursor();
194
-	}
195
-
196
-	/**
197
-	 * Returns a list of properties for this nodes.;
198
-	 * @param Node $node
199
-	 * @param array $requestedProperties requested properties or empty array for "all"
200
-	 * @return array
201
-	 * @note The properties list is a list of propertynames the client
202
-	 * requested, encoded as xmlnamespace#tagName, for example:
203
-	 * http://www.example.org/namespace#author If the array is empty, all
204
-	 * properties should be returned
205
-	 */
206
-	private function getProperties(Node $node, array $requestedProperties) {
207
-		$path = $node->getPath();
208
-		if (isset($this->cache[$path])) {
209
-			return $this->cache[$path];
210
-		}
211
-
212
-		// TODO: chunking if more than 1000 properties
213
-		$sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?';
214
-
215
-		$whereValues = array($this->user, $path);
216
-		$whereTypes = array(null, null);
217
-
218
-		if (!empty($requestedProperties)) {
219
-			// request only a subset
220
-			$sql .= ' AND `propertyname` in (?)';
221
-			$whereValues[] = $requestedProperties;
222
-			$whereTypes[] = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY;
223
-		}
224
-
225
-		$result = $this->connection->executeQuery(
226
-			$sql,
227
-			$whereValues,
228
-			$whereTypes
229
-		);
230
-
231
-		$props = [];
232
-		while ($row = $result->fetch()) {
233
-			$props[$row['propertyname']] = $row['propertyvalue'];
234
-		}
235
-
236
-		$result->closeCursor();
237
-
238
-		$this->cache[$path] = $props;
239
-		return $props;
240
-	}
241
-
242
-	/**
243
-	 * Update properties
244
-	 *
245
-	 * @param Node $node node for which to update properties
246
-	 * @param array $properties array of properties to update
247
-	 *
248
-	 * @return bool
249
-	 */
250
-	private function updateProperties($node, $properties) {
251
-		$path = $node->getPath();
252
-
253
-		$deleteStatement = 'DELETE FROM `*PREFIX*properties`' .
254
-			' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
255
-
256
-		$insertStatement = 'INSERT INTO `*PREFIX*properties`' .
257
-			' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)';
258
-
259
-		$updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?' .
260
-			' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
261
-
262
-		// TODO: use "insert or update" strategy ?
263
-		$existing = $this->getProperties($node, array());
264
-		$this->connection->beginTransaction();
265
-		foreach ($properties as $propertyName => $propertyValue) {
266
-			// If it was null, we need to delete the property
267
-			if (is_null($propertyValue)) {
268
-				if (array_key_exists($propertyName, $existing)) {
269
-					$this->connection->executeUpdate($deleteStatement,
270
-						array(
271
-							$this->user,
272
-							$path,
273
-							$propertyName
274
-						)
275
-					);
276
-				}
277
-			} else {
278
-				if (!array_key_exists($propertyName, $existing)) {
279
-					$this->connection->executeUpdate($insertStatement,
280
-						array(
281
-							$this->user,
282
-							$path,
283
-							$propertyName,
284
-							$propertyValue
285
-						)
286
-					);
287
-				} else {
288
-					$this->connection->executeUpdate($updateStatement,
289
-						array(
290
-							$propertyValue,
291
-							$this->user,
292
-							$path,
293
-							$propertyName
294
-						)
295
-					);
296
-				}
297
-			}
298
-		}
299
-
300
-		$this->connection->commit();
301
-		unset($this->cache[$path]);
302
-
303
-		return true;
304
-	}
305
-
306
-	/**
307
-	 * Bulk load properties for directory children
308
-	 *
309
-	 * @param Directory $node
310
-	 * @param array $requestedProperties requested properties
311
-	 *
312
-	 * @return void
313
-	 */
314
-	private function loadChildrenProperties(Directory $node, $requestedProperties) {
315
-		$path = $node->getPath();
316
-		if (isset($this->cache[$path])) {
317
-			// we already loaded them at some point
318
-			return;
319
-		}
320
-
321
-		$childNodes = $node->getChildren();
322
-		// pre-fill cache
323
-		foreach ($childNodes as $childNode) {
324
-			$this->cache[$childNode->getPath()] = [];
325
-		}
326
-
327
-		$sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` LIKE ?';
328
-		$sql .= ' AND `propertyname` in (?) ORDER BY `propertypath`, `propertyname`';
329
-
330
-		$result = $this->connection->executeQuery(
331
-			$sql,
332
-			array($this->user, $this->connection->escapeLikeParameter(rtrim($path, '/')) . '/%', $requestedProperties),
333
-			array(null, null, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
334
-		);
335
-
336
-		$oldPath = null;
337
-		$props = [];
338
-		while ($row = $result->fetch()) {
339
-			$path = $row['propertypath'];
340
-			if ($oldPath !== $path) {
341
-				// save previously gathered props
342
-				$this->cache[$oldPath] = $props;
343
-				$oldPath = $path;
344
-				// prepare props for next path
345
-				$props = [];
346
-			}
347
-			$props[$row['propertyname']] = $row['propertyvalue'];
348
-		}
349
-		if (!is_null($oldPath)) {
350
-			// save props from last run
351
-			$this->cache[$oldPath] = $props;
352
-		}
353
-
354
-		$result->closeCursor();
355
-	}
39
+    /**
40
+     * Ignored properties
41
+     *
42
+     * @var array
43
+     */
44
+    private $ignoredProperties = array(
45
+        '{DAV:}getcontentlength',
46
+        '{DAV:}getcontenttype',
47
+        '{DAV:}getetag',
48
+        '{DAV:}quota-used-bytes',
49
+        '{DAV:}quota-available-bytes',
50
+        '{DAV:}quota-available-bytes',
51
+        '{http://owncloud.org/ns}permissions',
52
+        '{http://owncloud.org/ns}downloadURL',
53
+        '{http://owncloud.org/ns}dDC',
54
+        '{http://owncloud.org/ns}size',
55
+    );
56
+
57
+    /**
58
+     * @var Tree
59
+     */
60
+    private $tree;
61
+
62
+    /**
63
+     * @var IDBConnection
64
+     */
65
+    private $connection;
66
+
67
+    /**
68
+     * @var IUser
69
+     */
70
+    private $user;
71
+
72
+    /**
73
+     * Properties cache
74
+     *
75
+     * @var array
76
+     */
77
+    private $cache = [];
78
+
79
+    /**
80
+     * @param Tree $tree node tree
81
+     * @param IDBConnection $connection database connection
82
+     * @param IUser $user owner of the tree and properties
83
+     */
84
+    public function __construct(
85
+        Tree $tree,
86
+        IDBConnection $connection,
87
+        IUser $user) {
88
+        $this->tree = $tree;
89
+        $this->connection = $connection;
90
+        $this->user = $user->getUID();
91
+    }
92
+
93
+    /**
94
+     * Fetches properties for a path.
95
+     *
96
+     * @param string $path
97
+     * @param PropFind $propFind
98
+     * @return void
99
+     */
100
+    public function propFind($path, PropFind $propFind) {
101
+        try {
102
+            $node = $this->tree->getNodeForPath($path);
103
+            if (!($node instanceof Node)) {
104
+                return;
105
+            }
106
+        } catch (ServiceUnavailable $e) {
107
+            // might happen for unavailable mount points, skip
108
+            return;
109
+        } catch (NotFound $e) {
110
+            // in some rare (buggy) cases the node might not be found,
111
+            // we catch the exception to prevent breaking the whole list with a 404
112
+            // (soft fail)
113
+            \OC::$server->getLogger()->warning(
114
+                'Could not get node for path: \"' . $path . '\" : ' . $e->getMessage(),
115
+                array('app' => 'files')
116
+            );
117
+            return;
118
+        }
119
+
120
+        $requestedProps = $propFind->get404Properties();
121
+
122
+        // these might appear
123
+        $requestedProps = array_diff(
124
+            $requestedProps,
125
+            $this->ignoredProperties
126
+        );
127
+
128
+        if (empty($requestedProps)) {
129
+            return;
130
+        }
131
+
132
+        if ($node instanceof Directory
133
+            && $propFind->getDepth() !== 0
134
+        ) {
135
+            // note: pre-fetching only supported for depth <= 1
136
+            $this->loadChildrenProperties($node, $requestedProps);
137
+        }
138
+
139
+        $props = $this->getProperties($node, $requestedProps);
140
+        foreach ($props as $propName => $propValue) {
141
+            $propFind->set($propName, $propValue);
142
+        }
143
+    }
144
+
145
+    /**
146
+     * Updates properties for a path
147
+     *
148
+     * @param string $path
149
+     * @param PropPatch $propPatch
150
+     *
151
+     * @return void
152
+     */
153
+    public function propPatch($path, PropPatch $propPatch) {
154
+        $node = $this->tree->getNodeForPath($path);
155
+        if (!($node instanceof Node)) {
156
+            return;
157
+        }
158
+
159
+        $propPatch->handleRemaining(function($changedProps) use ($node) {
160
+            return $this->updateProperties($node, $changedProps);
161
+        });
162
+    }
163
+
164
+    /**
165
+     * This method is called after a node is deleted.
166
+     *
167
+     * @param string $path path of node for which to delete properties
168
+     */
169
+    public function delete($path) {
170
+        $statement = $this->connection->prepare(
171
+            'DELETE FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?'
172
+        );
173
+        $statement->execute(array($this->user, '/' . $path));
174
+        $statement->closeCursor();
175
+
176
+        unset($this->cache[$path]);
177
+    }
178
+
179
+    /**
180
+     * This method is called after a successful MOVE
181
+     *
182
+     * @param string $source
183
+     * @param string $destination
184
+     *
185
+     * @return void
186
+     */
187
+    public function move($source, $destination) {
188
+        $statement = $this->connection->prepare(
189
+            'UPDATE `*PREFIX*properties` SET `propertypath` = ?' .
190
+            ' WHERE `userid` = ? AND `propertypath` = ?'
191
+        );
192
+        $statement->execute(array('/' . $destination, $this->user, '/' . $source));
193
+        $statement->closeCursor();
194
+    }
195
+
196
+    /**
197
+     * Returns a list of properties for this nodes.;
198
+     * @param Node $node
199
+     * @param array $requestedProperties requested properties or empty array for "all"
200
+     * @return array
201
+     * @note The properties list is a list of propertynames the client
202
+     * requested, encoded as xmlnamespace#tagName, for example:
203
+     * http://www.example.org/namespace#author If the array is empty, all
204
+     * properties should be returned
205
+     */
206
+    private function getProperties(Node $node, array $requestedProperties) {
207
+        $path = $node->getPath();
208
+        if (isset($this->cache[$path])) {
209
+            return $this->cache[$path];
210
+        }
211
+
212
+        // TODO: chunking if more than 1000 properties
213
+        $sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?';
214
+
215
+        $whereValues = array($this->user, $path);
216
+        $whereTypes = array(null, null);
217
+
218
+        if (!empty($requestedProperties)) {
219
+            // request only a subset
220
+            $sql .= ' AND `propertyname` in (?)';
221
+            $whereValues[] = $requestedProperties;
222
+            $whereTypes[] = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY;
223
+        }
224
+
225
+        $result = $this->connection->executeQuery(
226
+            $sql,
227
+            $whereValues,
228
+            $whereTypes
229
+        );
230
+
231
+        $props = [];
232
+        while ($row = $result->fetch()) {
233
+            $props[$row['propertyname']] = $row['propertyvalue'];
234
+        }
235
+
236
+        $result->closeCursor();
237
+
238
+        $this->cache[$path] = $props;
239
+        return $props;
240
+    }
241
+
242
+    /**
243
+     * Update properties
244
+     *
245
+     * @param Node $node node for which to update properties
246
+     * @param array $properties array of properties to update
247
+     *
248
+     * @return bool
249
+     */
250
+    private function updateProperties($node, $properties) {
251
+        $path = $node->getPath();
252
+
253
+        $deleteStatement = 'DELETE FROM `*PREFIX*properties`' .
254
+            ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
255
+
256
+        $insertStatement = 'INSERT INTO `*PREFIX*properties`' .
257
+            ' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)';
258
+
259
+        $updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?' .
260
+            ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
261
+
262
+        // TODO: use "insert or update" strategy ?
263
+        $existing = $this->getProperties($node, array());
264
+        $this->connection->beginTransaction();
265
+        foreach ($properties as $propertyName => $propertyValue) {
266
+            // If it was null, we need to delete the property
267
+            if (is_null($propertyValue)) {
268
+                if (array_key_exists($propertyName, $existing)) {
269
+                    $this->connection->executeUpdate($deleteStatement,
270
+                        array(
271
+                            $this->user,
272
+                            $path,
273
+                            $propertyName
274
+                        )
275
+                    );
276
+                }
277
+            } else {
278
+                if (!array_key_exists($propertyName, $existing)) {
279
+                    $this->connection->executeUpdate($insertStatement,
280
+                        array(
281
+                            $this->user,
282
+                            $path,
283
+                            $propertyName,
284
+                            $propertyValue
285
+                        )
286
+                    );
287
+                } else {
288
+                    $this->connection->executeUpdate($updateStatement,
289
+                        array(
290
+                            $propertyValue,
291
+                            $this->user,
292
+                            $path,
293
+                            $propertyName
294
+                        )
295
+                    );
296
+                }
297
+            }
298
+        }
299
+
300
+        $this->connection->commit();
301
+        unset($this->cache[$path]);
302
+
303
+        return true;
304
+    }
305
+
306
+    /**
307
+     * Bulk load properties for directory children
308
+     *
309
+     * @param Directory $node
310
+     * @param array $requestedProperties requested properties
311
+     *
312
+     * @return void
313
+     */
314
+    private function loadChildrenProperties(Directory $node, $requestedProperties) {
315
+        $path = $node->getPath();
316
+        if (isset($this->cache[$path])) {
317
+            // we already loaded them at some point
318
+            return;
319
+        }
320
+
321
+        $childNodes = $node->getChildren();
322
+        // pre-fill cache
323
+        foreach ($childNodes as $childNode) {
324
+            $this->cache[$childNode->getPath()] = [];
325
+        }
326
+
327
+        $sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` LIKE ?';
328
+        $sql .= ' AND `propertyname` in (?) ORDER BY `propertypath`, `propertyname`';
329
+
330
+        $result = $this->connection->executeQuery(
331
+            $sql,
332
+            array($this->user, $this->connection->escapeLikeParameter(rtrim($path, '/')) . '/%', $requestedProperties),
333
+            array(null, null, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
334
+        );
335
+
336
+        $oldPath = null;
337
+        $props = [];
338
+        while ($row = $result->fetch()) {
339
+            $path = $row['propertypath'];
340
+            if ($oldPath !== $path) {
341
+                // save previously gathered props
342
+                $this->cache[$oldPath] = $props;
343
+                $oldPath = $path;
344
+                // prepare props for next path
345
+                $props = [];
346
+            }
347
+            $props[$row['propertyname']] = $row['propertyvalue'];
348
+        }
349
+        if (!is_null($oldPath)) {
350
+            // save props from last run
351
+            $this->cache[$oldPath] = $props;
352
+        }
353
+
354
+        $result->closeCursor();
355
+    }
356 356
 
357 357
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -111,7 +111,7 @@  discard block
 block discarded – undo
111 111
 			// we catch the exception to prevent breaking the whole list with a 404
112 112
 			// (soft fail)
113 113
 			\OC::$server->getLogger()->warning(
114
-				'Could not get node for path: \"' . $path . '\" : ' . $e->getMessage(),
114
+				'Could not get node for path: \"'.$path.'\" : '.$e->getMessage(),
115 115
 				array('app' => 'files')
116 116
 			);
117 117
 			return;
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
 		$statement = $this->connection->prepare(
171 171
 			'DELETE FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?'
172 172
 		);
173
-		$statement->execute(array($this->user, '/' . $path));
173
+		$statement->execute(array($this->user, '/'.$path));
174 174
 		$statement->closeCursor();
175 175
 
176 176
 		unset($this->cache[$path]);
@@ -186,10 +186,10 @@  discard block
 block discarded – undo
186 186
 	 */
187 187
 	public function move($source, $destination) {
188 188
 		$statement = $this->connection->prepare(
189
-			'UPDATE `*PREFIX*properties` SET `propertypath` = ?' .
189
+			'UPDATE `*PREFIX*properties` SET `propertypath` = ?'.
190 190
 			' WHERE `userid` = ? AND `propertypath` = ?'
191 191
 		);
192
-		$statement->execute(array('/' . $destination, $this->user, '/' . $source));
192
+		$statement->execute(array('/'.$destination, $this->user, '/'.$source));
193 193
 		$statement->closeCursor();
194 194
 	}
195 195
 
@@ -250,13 +250,13 @@  discard block
 block discarded – undo
250 250
 	private function updateProperties($node, $properties) {
251 251
 		$path = $node->getPath();
252 252
 
253
-		$deleteStatement = 'DELETE FROM `*PREFIX*properties`' .
253
+		$deleteStatement = 'DELETE FROM `*PREFIX*properties`'.
254 254
 			' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
255 255
 
256
-		$insertStatement = 'INSERT INTO `*PREFIX*properties`' .
256
+		$insertStatement = 'INSERT INTO `*PREFIX*properties`'.
257 257
 			' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)';
258 258
 
259
-		$updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?' .
259
+		$updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?'.
260 260
 			' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
261 261
 
262 262
 		// TODO: use "insert or update" strategy ?
@@ -329,7 +329,7 @@  discard block
 block discarded – undo
329 329
 
330 330
 		$result = $this->connection->executeQuery(
331 331
 			$sql,
332
-			array($this->user, $this->connection->escapeLikeParameter(rtrim($path, '/')) . '/%', $requestedProperties),
332
+			array($this->user, $this->connection->escapeLikeParameter(rtrim($path, '/')).'/%', $requestedProperties),
333 333
 			array(null, null, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
334 334
 		);
335 335
 
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/File.php 3 patches
Doc Comments   +3 added lines patch added patch discarded remove patch
@@ -232,6 +232,9 @@
 block discarded – undo
232 232
 		return '"' . $this->info->getEtag() . '"';
233 233
 	}
234 234
 
235
+	/**
236
+	 * @param string $path
237
+	 */
235 238
 	private function getPartFileBasePath($path) {
236 239
 		$partFileInStorage = \OC::$server->getConfig()->getSystemValue('part_file_in_storage', true);
237 240
 		if ($partFileInStorage) {
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -92,7 +92,7 @@  discard block
 block discarded – undo
92 92
 				throw new Forbidden();
93 93
 			}
94 94
 		} catch (StorageNotAvailableException $e) {
95
-			throw new ServiceUnavailable("File is not updatable: " . $e->getMessage());
95
+			throw new ServiceUnavailable("File is not updatable: ".$e->getMessage());
96 96
 		}
97 97
 
98 98
 		// verify path of the target
@@ -112,7 +112,7 @@  discard block
 block discarded – undo
112 112
 
113 113
 		if ($needsPartFile) {
114 114
 			// mark file as partial while uploading (ignored by the scanner)
115
-			$partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
115
+			$partFilePath = $this->getPartFileBasePath($this->path).'.ocTransferId'.rand().'.part';
116 116
 		} else {
117 117
 			// upload file directly as the final path
118 118
 			$partFilePath = $this->path;
@@ -138,7 +138,7 @@  discard block
 block discarded – undo
138 138
 				if (isset($_SERVER['CONTENT_LENGTH'])) {
139 139
 					$expected = $_SERVER['CONTENT_LENGTH'];
140 140
 				}
141
-				throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: ' . $expected . ' )');
141
+				throw new Exception('Error while copying file to target location (copied bytes: '.$count.', expected filesize: '.$expected.' )');
142 142
 			}
143 143
 
144 144
 			// if content length is sent by client:
@@ -147,7 +147,7 @@  discard block
 block discarded – undo
147 147
 			if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
148 148
 				$expected = $_SERVER['CONTENT_LENGTH'];
149 149
 				if ($count != $expected) {
150
-					throw new BadRequest('expected filesize ' . $expected . ' got ' . $count);
150
+					throw new BadRequest('expected filesize '.$expected.' got '.$count);
151 151
 				}
152 152
 			}
153 153
 
@@ -227,10 +227,10 @@  discard block
 block discarded – undo
227 227
 			}
228 228
 
229 229
 		} catch (StorageNotAvailableException $e) {
230
-			throw new ServiceUnavailable("Failed to check file size: " . $e->getMessage());
230
+			throw new ServiceUnavailable("Failed to check file size: ".$e->getMessage());
231 231
 		}
232 232
 
233
-		return '"' . $this->info->getEtag() . '"';
233
+		return '"'.$this->info->getEtag().'"';
234 234
 	}
235 235
 
236 236
 	private function getPartFileBasePath($path) {
@@ -309,9 +309,9 @@  discard block
 block discarded – undo
309 309
 			return $res;
310 310
 		} catch (GenericEncryptionException $e) {
311 311
 			// returning 503 will allow retry of the operation at a later point in time
312
-			throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
312
+			throw new ServiceUnavailable("Encryption not ready: ".$e->getMessage());
313 313
 		} catch (StorageNotAvailableException $e) {
314
-			throw new ServiceUnavailable("Failed to open file: " . $e->getMessage());
314
+			throw new ServiceUnavailable("Failed to open file: ".$e->getMessage());
315 315
 		} catch (ForbiddenException $ex) {
316 316
 			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
317 317
 		} catch (LockedException $e) {
@@ -336,7 +336,7 @@  discard block
 block discarded – undo
336 336
 				throw new Forbidden();
337 337
 			}
338 338
 		} catch (StorageNotAvailableException $e) {
339
-			throw new ServiceUnavailable("Failed to unlink: " . $e->getMessage());
339
+			throw new ServiceUnavailable("Failed to unlink: ".$e->getMessage());
340 340
 		} catch (ForbiddenException $ex) {
341 341
 			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
342 342
 		} catch (LockedException $e) {
@@ -403,7 +403,7 @@  discard block
 block discarded – undo
403 403
 				if ($bytesWritten != $expected) {
404 404
 					$chunk_handler->remove($info['index']);
405 405
 					throw new BadRequest(
406
-						'expected filesize ' . $expected . ' got ' . $bytesWritten);
406
+						'expected filesize '.$expected.' got '.$bytesWritten);
407 407
 				}
408 408
 			}
409 409
 		}
@@ -413,7 +413,7 @@  discard block
 block discarded – undo
413 413
 			$needsPartFile = $this->needsPartFile($storage);
414 414
 			$partFile = null;
415 415
 
416
-			$targetPath = $path . '/' . $info['name'];
416
+			$targetPath = $path.'/'.$info['name'];
417 417
 			/** @var \OC\Files\Storage\Storage $targetStorage */
418 418
 			list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
419 419
 
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
 
430 430
 				if ($needsPartFile) {
431 431
 					// we first assembly the target file as a part file
432
-					$partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
432
+					$partFile = $this->getPartFileBasePath($path.'/'.$info['name']).'.ocTransferId'.$info['transferid'].'.part';
433 433
 					/** @var \OC\Files\Storage\Storage $targetStorage */
434 434
 					list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile);
435 435
 
@@ -548,10 +548,10 @@  discard block
 block discarded – undo
548 548
 		}
549 549
 		if ($e instanceof GenericEncryptionException) {
550 550
 			// returning 503 will allow retry of the operation at a later point in time
551
-			throw new ServiceUnavailable('Encryption not ready: ' . $e->getMessage(), 0, $e);
551
+			throw new ServiceUnavailable('Encryption not ready: '.$e->getMessage(), 0, $e);
552 552
 		}
553 553
 		if ($e instanceof StorageNotAvailableException) {
554
-			throw new ServiceUnavailable('Failed to write file contents: ' . $e->getMessage(), 0, $e);
554
+			throw new ServiceUnavailable('Failed to write file contents: '.$e->getMessage(), 0, $e);
555 555
 		}
556 556
 
557 557
 		throw new \Sabre\DAV\Exception($e->getMessage(), 0, $e);
Please login to merge, or discard this patch.
Indentation   +508 added lines, -508 removed lines patch added patch discarded remove patch
@@ -57,512 +57,512 @@
 block discarded – undo
57 57
 
58 58
 class File extends Node implements IFile {
59 59
 
60
-	/**
61
-	 * Updates the data
62
-	 *
63
-	 * The data argument is a readable stream resource.
64
-	 *
65
-	 * After a successful put operation, you may choose to return an ETag. The
66
-	 * etag must always be surrounded by double-quotes. These quotes must
67
-	 * appear in the actual string you're returning.
68
-	 *
69
-	 * Clients may use the ETag from a PUT request to later on make sure that
70
-	 * when they update the file, the contents haven't changed in the mean
71
-	 * time.
72
-	 *
73
-	 * If you don't plan to store the file byte-by-byte, and you return a
74
-	 * different object on a subsequent GET you are strongly recommended to not
75
-	 * return an ETag, and just return null.
76
-	 *
77
-	 * @param resource $data
78
-	 *
79
-	 * @throws Forbidden
80
-	 * @throws UnsupportedMediaType
81
-	 * @throws BadRequest
82
-	 * @throws Exception
83
-	 * @throws EntityTooLarge
84
-	 * @throws ServiceUnavailable
85
-	 * @throws FileLocked
86
-	 * @return string|null
87
-	 */
88
-	public function put($data) {
89
-		try {
90
-			$exists = $this->fileView->file_exists($this->path);
91
-			if ($this->info && $exists && !$this->info->isUpdateable()) {
92
-				throw new Forbidden();
93
-			}
94
-		} catch (StorageNotAvailableException $e) {
95
-			throw new ServiceUnavailable("File is not updatable: " . $e->getMessage());
96
-		}
97
-
98
-		// verify path of the target
99
-		$this->verifyPath();
100
-
101
-		// chunked handling
102
-		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
103
-			try {
104
-				return $this->createFileChunked($data);
105
-			} catch (\Exception $e) {
106
-				$this->convertToSabreException($e);
107
-			}
108
-		}
109
-
110
-		list($partStorage) = $this->fileView->resolvePath($this->path);
111
-		$needsPartFile = $this->needsPartFile($partStorage) && (strlen($this->path) > 1);
112
-
113
-		if ($needsPartFile) {
114
-			// mark file as partial while uploading (ignored by the scanner)
115
-			$partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
116
-		} else {
117
-			// upload file directly as the final path
118
-			$partFilePath = $this->path;
119
-		}
120
-
121
-		// the part file and target file might be on a different storage in case of a single file storage (e.g. single file share)
122
-		/** @var \OC\Files\Storage\Storage $partStorage */
123
-		list($partStorage, $internalPartPath) = $this->fileView->resolvePath($partFilePath);
124
-		/** @var \OC\Files\Storage\Storage $storage */
125
-		list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
126
-		try {
127
-			$target = $partStorage->fopen($internalPartPath, 'wb');
128
-			if ($target === false) {
129
-				\OCP\Util::writeLog('webdav', '\OC\Files\Filesystem::fopen() failed', \OCP\Util::ERROR);
130
-				// because we have no clue about the cause we can only throw back a 500/Internal Server Error
131
-				throw new Exception('Could not write file contents');
132
-			}
133
-			list($count, $result) = \OC_Helper::streamCopy($data, $target);
134
-			fclose($target);
135
-
136
-			if ($result === false) {
137
-				$expected = -1;
138
-				if (isset($_SERVER['CONTENT_LENGTH'])) {
139
-					$expected = $_SERVER['CONTENT_LENGTH'];
140
-				}
141
-				throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: ' . $expected . ' )');
142
-			}
143
-
144
-			// if content length is sent by client:
145
-			// double check if the file was fully received
146
-			// compare expected and actual size
147
-			if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
148
-				$expected = $_SERVER['CONTENT_LENGTH'];
149
-				if ($count != $expected) {
150
-					throw new BadRequest('expected filesize ' . $expected . ' got ' . $count);
151
-				}
152
-			}
153
-
154
-		} catch (\Exception $e) {
155
-			if ($needsPartFile) {
156
-				$partStorage->unlink($internalPartPath);
157
-			}
158
-			$this->convertToSabreException($e);
159
-		}
160
-
161
-		try {
162
-			$view = \OC\Files\Filesystem::getView();
163
-			if ($view) {
164
-				$run = $this->emitPreHooks($exists);
165
-			} else {
166
-				$run = true;
167
-			}
168
-
169
-			try {
170
-				$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
171
-			} catch (LockedException $e) {
172
-				if ($needsPartFile) {
173
-					$partStorage->unlink($internalPartPath);
174
-				}
175
-				throw new FileLocked($e->getMessage(), $e->getCode(), $e);
176
-			}
177
-
178
-			if ($needsPartFile) {
179
-				// rename to correct path
180
-				try {
181
-					if ($run) {
182
-						$renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
183
-						$fileExists = $storage->file_exists($internalPath);
184
-					}
185
-					if (!$run || $renameOkay === false || $fileExists === false) {
186
-						\OCP\Util::writeLog('webdav', 'renaming part file to final file failed', \OCP\Util::ERROR);
187
-						throw new Exception('Could not rename part file to final file');
188
-					}
189
-				} catch (ForbiddenException $ex) {
190
-					throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
191
-				} catch (\Exception $e) {
192
-					$partStorage->unlink($internalPartPath);
193
-					$this->convertToSabreException($e);
194
-				}
195
-			}
196
-
197
-			// since we skipped the view we need to scan and emit the hooks ourselves
198
-			$storage->getUpdater()->update($internalPath);
199
-
200
-			try {
201
-				$this->changeLock(ILockingProvider::LOCK_SHARED);
202
-			} catch (LockedException $e) {
203
-				throw new FileLocked($e->getMessage(), $e->getCode(), $e);
204
-			}
205
-
206
-			if ($view) {
207
-				$this->emitPostHooks($exists);
208
-			}
209
-
210
-			// allow sync clients to send the mtime along in a header
211
-			$request = \OC::$server->getRequest();
212
-			if (isset($request->server['HTTP_X_OC_MTIME'])) {
213
-				if ($this->fileView->touch($this->path, $request->server['HTTP_X_OC_MTIME'])) {
214
-					header('X-OC-MTime: accepted');
215
-				}
216
-			}
217
-
218
-			$this->refreshInfo();
219
-
220
-			if (isset($request->server['HTTP_OC_CHECKSUM'])) {
221
-				$checksum = trim($request->server['HTTP_OC_CHECKSUM']);
222
-				$this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
223
-				$this->refreshInfo();
224
-			} else if ($this->getChecksum() !== null && $this->getChecksum() !== '') {
225
-				$this->fileView->putFileInfo($this->path, ['checksum' => '']);
226
-				$this->refreshInfo();
227
-			}
228
-
229
-		} catch (StorageNotAvailableException $e) {
230
-			throw new ServiceUnavailable("Failed to check file size: " . $e->getMessage());
231
-		}
232
-
233
-		return '"' . $this->info->getEtag() . '"';
234
-	}
235
-
236
-	private function getPartFileBasePath($path) {
237
-		$partFileInStorage = \OC::$server->getConfig()->getSystemValue('part_file_in_storage', true);
238
-		if ($partFileInStorage) {
239
-			return $path;
240
-		} else {
241
-			return md5($path); // will place it in the root of the view with a unique name
242
-		}
243
-	}
244
-
245
-	/**
246
-	 * @param string $path
247
-	 */
248
-	private function emitPreHooks($exists, $path = null) {
249
-		if (is_null($path)) {
250
-			$path = $this->path;
251
-		}
252
-		$hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
253
-		$run = true;
254
-
255
-		if (!$exists) {
256
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_create, array(
257
-				\OC\Files\Filesystem::signal_param_path => $hookPath,
258
-				\OC\Files\Filesystem::signal_param_run => &$run,
259
-			));
260
-		} else {
261
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_update, array(
262
-				\OC\Files\Filesystem::signal_param_path => $hookPath,
263
-				\OC\Files\Filesystem::signal_param_run => &$run,
264
-			));
265
-		}
266
-		\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_write, array(
267
-			\OC\Files\Filesystem::signal_param_path => $hookPath,
268
-			\OC\Files\Filesystem::signal_param_run => &$run,
269
-		));
270
-		return $run;
271
-	}
272
-
273
-	/**
274
-	 * @param string $path
275
-	 */
276
-	private function emitPostHooks($exists, $path = null) {
277
-		if (is_null($path)) {
278
-			$path = $this->path;
279
-		}
280
-		$hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
281
-		if (!$exists) {
282
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_create, array(
283
-				\OC\Files\Filesystem::signal_param_path => $hookPath
284
-			));
285
-		} else {
286
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_update, array(
287
-				\OC\Files\Filesystem::signal_param_path => $hookPath
288
-			));
289
-		}
290
-		\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_write, array(
291
-			\OC\Files\Filesystem::signal_param_path => $hookPath
292
-		));
293
-	}
294
-
295
-	/**
296
-	 * Returns the data
297
-	 *
298
-	 * @return resource
299
-	 * @throws Forbidden
300
-	 * @throws ServiceUnavailable
301
-	 */
302
-	public function get() {
303
-		//throw exception if encryption is disabled but files are still encrypted
304
-		try {
305
-			$res = $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
306
-			if ($res === false) {
307
-				throw new ServiceUnavailable("Could not open file");
308
-			}
309
-			return $res;
310
-		} catch (GenericEncryptionException $e) {
311
-			// returning 503 will allow retry of the operation at a later point in time
312
-			throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
313
-		} catch (StorageNotAvailableException $e) {
314
-			throw new ServiceUnavailable("Failed to open file: " . $e->getMessage());
315
-		} catch (ForbiddenException $ex) {
316
-			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
317
-		} catch (LockedException $e) {
318
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
319
-		}
320
-	}
321
-
322
-	/**
323
-	 * Delete the current file
324
-	 *
325
-	 * @throws Forbidden
326
-	 * @throws ServiceUnavailable
327
-	 */
328
-	public function delete() {
329
-		if (!$this->info->isDeletable()) {
330
-			throw new Forbidden();
331
-		}
332
-
333
-		try {
334
-			if (!$this->fileView->unlink($this->path)) {
335
-				// assume it wasn't possible to delete due to permissions
336
-				throw new Forbidden();
337
-			}
338
-		} catch (StorageNotAvailableException $e) {
339
-			throw new ServiceUnavailable("Failed to unlink: " . $e->getMessage());
340
-		} catch (ForbiddenException $ex) {
341
-			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
342
-		} catch (LockedException $e) {
343
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
344
-		}
345
-	}
346
-
347
-	/**
348
-	 * Returns the mime-type for a file
349
-	 *
350
-	 * If null is returned, we'll assume application/octet-stream
351
-	 *
352
-	 * @return string
353
-	 */
354
-	public function getContentType() {
355
-		$mimeType = $this->info->getMimetype();
356
-
357
-		// PROPFIND needs to return the correct mime type, for consistency with the web UI
358
-		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
359
-			return $mimeType;
360
-		}
361
-		return \OC::$server->getMimeTypeDetector()->getSecureMimeType($mimeType);
362
-	}
363
-
364
-	/**
365
-	 * @return array|false
366
-	 */
367
-	public function getDirectDownload() {
368
-		if (\OCP\App::isEnabled('encryption')) {
369
-			return [];
370
-		}
371
-		/** @var \OCP\Files\Storage $storage */
372
-		list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
373
-		if (is_null($storage)) {
374
-			return [];
375
-		}
376
-
377
-		return $storage->getDirectDownload($internalPath);
378
-	}
379
-
380
-	/**
381
-	 * @param resource $data
382
-	 * @return null|string
383
-	 * @throws Exception
384
-	 * @throws BadRequest
385
-	 * @throws NotImplemented
386
-	 * @throws ServiceUnavailable
387
-	 */
388
-	private function createFileChunked($data) {
389
-		list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($this->path);
390
-
391
-		$info = \OC_FileChunking::decodeName($name);
392
-		if (empty($info)) {
393
-			throw new NotImplemented('Invalid chunk name');
394
-		}
395
-
396
-		$chunk_handler = new \OC_FileChunking($info);
397
-		$bytesWritten = $chunk_handler->store($info['index'], $data);
398
-
399
-		//detect aborted upload
400
-		if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
401
-			if (isset($_SERVER['CONTENT_LENGTH'])) {
402
-				$expected = $_SERVER['CONTENT_LENGTH'];
403
-				if ($bytesWritten != $expected) {
404
-					$chunk_handler->remove($info['index']);
405
-					throw new BadRequest(
406
-						'expected filesize ' . $expected . ' got ' . $bytesWritten);
407
-				}
408
-			}
409
-		}
410
-
411
-		if ($chunk_handler->isComplete()) {
412
-			list($storage,) = $this->fileView->resolvePath($path);
413
-			$needsPartFile = $this->needsPartFile($storage);
414
-			$partFile = null;
415
-
416
-			$targetPath = $path . '/' . $info['name'];
417
-			/** @var \OC\Files\Storage\Storage $targetStorage */
418
-			list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
419
-
420
-			$exists = $this->fileView->file_exists($targetPath);
421
-
422
-			try {
423
-				$this->fileView->lockFile($targetPath, ILockingProvider::LOCK_SHARED);
424
-
425
-				$this->emitPreHooks($exists, $targetPath);
426
-				$this->fileView->changeLock($targetPath, ILockingProvider::LOCK_EXCLUSIVE);
427
-				/** @var \OC\Files\Storage\Storage $targetStorage */
428
-				list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
429
-
430
-				if ($needsPartFile) {
431
-					// we first assembly the target file as a part file
432
-					$partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
433
-					/** @var \OC\Files\Storage\Storage $targetStorage */
434
-					list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile);
435
-
436
-
437
-					$chunk_handler->file_assemble($partStorage, $partInternalPath);
438
-
439
-					// here is the final atomic rename
440
-					$renameOkay = $targetStorage->moveFromStorage($partStorage, $partInternalPath, $targetInternalPath);
441
-					$fileExists = $targetStorage->file_exists($targetInternalPath);
442
-					if ($renameOkay === false || $fileExists === false) {
443
-						\OCP\Util::writeLog('webdav', '\OC\Files\Filesystem::rename() failed', \OCP\Util::ERROR);
444
-						// only delete if an error occurred and the target file was already created
445
-						if ($fileExists) {
446
-							// set to null to avoid double-deletion when handling exception
447
-							// stray part file
448
-							$partFile = null;
449
-							$targetStorage->unlink($targetInternalPath);
450
-						}
451
-						$this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
452
-						throw new Exception('Could not rename part file assembled from chunks');
453
-					}
454
-				} else {
455
-					// assemble directly into the final file
456
-					$chunk_handler->file_assemble($targetStorage, $targetInternalPath);
457
-				}
458
-
459
-				// allow sync clients to send the mtime along in a header
460
-				$request = \OC::$server->getRequest();
461
-				if (isset($request->server['HTTP_X_OC_MTIME'])) {
462
-					if ($targetStorage->touch($targetInternalPath, $request->server['HTTP_X_OC_MTIME'])) {
463
-						header('X-OC-MTime: accepted');
464
-					}
465
-				}
466
-
467
-				// since we skipped the view we need to scan and emit the hooks ourselves
468
-				$targetStorage->getUpdater()->update($targetInternalPath);
469
-
470
-				$this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
471
-
472
-				$this->emitPostHooks($exists, $targetPath);
473
-
474
-				// FIXME: should call refreshInfo but can't because $this->path is not the of the final file
475
-				$info = $this->fileView->getFileInfo($targetPath);
476
-
477
-				if (isset($request->server['HTTP_OC_CHECKSUM'])) {
478
-					$checksum = trim($request->server['HTTP_OC_CHECKSUM']);
479
-					$this->fileView->putFileInfo($targetPath, ['checksum' => $checksum]);
480
-				} else if ($info->getChecksum() !== null && $info->getChecksum() !== '') {
481
-					$this->fileView->putFileInfo($this->path, ['checksum' => '']);
482
-				}
483
-
484
-				$this->fileView->unlockFile($targetPath, ILockingProvider::LOCK_SHARED);
485
-
486
-				return $info->getEtag();
487
-			} catch (\Exception $e) {
488
-				if ($partFile !== null) {
489
-					$targetStorage->unlink($targetInternalPath);
490
-				}
491
-				$this->convertToSabreException($e);
492
-			}
493
-		}
494
-
495
-		return null;
496
-	}
497
-
498
-	/**
499
-	 * Returns whether a part file is needed for the given storage
500
-	 * or whether the file can be assembled/uploaded directly on the
501
-	 * target storage.
502
-	 *
503
-	 * @param \OCP\Files\Storage $storage
504
-	 * @return bool true if the storage needs part file handling
505
-	 */
506
-	private function needsPartFile($storage) {
507
-		// TODO: in the future use ChunkHandler provided by storage
508
-		// and/or add method on Storage called "needsPartFile()"
509
-		return !$storage->instanceOfStorage('OCA\Files_Sharing\External\Storage') &&
510
-		!$storage->instanceOfStorage('OC\Files\Storage\OwnCloud');
511
-	}
512
-
513
-	/**
514
-	 * Convert the given exception to a SabreException instance
515
-	 *
516
-	 * @param \Exception $e
517
-	 *
518
-	 * @throws \Sabre\DAV\Exception
519
-	 */
520
-	private function convertToSabreException(\Exception $e) {
521
-		if ($e instanceof \Sabre\DAV\Exception) {
522
-			throw $e;
523
-		}
524
-		if ($e instanceof NotPermittedException) {
525
-			// a more general case - due to whatever reason the content could not be written
526
-			throw new Forbidden($e->getMessage(), 0, $e);
527
-		}
528
-		if ($e instanceof ForbiddenException) {
529
-			// the path for the file was forbidden
530
-			throw new DAVForbiddenException($e->getMessage(), $e->getRetry(), $e);
531
-		}
532
-		if ($e instanceof EntityTooLargeException) {
533
-			// the file is too big to be stored
534
-			throw new EntityTooLarge($e->getMessage(), 0, $e);
535
-		}
536
-		if ($e instanceof InvalidContentException) {
537
-			// the file content is not permitted
538
-			throw new UnsupportedMediaType($e->getMessage(), 0, $e);
539
-		}
540
-		if ($e instanceof InvalidPathException) {
541
-			// the path for the file was not valid
542
-			// TODO: find proper http status code for this case
543
-			throw new Forbidden($e->getMessage(), 0, $e);
544
-		}
545
-		if ($e instanceof LockedException || $e instanceof LockNotAcquiredException) {
546
-			// the file is currently being written to by another process
547
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
548
-		}
549
-		if ($e instanceof GenericEncryptionException) {
550
-			// returning 503 will allow retry of the operation at a later point in time
551
-			throw new ServiceUnavailable('Encryption not ready: ' . $e->getMessage(), 0, $e);
552
-		}
553
-		if ($e instanceof StorageNotAvailableException) {
554
-			throw new ServiceUnavailable('Failed to write file contents: ' . $e->getMessage(), 0, $e);
555
-		}
556
-
557
-		throw new \Sabre\DAV\Exception($e->getMessage(), 0, $e);
558
-	}
559
-
560
-	/**
561
-	 * Get the checksum for this file
562
-	 *
563
-	 * @return string
564
-	 */
565
-	public function getChecksum() {
566
-		return $this->info->getChecksum();
567
-	}
60
+    /**
61
+     * Updates the data
62
+     *
63
+     * The data argument is a readable stream resource.
64
+     *
65
+     * After a successful put operation, you may choose to return an ETag. The
66
+     * etag must always be surrounded by double-quotes. These quotes must
67
+     * appear in the actual string you're returning.
68
+     *
69
+     * Clients may use the ETag from a PUT request to later on make sure that
70
+     * when they update the file, the contents haven't changed in the mean
71
+     * time.
72
+     *
73
+     * If you don't plan to store the file byte-by-byte, and you return a
74
+     * different object on a subsequent GET you are strongly recommended to not
75
+     * return an ETag, and just return null.
76
+     *
77
+     * @param resource $data
78
+     *
79
+     * @throws Forbidden
80
+     * @throws UnsupportedMediaType
81
+     * @throws BadRequest
82
+     * @throws Exception
83
+     * @throws EntityTooLarge
84
+     * @throws ServiceUnavailable
85
+     * @throws FileLocked
86
+     * @return string|null
87
+     */
88
+    public function put($data) {
89
+        try {
90
+            $exists = $this->fileView->file_exists($this->path);
91
+            if ($this->info && $exists && !$this->info->isUpdateable()) {
92
+                throw new Forbidden();
93
+            }
94
+        } catch (StorageNotAvailableException $e) {
95
+            throw new ServiceUnavailable("File is not updatable: " . $e->getMessage());
96
+        }
97
+
98
+        // verify path of the target
99
+        $this->verifyPath();
100
+
101
+        // chunked handling
102
+        if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
103
+            try {
104
+                return $this->createFileChunked($data);
105
+            } catch (\Exception $e) {
106
+                $this->convertToSabreException($e);
107
+            }
108
+        }
109
+
110
+        list($partStorage) = $this->fileView->resolvePath($this->path);
111
+        $needsPartFile = $this->needsPartFile($partStorage) && (strlen($this->path) > 1);
112
+
113
+        if ($needsPartFile) {
114
+            // mark file as partial while uploading (ignored by the scanner)
115
+            $partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
116
+        } else {
117
+            // upload file directly as the final path
118
+            $partFilePath = $this->path;
119
+        }
120
+
121
+        // the part file and target file might be on a different storage in case of a single file storage (e.g. single file share)
122
+        /** @var \OC\Files\Storage\Storage $partStorage */
123
+        list($partStorage, $internalPartPath) = $this->fileView->resolvePath($partFilePath);
124
+        /** @var \OC\Files\Storage\Storage $storage */
125
+        list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
126
+        try {
127
+            $target = $partStorage->fopen($internalPartPath, 'wb');
128
+            if ($target === false) {
129
+                \OCP\Util::writeLog('webdav', '\OC\Files\Filesystem::fopen() failed', \OCP\Util::ERROR);
130
+                // because we have no clue about the cause we can only throw back a 500/Internal Server Error
131
+                throw new Exception('Could not write file contents');
132
+            }
133
+            list($count, $result) = \OC_Helper::streamCopy($data, $target);
134
+            fclose($target);
135
+
136
+            if ($result === false) {
137
+                $expected = -1;
138
+                if (isset($_SERVER['CONTENT_LENGTH'])) {
139
+                    $expected = $_SERVER['CONTENT_LENGTH'];
140
+                }
141
+                throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: ' . $expected . ' )');
142
+            }
143
+
144
+            // if content length is sent by client:
145
+            // double check if the file was fully received
146
+            // compare expected and actual size
147
+            if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
148
+                $expected = $_SERVER['CONTENT_LENGTH'];
149
+                if ($count != $expected) {
150
+                    throw new BadRequest('expected filesize ' . $expected . ' got ' . $count);
151
+                }
152
+            }
153
+
154
+        } catch (\Exception $e) {
155
+            if ($needsPartFile) {
156
+                $partStorage->unlink($internalPartPath);
157
+            }
158
+            $this->convertToSabreException($e);
159
+        }
160
+
161
+        try {
162
+            $view = \OC\Files\Filesystem::getView();
163
+            if ($view) {
164
+                $run = $this->emitPreHooks($exists);
165
+            } else {
166
+                $run = true;
167
+            }
168
+
169
+            try {
170
+                $this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
171
+            } catch (LockedException $e) {
172
+                if ($needsPartFile) {
173
+                    $partStorage->unlink($internalPartPath);
174
+                }
175
+                throw new FileLocked($e->getMessage(), $e->getCode(), $e);
176
+            }
177
+
178
+            if ($needsPartFile) {
179
+                // rename to correct path
180
+                try {
181
+                    if ($run) {
182
+                        $renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
183
+                        $fileExists = $storage->file_exists($internalPath);
184
+                    }
185
+                    if (!$run || $renameOkay === false || $fileExists === false) {
186
+                        \OCP\Util::writeLog('webdav', 'renaming part file to final file failed', \OCP\Util::ERROR);
187
+                        throw new Exception('Could not rename part file to final file');
188
+                    }
189
+                } catch (ForbiddenException $ex) {
190
+                    throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
191
+                } catch (\Exception $e) {
192
+                    $partStorage->unlink($internalPartPath);
193
+                    $this->convertToSabreException($e);
194
+                }
195
+            }
196
+
197
+            // since we skipped the view we need to scan and emit the hooks ourselves
198
+            $storage->getUpdater()->update($internalPath);
199
+
200
+            try {
201
+                $this->changeLock(ILockingProvider::LOCK_SHARED);
202
+            } catch (LockedException $e) {
203
+                throw new FileLocked($e->getMessage(), $e->getCode(), $e);
204
+            }
205
+
206
+            if ($view) {
207
+                $this->emitPostHooks($exists);
208
+            }
209
+
210
+            // allow sync clients to send the mtime along in a header
211
+            $request = \OC::$server->getRequest();
212
+            if (isset($request->server['HTTP_X_OC_MTIME'])) {
213
+                if ($this->fileView->touch($this->path, $request->server['HTTP_X_OC_MTIME'])) {
214
+                    header('X-OC-MTime: accepted');
215
+                }
216
+            }
217
+
218
+            $this->refreshInfo();
219
+
220
+            if (isset($request->server['HTTP_OC_CHECKSUM'])) {
221
+                $checksum = trim($request->server['HTTP_OC_CHECKSUM']);
222
+                $this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
223
+                $this->refreshInfo();
224
+            } else if ($this->getChecksum() !== null && $this->getChecksum() !== '') {
225
+                $this->fileView->putFileInfo($this->path, ['checksum' => '']);
226
+                $this->refreshInfo();
227
+            }
228
+
229
+        } catch (StorageNotAvailableException $e) {
230
+            throw new ServiceUnavailable("Failed to check file size: " . $e->getMessage());
231
+        }
232
+
233
+        return '"' . $this->info->getEtag() . '"';
234
+    }
235
+
236
+    private function getPartFileBasePath($path) {
237
+        $partFileInStorage = \OC::$server->getConfig()->getSystemValue('part_file_in_storage', true);
238
+        if ($partFileInStorage) {
239
+            return $path;
240
+        } else {
241
+            return md5($path); // will place it in the root of the view with a unique name
242
+        }
243
+    }
244
+
245
+    /**
246
+     * @param string $path
247
+     */
248
+    private function emitPreHooks($exists, $path = null) {
249
+        if (is_null($path)) {
250
+            $path = $this->path;
251
+        }
252
+        $hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
253
+        $run = true;
254
+
255
+        if (!$exists) {
256
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_create, array(
257
+                \OC\Files\Filesystem::signal_param_path => $hookPath,
258
+                \OC\Files\Filesystem::signal_param_run => &$run,
259
+            ));
260
+        } else {
261
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_update, array(
262
+                \OC\Files\Filesystem::signal_param_path => $hookPath,
263
+                \OC\Files\Filesystem::signal_param_run => &$run,
264
+            ));
265
+        }
266
+        \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_write, array(
267
+            \OC\Files\Filesystem::signal_param_path => $hookPath,
268
+            \OC\Files\Filesystem::signal_param_run => &$run,
269
+        ));
270
+        return $run;
271
+    }
272
+
273
+    /**
274
+     * @param string $path
275
+     */
276
+    private function emitPostHooks($exists, $path = null) {
277
+        if (is_null($path)) {
278
+            $path = $this->path;
279
+        }
280
+        $hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
281
+        if (!$exists) {
282
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_create, array(
283
+                \OC\Files\Filesystem::signal_param_path => $hookPath
284
+            ));
285
+        } else {
286
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_update, array(
287
+                \OC\Files\Filesystem::signal_param_path => $hookPath
288
+            ));
289
+        }
290
+        \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_write, array(
291
+            \OC\Files\Filesystem::signal_param_path => $hookPath
292
+        ));
293
+    }
294
+
295
+    /**
296
+     * Returns the data
297
+     *
298
+     * @return resource
299
+     * @throws Forbidden
300
+     * @throws ServiceUnavailable
301
+     */
302
+    public function get() {
303
+        //throw exception if encryption is disabled but files are still encrypted
304
+        try {
305
+            $res = $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
306
+            if ($res === false) {
307
+                throw new ServiceUnavailable("Could not open file");
308
+            }
309
+            return $res;
310
+        } catch (GenericEncryptionException $e) {
311
+            // returning 503 will allow retry of the operation at a later point in time
312
+            throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
313
+        } catch (StorageNotAvailableException $e) {
314
+            throw new ServiceUnavailable("Failed to open file: " . $e->getMessage());
315
+        } catch (ForbiddenException $ex) {
316
+            throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
317
+        } catch (LockedException $e) {
318
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
319
+        }
320
+    }
321
+
322
+    /**
323
+     * Delete the current file
324
+     *
325
+     * @throws Forbidden
326
+     * @throws ServiceUnavailable
327
+     */
328
+    public function delete() {
329
+        if (!$this->info->isDeletable()) {
330
+            throw new Forbidden();
331
+        }
332
+
333
+        try {
334
+            if (!$this->fileView->unlink($this->path)) {
335
+                // assume it wasn't possible to delete due to permissions
336
+                throw new Forbidden();
337
+            }
338
+        } catch (StorageNotAvailableException $e) {
339
+            throw new ServiceUnavailable("Failed to unlink: " . $e->getMessage());
340
+        } catch (ForbiddenException $ex) {
341
+            throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
342
+        } catch (LockedException $e) {
343
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
344
+        }
345
+    }
346
+
347
+    /**
348
+     * Returns the mime-type for a file
349
+     *
350
+     * If null is returned, we'll assume application/octet-stream
351
+     *
352
+     * @return string
353
+     */
354
+    public function getContentType() {
355
+        $mimeType = $this->info->getMimetype();
356
+
357
+        // PROPFIND needs to return the correct mime type, for consistency with the web UI
358
+        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
359
+            return $mimeType;
360
+        }
361
+        return \OC::$server->getMimeTypeDetector()->getSecureMimeType($mimeType);
362
+    }
363
+
364
+    /**
365
+     * @return array|false
366
+     */
367
+    public function getDirectDownload() {
368
+        if (\OCP\App::isEnabled('encryption')) {
369
+            return [];
370
+        }
371
+        /** @var \OCP\Files\Storage $storage */
372
+        list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
373
+        if (is_null($storage)) {
374
+            return [];
375
+        }
376
+
377
+        return $storage->getDirectDownload($internalPath);
378
+    }
379
+
380
+    /**
381
+     * @param resource $data
382
+     * @return null|string
383
+     * @throws Exception
384
+     * @throws BadRequest
385
+     * @throws NotImplemented
386
+     * @throws ServiceUnavailable
387
+     */
388
+    private function createFileChunked($data) {
389
+        list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($this->path);
390
+
391
+        $info = \OC_FileChunking::decodeName($name);
392
+        if (empty($info)) {
393
+            throw new NotImplemented('Invalid chunk name');
394
+        }
395
+
396
+        $chunk_handler = new \OC_FileChunking($info);
397
+        $bytesWritten = $chunk_handler->store($info['index'], $data);
398
+
399
+        //detect aborted upload
400
+        if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
401
+            if (isset($_SERVER['CONTENT_LENGTH'])) {
402
+                $expected = $_SERVER['CONTENT_LENGTH'];
403
+                if ($bytesWritten != $expected) {
404
+                    $chunk_handler->remove($info['index']);
405
+                    throw new BadRequest(
406
+                        'expected filesize ' . $expected . ' got ' . $bytesWritten);
407
+                }
408
+            }
409
+        }
410
+
411
+        if ($chunk_handler->isComplete()) {
412
+            list($storage,) = $this->fileView->resolvePath($path);
413
+            $needsPartFile = $this->needsPartFile($storage);
414
+            $partFile = null;
415
+
416
+            $targetPath = $path . '/' . $info['name'];
417
+            /** @var \OC\Files\Storage\Storage $targetStorage */
418
+            list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
419
+
420
+            $exists = $this->fileView->file_exists($targetPath);
421
+
422
+            try {
423
+                $this->fileView->lockFile($targetPath, ILockingProvider::LOCK_SHARED);
424
+
425
+                $this->emitPreHooks($exists, $targetPath);
426
+                $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_EXCLUSIVE);
427
+                /** @var \OC\Files\Storage\Storage $targetStorage */
428
+                list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
429
+
430
+                if ($needsPartFile) {
431
+                    // we first assembly the target file as a part file
432
+                    $partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
433
+                    /** @var \OC\Files\Storage\Storage $targetStorage */
434
+                    list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile);
435
+
436
+
437
+                    $chunk_handler->file_assemble($partStorage, $partInternalPath);
438
+
439
+                    // here is the final atomic rename
440
+                    $renameOkay = $targetStorage->moveFromStorage($partStorage, $partInternalPath, $targetInternalPath);
441
+                    $fileExists = $targetStorage->file_exists($targetInternalPath);
442
+                    if ($renameOkay === false || $fileExists === false) {
443
+                        \OCP\Util::writeLog('webdav', '\OC\Files\Filesystem::rename() failed', \OCP\Util::ERROR);
444
+                        // only delete if an error occurred and the target file was already created
445
+                        if ($fileExists) {
446
+                            // set to null to avoid double-deletion when handling exception
447
+                            // stray part file
448
+                            $partFile = null;
449
+                            $targetStorage->unlink($targetInternalPath);
450
+                        }
451
+                        $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
452
+                        throw new Exception('Could not rename part file assembled from chunks');
453
+                    }
454
+                } else {
455
+                    // assemble directly into the final file
456
+                    $chunk_handler->file_assemble($targetStorage, $targetInternalPath);
457
+                }
458
+
459
+                // allow sync clients to send the mtime along in a header
460
+                $request = \OC::$server->getRequest();
461
+                if (isset($request->server['HTTP_X_OC_MTIME'])) {
462
+                    if ($targetStorage->touch($targetInternalPath, $request->server['HTTP_X_OC_MTIME'])) {
463
+                        header('X-OC-MTime: accepted');
464
+                    }
465
+                }
466
+
467
+                // since we skipped the view we need to scan and emit the hooks ourselves
468
+                $targetStorage->getUpdater()->update($targetInternalPath);
469
+
470
+                $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
471
+
472
+                $this->emitPostHooks($exists, $targetPath);
473
+
474
+                // FIXME: should call refreshInfo but can't because $this->path is not the of the final file
475
+                $info = $this->fileView->getFileInfo($targetPath);
476
+
477
+                if (isset($request->server['HTTP_OC_CHECKSUM'])) {
478
+                    $checksum = trim($request->server['HTTP_OC_CHECKSUM']);
479
+                    $this->fileView->putFileInfo($targetPath, ['checksum' => $checksum]);
480
+                } else if ($info->getChecksum() !== null && $info->getChecksum() !== '') {
481
+                    $this->fileView->putFileInfo($this->path, ['checksum' => '']);
482
+                }
483
+
484
+                $this->fileView->unlockFile($targetPath, ILockingProvider::LOCK_SHARED);
485
+
486
+                return $info->getEtag();
487
+            } catch (\Exception $e) {
488
+                if ($partFile !== null) {
489
+                    $targetStorage->unlink($targetInternalPath);
490
+                }
491
+                $this->convertToSabreException($e);
492
+            }
493
+        }
494
+
495
+        return null;
496
+    }
497
+
498
+    /**
499
+     * Returns whether a part file is needed for the given storage
500
+     * or whether the file can be assembled/uploaded directly on the
501
+     * target storage.
502
+     *
503
+     * @param \OCP\Files\Storage $storage
504
+     * @return bool true if the storage needs part file handling
505
+     */
506
+    private function needsPartFile($storage) {
507
+        // TODO: in the future use ChunkHandler provided by storage
508
+        // and/or add method on Storage called "needsPartFile()"
509
+        return !$storage->instanceOfStorage('OCA\Files_Sharing\External\Storage') &&
510
+        !$storage->instanceOfStorage('OC\Files\Storage\OwnCloud');
511
+    }
512
+
513
+    /**
514
+     * Convert the given exception to a SabreException instance
515
+     *
516
+     * @param \Exception $e
517
+     *
518
+     * @throws \Sabre\DAV\Exception
519
+     */
520
+    private function convertToSabreException(\Exception $e) {
521
+        if ($e instanceof \Sabre\DAV\Exception) {
522
+            throw $e;
523
+        }
524
+        if ($e instanceof NotPermittedException) {
525
+            // a more general case - due to whatever reason the content could not be written
526
+            throw new Forbidden($e->getMessage(), 0, $e);
527
+        }
528
+        if ($e instanceof ForbiddenException) {
529
+            // the path for the file was forbidden
530
+            throw new DAVForbiddenException($e->getMessage(), $e->getRetry(), $e);
531
+        }
532
+        if ($e instanceof EntityTooLargeException) {
533
+            // the file is too big to be stored
534
+            throw new EntityTooLarge($e->getMessage(), 0, $e);
535
+        }
536
+        if ($e instanceof InvalidContentException) {
537
+            // the file content is not permitted
538
+            throw new UnsupportedMediaType($e->getMessage(), 0, $e);
539
+        }
540
+        if ($e instanceof InvalidPathException) {
541
+            // the path for the file was not valid
542
+            // TODO: find proper http status code for this case
543
+            throw new Forbidden($e->getMessage(), 0, $e);
544
+        }
545
+        if ($e instanceof LockedException || $e instanceof LockNotAcquiredException) {
546
+            // the file is currently being written to by another process
547
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
548
+        }
549
+        if ($e instanceof GenericEncryptionException) {
550
+            // returning 503 will allow retry of the operation at a later point in time
551
+            throw new ServiceUnavailable('Encryption not ready: ' . $e->getMessage(), 0, $e);
552
+        }
553
+        if ($e instanceof StorageNotAvailableException) {
554
+            throw new ServiceUnavailable('Failed to write file contents: ' . $e->getMessage(), 0, $e);
555
+        }
556
+
557
+        throw new \Sabre\DAV\Exception($e->getMessage(), 0, $e);
558
+    }
559
+
560
+    /**
561
+     * Get the checksum for this file
562
+     *
563
+     * @return string
564
+     */
565
+    public function getChecksum() {
566
+        return $this->info->getChecksum();
567
+    }
568 568
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/FilesReportPlugin.php 3 patches
Doc Comments   +3 added lines, -2 removed lines patch added patch discarded remove patch
@@ -89,7 +89,7 @@  discard block
 block discarded – undo
89 89
 	private $userFolder;
90 90
 
91 91
 	/**
92
-	 * @param Tree $tree
92
+	 * @param ObjectTree $tree
93 93
 	 * @param View $view
94 94
 	 */
95 95
 	public function __construct(Tree $tree,
@@ -134,7 +134,7 @@  discard block
 block discarded – undo
134 134
 	 * This will be used in the {DAV:}supported-report-set property.
135 135
 	 *
136 136
 	 * @param string $uri
137
-	 * @return array
137
+	 * @return string[]
138 138
 	 */
139 139
 	public function getSupportedReportSet($uri) {
140 140
 		return [self::REPORT_NAME];
@@ -265,6 +265,7 @@  discard block
 block discarded – undo
265 265
 	 *
266 266
 	 * @param string[] $requestedProps requested properties
267 267
 	 * @param Node[] nodes nodes for which to fetch and prepare responses
268
+	 * @param Node[] $nodes
268 269
 	 * @return Response[]
269 270
 	 */
270 271
 	public function prepareResponses($requestedProps, $nodes) {
Please login to merge, or discard this patch.
Indentation   +289 added lines, -289 removed lines patch added patch discarded remove patch
@@ -42,293 +42,293 @@
 block discarded – undo
42 42
 
43 43
 class FilesReportPlugin extends ServerPlugin {
44 44
 
45
-	// namespace
46
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
47
-	const REPORT_NAME            = '{http://owncloud.org/ns}filter-files';
48
-	const SYSTEMTAG_PROPERTYNAME = '{http://owncloud.org/ns}systemtag';
49
-
50
-	/**
51
-	 * Reference to main server object
52
-	 *
53
-	 * @var \Sabre\DAV\Server
54
-	 */
55
-	private $server;
56
-
57
-	/**
58
-	 * @var Tree
59
-	 */
60
-	private $tree;
61
-
62
-	/**
63
-	 * @var View
64
-	 */
65
-	private $fileView;
66
-
67
-	/**
68
-	 * @var ISystemTagManager
69
-	 */
70
-	private $tagManager;
71
-
72
-	/**
73
-	 * @var ISystemTagObjectMapper
74
-	 */
75
-	private $tagMapper;
76
-
77
-	/**
78
-	 * @var IUserSession
79
-	 */
80
-	private $userSession;
81
-
82
-	/**
83
-	 * @var IGroupManager
84
-	 */
85
-	private $groupManager;
86
-
87
-	/**
88
-	 * @var Folder
89
-	 */
90
-	private $userFolder;
91
-
92
-	/**
93
-	 * @param Tree $tree
94
-	 * @param View $view
95
-	 */
96
-	public function __construct(Tree $tree,
97
-								View $view,
98
-								ISystemTagManager $tagManager,
99
-								ISystemTagObjectMapper $tagMapper,
100
-								IUserSession $userSession,
101
-								IGroupManager $groupManager,
102
-								Folder $userFolder
103
-	) {
104
-		$this->tree = $tree;
105
-		$this->fileView = $view;
106
-		$this->tagManager = $tagManager;
107
-		$this->tagMapper = $tagMapper;
108
-		$this->userSession = $userSession;
109
-		$this->groupManager = $groupManager;
110
-		$this->userFolder = $userFolder;
111
-	}
112
-
113
-	/**
114
-	 * This initializes the plugin.
115
-	 *
116
-	 * This function is called by \Sabre\DAV\Server, after
117
-	 * addPlugin is called.
118
-	 *
119
-	 * This method should set up the required event subscriptions.
120
-	 *
121
-	 * @param \Sabre\DAV\Server $server
122
-	 * @return void
123
-	 */
124
-	public function initialize(\Sabre\DAV\Server $server) {
125
-
126
-		$server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
127
-
128
-		$this->server = $server;
129
-		$this->server->on('report', array($this, 'onReport'));
130
-	}
131
-
132
-	/**
133
-	 * Returns a list of reports this plugin supports.
134
-	 *
135
-	 * This will be used in the {DAV:}supported-report-set property.
136
-	 *
137
-	 * @param string $uri
138
-	 * @return array
139
-	 */
140
-	public function getSupportedReportSet($uri) {
141
-		return [self::REPORT_NAME];
142
-	}
143
-
144
-	/**
145
-	 * REPORT operations to look for files
146
-	 *
147
-	 * @param string $reportName
148
-	 * @param [] $report
149
-	 * @param string $uri
150
-	 * @return bool
151
-	 * @throws NotFound
152
-	 * @throws ReportNotSupported
153
-	 */
154
-	public function onReport($reportName, $report, $uri) {
155
-		$reportTargetNode = $this->server->tree->getNodeForPath($uri);
156
-		if (!$reportTargetNode instanceof Directory || $reportName !== self::REPORT_NAME) {
157
-			throw new ReportNotSupported();
158
-		}
159
-
160
-		$ns = '{' . $this::NS_OWNCLOUD . '}';
161
-		$requestedProps = [];
162
-		$filterRules = [];
163
-
164
-		// parse report properties and gather filter info
165
-		foreach ($report as $reportProps) {
166
-			$name = $reportProps['name'];
167
-			if ($name === $ns . 'filter-rules') {
168
-				$filterRules = $reportProps['value'];
169
-			} else if ($name === '{DAV:}prop') {
170
-				// propfind properties
171
-				foreach ($reportProps['value'] as $propVal) {
172
-					$requestedProps[] = $propVal['name'];
173
-				}
174
-			}
175
-		}
176
-
177
-		if (empty($filterRules)) {
178
-			// an empty filter would return all existing files which would be slow
179
-			throw new BadRequest('Missing filter-rule block in request');
180
-		}
181
-
182
-		// gather all file ids matching filter
183
-		try {
184
-			$resultFileIds = $this->processFilterRules($filterRules);
185
-		} catch (TagNotFoundException $e) {
186
-			throw new PreconditionFailed('Cannot filter by non-existing tag', 0, $e);
187
-		}
188
-
189
-		// find sabre nodes by file id, restricted to the root node path
190
-		$results = $this->findNodesByFileIds($reportTargetNode, $resultFileIds);
191
-
192
-		$responses = $this->prepareResponses($requestedProps, $results);
193
-
194
-		$xml = $this->server->xml->write(
195
-			'{DAV:}multistatus',
196
-			new MultiStatus($responses)
197
-		);
198
-
199
-		$this->server->httpResponse->setStatus(207);
200
-		$this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
201
-		$this->server->httpResponse->setBody($xml);
202
-
203
-		return false;
204
-	}
205
-
206
-	/**
207
-	 * Find file ids matching the given filter rules
208
-	 *
209
-	 * @param array $filterRules
210
-	 * @return array array of unique file id results
211
-	 *
212
-	 * @throws TagNotFoundException whenever a tag was not found
213
-	 */
214
-	protected function processFilterRules($filterRules) {
215
-		$ns = '{' . $this::NS_OWNCLOUD . '}';
216
-		$resultFileIds = null;
217
-		$systemTagIds = [];
218
-		foreach ($filterRules as $filterRule) {
219
-			if ($filterRule['name'] === $ns . 'systemtag') {
220
-				$systemTagIds[] = $filterRule['value'];
221
-			}
222
-		}
223
-
224
-		// check user permissions, if applicable
225
-		if (!$this->isAdmin()) {
226
-			// check visibility/permission
227
-			$tags = $this->tagManager->getTagsByIds($systemTagIds);
228
-			$unknownTagIds = [];
229
-			foreach ($tags as $tag) {
230
-				if (!$tag->isUserVisible()) {
231
-					$unknownTagIds[] = $tag->getId();
232
-				}
233
-			}
234
-
235
-			if (!empty($unknownTagIds)) {
236
-				throw new TagNotFoundException('Tag with ids ' . implode(', ', $unknownTagIds) . ' not found');
237
-			}
238
-		}
239
-
240
-		// fetch all file ids and intersect them
241
-		foreach ($systemTagIds as $systemTagId) {
242
-			$fileIds = $this->tagMapper->getObjectIdsForTags($systemTagId, 'files');
243
-
244
-			if (empty($fileIds)) {
245
-				// This tag has no files, nothing can ever show up
246
-				return [];
247
-			}
248
-
249
-			// first run ?
250
-			if ($resultFileIds === null) {
251
-				$resultFileIds = $fileIds;
252
-			} else {
253
-				$resultFileIds = array_intersect($resultFileIds, $fileIds);
254
-			}
255
-
256
-			if (empty($resultFileIds)) {
257
-				// Empty intersection, nothing can show up anymore
258
-				return [];
259
-			}
260
-		}
261
-		return $resultFileIds;
262
-	}
263
-
264
-	/**
265
-	 * Prepare propfind response for the given nodes
266
-	 *
267
-	 * @param string[] $requestedProps requested properties
268
-	 * @param Node[] nodes nodes for which to fetch and prepare responses
269
-	 * @return Response[]
270
-	 */
271
-	public function prepareResponses($requestedProps, $nodes) {
272
-		$responses = [];
273
-		foreach ($nodes as $node) {
274
-			$propFind = new PropFind($node->getPath(), $requestedProps);
275
-
276
-			$this->server->getPropertiesByNode($propFind, $node);
277
-			// copied from Sabre Server's getPropertiesForPath
278
-			$result = $propFind->getResultForMultiStatus();
279
-			$result['href'] = $propFind->getPath();
280
-
281
-			$resourceType = $this->server->getResourceTypeForNode($node);
282
-			if (in_array('{DAV:}collection', $resourceType) || in_array('{DAV:}principal', $resourceType)) {
283
-				$result['href'] .= '/';
284
-			}
285
-
286
-			$responses[] = new Response(
287
-				rtrim($this->server->getBaseUri(), '/') . $node->getPath(),
288
-				$result,
289
-				200
290
-			);
291
-		}
292
-		return $responses;
293
-	}
294
-
295
-	/**
296
-	 * Find Sabre nodes by file ids
297
-	 *
298
-	 * @param Node $rootNode root node for search
299
-	 * @param array $fileIds file ids
300
-	 * @return Node[] array of Sabre nodes
301
-	 */
302
-	public function findNodesByFileIds($rootNode, $fileIds) {
303
-		$folder = $this->userFolder;
304
-		if (trim($rootNode->getPath(), '/') !== '') {
305
-			$folder = $folder->get($rootNode->getPath());
306
-		}
307
-
308
-		$results = [];
309
-		foreach ($fileIds as $fileId) {
310
-			$entry = $folder->getById($fileId);
311
-			if ($entry) {
312
-				$entry = current($entry);
313
-				if ($entry instanceof \OCP\Files\File) {
314
-					$results[] = new File($this->fileView, $entry);
315
-				} else if ($entry instanceof \OCP\Files\Folder) {
316
-					$results[] = new Directory($this->fileView, $entry);
317
-				}
318
-			}
319
-		}
320
-
321
-		return $results;
322
-	}
323
-
324
-	/**
325
-	 * Returns whether the currently logged in user is an administrator
326
-	 */
327
-	private function isAdmin() {
328
-		$user = $this->userSession->getUser();
329
-		if ($user !== null) {
330
-			return $this->groupManager->isAdmin($user->getUID());
331
-		}
332
-		return false;
333
-	}
45
+    // namespace
46
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
47
+    const REPORT_NAME            = '{http://owncloud.org/ns}filter-files';
48
+    const SYSTEMTAG_PROPERTYNAME = '{http://owncloud.org/ns}systemtag';
49
+
50
+    /**
51
+     * Reference to main server object
52
+     *
53
+     * @var \Sabre\DAV\Server
54
+     */
55
+    private $server;
56
+
57
+    /**
58
+     * @var Tree
59
+     */
60
+    private $tree;
61
+
62
+    /**
63
+     * @var View
64
+     */
65
+    private $fileView;
66
+
67
+    /**
68
+     * @var ISystemTagManager
69
+     */
70
+    private $tagManager;
71
+
72
+    /**
73
+     * @var ISystemTagObjectMapper
74
+     */
75
+    private $tagMapper;
76
+
77
+    /**
78
+     * @var IUserSession
79
+     */
80
+    private $userSession;
81
+
82
+    /**
83
+     * @var IGroupManager
84
+     */
85
+    private $groupManager;
86
+
87
+    /**
88
+     * @var Folder
89
+     */
90
+    private $userFolder;
91
+
92
+    /**
93
+     * @param Tree $tree
94
+     * @param View $view
95
+     */
96
+    public function __construct(Tree $tree,
97
+                                View $view,
98
+                                ISystemTagManager $tagManager,
99
+                                ISystemTagObjectMapper $tagMapper,
100
+                                IUserSession $userSession,
101
+                                IGroupManager $groupManager,
102
+                                Folder $userFolder
103
+    ) {
104
+        $this->tree = $tree;
105
+        $this->fileView = $view;
106
+        $this->tagManager = $tagManager;
107
+        $this->tagMapper = $tagMapper;
108
+        $this->userSession = $userSession;
109
+        $this->groupManager = $groupManager;
110
+        $this->userFolder = $userFolder;
111
+    }
112
+
113
+    /**
114
+     * This initializes the plugin.
115
+     *
116
+     * This function is called by \Sabre\DAV\Server, after
117
+     * addPlugin is called.
118
+     *
119
+     * This method should set up the required event subscriptions.
120
+     *
121
+     * @param \Sabre\DAV\Server $server
122
+     * @return void
123
+     */
124
+    public function initialize(\Sabre\DAV\Server $server) {
125
+
126
+        $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
127
+
128
+        $this->server = $server;
129
+        $this->server->on('report', array($this, 'onReport'));
130
+    }
131
+
132
+    /**
133
+     * Returns a list of reports this plugin supports.
134
+     *
135
+     * This will be used in the {DAV:}supported-report-set property.
136
+     *
137
+     * @param string $uri
138
+     * @return array
139
+     */
140
+    public function getSupportedReportSet($uri) {
141
+        return [self::REPORT_NAME];
142
+    }
143
+
144
+    /**
145
+     * REPORT operations to look for files
146
+     *
147
+     * @param string $reportName
148
+     * @param [] $report
149
+     * @param string $uri
150
+     * @return bool
151
+     * @throws NotFound
152
+     * @throws ReportNotSupported
153
+     */
154
+    public function onReport($reportName, $report, $uri) {
155
+        $reportTargetNode = $this->server->tree->getNodeForPath($uri);
156
+        if (!$reportTargetNode instanceof Directory || $reportName !== self::REPORT_NAME) {
157
+            throw new ReportNotSupported();
158
+        }
159
+
160
+        $ns = '{' . $this::NS_OWNCLOUD . '}';
161
+        $requestedProps = [];
162
+        $filterRules = [];
163
+
164
+        // parse report properties and gather filter info
165
+        foreach ($report as $reportProps) {
166
+            $name = $reportProps['name'];
167
+            if ($name === $ns . 'filter-rules') {
168
+                $filterRules = $reportProps['value'];
169
+            } else if ($name === '{DAV:}prop') {
170
+                // propfind properties
171
+                foreach ($reportProps['value'] as $propVal) {
172
+                    $requestedProps[] = $propVal['name'];
173
+                }
174
+            }
175
+        }
176
+
177
+        if (empty($filterRules)) {
178
+            // an empty filter would return all existing files which would be slow
179
+            throw new BadRequest('Missing filter-rule block in request');
180
+        }
181
+
182
+        // gather all file ids matching filter
183
+        try {
184
+            $resultFileIds = $this->processFilterRules($filterRules);
185
+        } catch (TagNotFoundException $e) {
186
+            throw new PreconditionFailed('Cannot filter by non-existing tag', 0, $e);
187
+        }
188
+
189
+        // find sabre nodes by file id, restricted to the root node path
190
+        $results = $this->findNodesByFileIds($reportTargetNode, $resultFileIds);
191
+
192
+        $responses = $this->prepareResponses($requestedProps, $results);
193
+
194
+        $xml = $this->server->xml->write(
195
+            '{DAV:}multistatus',
196
+            new MultiStatus($responses)
197
+        );
198
+
199
+        $this->server->httpResponse->setStatus(207);
200
+        $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
201
+        $this->server->httpResponse->setBody($xml);
202
+
203
+        return false;
204
+    }
205
+
206
+    /**
207
+     * Find file ids matching the given filter rules
208
+     *
209
+     * @param array $filterRules
210
+     * @return array array of unique file id results
211
+     *
212
+     * @throws TagNotFoundException whenever a tag was not found
213
+     */
214
+    protected function processFilterRules($filterRules) {
215
+        $ns = '{' . $this::NS_OWNCLOUD . '}';
216
+        $resultFileIds = null;
217
+        $systemTagIds = [];
218
+        foreach ($filterRules as $filterRule) {
219
+            if ($filterRule['name'] === $ns . 'systemtag') {
220
+                $systemTagIds[] = $filterRule['value'];
221
+            }
222
+        }
223
+
224
+        // check user permissions, if applicable
225
+        if (!$this->isAdmin()) {
226
+            // check visibility/permission
227
+            $tags = $this->tagManager->getTagsByIds($systemTagIds);
228
+            $unknownTagIds = [];
229
+            foreach ($tags as $tag) {
230
+                if (!$tag->isUserVisible()) {
231
+                    $unknownTagIds[] = $tag->getId();
232
+                }
233
+            }
234
+
235
+            if (!empty($unknownTagIds)) {
236
+                throw new TagNotFoundException('Tag with ids ' . implode(', ', $unknownTagIds) . ' not found');
237
+            }
238
+        }
239
+
240
+        // fetch all file ids and intersect them
241
+        foreach ($systemTagIds as $systemTagId) {
242
+            $fileIds = $this->tagMapper->getObjectIdsForTags($systemTagId, 'files');
243
+
244
+            if (empty($fileIds)) {
245
+                // This tag has no files, nothing can ever show up
246
+                return [];
247
+            }
248
+
249
+            // first run ?
250
+            if ($resultFileIds === null) {
251
+                $resultFileIds = $fileIds;
252
+            } else {
253
+                $resultFileIds = array_intersect($resultFileIds, $fileIds);
254
+            }
255
+
256
+            if (empty($resultFileIds)) {
257
+                // Empty intersection, nothing can show up anymore
258
+                return [];
259
+            }
260
+        }
261
+        return $resultFileIds;
262
+    }
263
+
264
+    /**
265
+     * Prepare propfind response for the given nodes
266
+     *
267
+     * @param string[] $requestedProps requested properties
268
+     * @param Node[] nodes nodes for which to fetch and prepare responses
269
+     * @return Response[]
270
+     */
271
+    public function prepareResponses($requestedProps, $nodes) {
272
+        $responses = [];
273
+        foreach ($nodes as $node) {
274
+            $propFind = new PropFind($node->getPath(), $requestedProps);
275
+
276
+            $this->server->getPropertiesByNode($propFind, $node);
277
+            // copied from Sabre Server's getPropertiesForPath
278
+            $result = $propFind->getResultForMultiStatus();
279
+            $result['href'] = $propFind->getPath();
280
+
281
+            $resourceType = $this->server->getResourceTypeForNode($node);
282
+            if (in_array('{DAV:}collection', $resourceType) || in_array('{DAV:}principal', $resourceType)) {
283
+                $result['href'] .= '/';
284
+            }
285
+
286
+            $responses[] = new Response(
287
+                rtrim($this->server->getBaseUri(), '/') . $node->getPath(),
288
+                $result,
289
+                200
290
+            );
291
+        }
292
+        return $responses;
293
+    }
294
+
295
+    /**
296
+     * Find Sabre nodes by file ids
297
+     *
298
+     * @param Node $rootNode root node for search
299
+     * @param array $fileIds file ids
300
+     * @return Node[] array of Sabre nodes
301
+     */
302
+    public function findNodesByFileIds($rootNode, $fileIds) {
303
+        $folder = $this->userFolder;
304
+        if (trim($rootNode->getPath(), '/') !== '') {
305
+            $folder = $folder->get($rootNode->getPath());
306
+        }
307
+
308
+        $results = [];
309
+        foreach ($fileIds as $fileId) {
310
+            $entry = $folder->getById($fileId);
311
+            if ($entry) {
312
+                $entry = current($entry);
313
+                if ($entry instanceof \OCP\Files\File) {
314
+                    $results[] = new File($this->fileView, $entry);
315
+                } else if ($entry instanceof \OCP\Files\Folder) {
316
+                    $results[] = new Directory($this->fileView, $entry);
317
+                }
318
+            }
319
+        }
320
+
321
+        return $results;
322
+    }
323
+
324
+    /**
325
+     * Returns whether the currently logged in user is an administrator
326
+     */
327
+    private function isAdmin() {
328
+        $user = $this->userSession->getUser();
329
+        if ($user !== null) {
330
+            return $this->groupManager->isAdmin($user->getUID());
331
+        }
332
+        return false;
333
+    }
334 334
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -157,14 +157,14 @@  discard block
 block discarded – undo
157 157
 			throw new ReportNotSupported();
158 158
 		}
159 159
 
160
-		$ns = '{' . $this::NS_OWNCLOUD . '}';
160
+		$ns = '{'.$this::NS_OWNCLOUD.'}';
161 161
 		$requestedProps = [];
162 162
 		$filterRules = [];
163 163
 
164 164
 		// parse report properties and gather filter info
165 165
 		foreach ($report as $reportProps) {
166 166
 			$name = $reportProps['name'];
167
-			if ($name === $ns . 'filter-rules') {
167
+			if ($name === $ns.'filter-rules') {
168 168
 				$filterRules = $reportProps['value'];
169 169
 			} else if ($name === '{DAV:}prop') {
170 170
 				// propfind properties
@@ -212,11 +212,11 @@  discard block
 block discarded – undo
212 212
 	 * @throws TagNotFoundException whenever a tag was not found
213 213
 	 */
214 214
 	protected function processFilterRules($filterRules) {
215
-		$ns = '{' . $this::NS_OWNCLOUD . '}';
215
+		$ns = '{'.$this::NS_OWNCLOUD.'}';
216 216
 		$resultFileIds = null;
217 217
 		$systemTagIds = [];
218 218
 		foreach ($filterRules as $filterRule) {
219
-			if ($filterRule['name'] === $ns . 'systemtag') {
219
+			if ($filterRule['name'] === $ns.'systemtag') {
220 220
 				$systemTagIds[] = $filterRule['value'];
221 221
 			}
222 222
 		}
@@ -233,7 +233,7 @@  discard block
 block discarded – undo
233 233
 			}
234 234
 
235 235
 			if (!empty($unknownTagIds)) {
236
-				throw new TagNotFoundException('Tag with ids ' . implode(', ', $unknownTagIds) . ' not found');
236
+				throw new TagNotFoundException('Tag with ids '.implode(', ', $unknownTagIds).' not found');
237 237
 			}
238 238
 		}
239 239
 
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
 			}
285 285
 
286 286
 			$responses[] = new Response(
287
-				rtrim($this->server->getBaseUri(), '/') . $node->getPath(),
287
+				rtrim($this->server->getBaseUri(), '/').$node->getPath(),
288 288
 				$result,
289 289
 				200
290 290
 			);
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/ShareTypeList.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -60,7 +60,7 @@
 block discarded – undo
60 60
 	 * The deserialize method is called during xml parsing.
61 61
 	 *
62 62
 	 * @param Reader $reader
63
-	 * @return mixed
63
+	 * @return ShareTypeList
64 64
 	 */
65 65
 	static function xmlDeserialize(Reader $reader) {
66 66
 		$shareTypes = [];
Please login to merge, or discard this patch.
Indentation   +47 added lines, -47 removed lines patch added patch discarded remove patch
@@ -32,57 +32,57 @@
 block discarded – undo
32 32
  * This property contains multiple "share-type" elements, each containing a share type.
33 33
  */
34 34
 class ShareTypeList implements Element {
35
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
35
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
36 36
 
37
-	/**
38
-	 * Share types
39
-	 *
40
-	 * @var int[]
41
-	 */
42
-	private $shareTypes;
37
+    /**
38
+     * Share types
39
+     *
40
+     * @var int[]
41
+     */
42
+    private $shareTypes;
43 43
 
44
-	/**
45
-	 * @param int[] $shareTypes
46
-	 */
47
-	public function __construct($shareTypes) {
48
-		$this->shareTypes = $shareTypes;
49
-	}
44
+    /**
45
+     * @param int[] $shareTypes
46
+     */
47
+    public function __construct($shareTypes) {
48
+        $this->shareTypes = $shareTypes;
49
+    }
50 50
 
51
-	/**
52
-	 * Returns the share types
53
-	 *
54
-	 * @return int[]
55
-	 */
56
-	public function getShareTypes() {
57
-		return $this->shareTypes;
58
-	}
51
+    /**
52
+     * Returns the share types
53
+     *
54
+     * @return int[]
55
+     */
56
+    public function getShareTypes() {
57
+        return $this->shareTypes;
58
+    }
59 59
 
60
-	/**
61
-	 * The deserialize method is called during xml parsing.
62
-	 *
63
-	 * @param Reader $reader
64
-	 * @return mixed
65
-	 */
66
-	static function xmlDeserialize(Reader $reader) {
67
-		$shareTypes = [];
60
+    /**
61
+     * The deserialize method is called during xml parsing.
62
+     *
63
+     * @param Reader $reader
64
+     * @return mixed
65
+     */
66
+    static function xmlDeserialize(Reader $reader) {
67
+        $shareTypes = [];
68 68
 
69
-		foreach ($reader->parseInnerTree() as $elem) {
70
-			if ($elem['name'] === '{' . self::NS_OWNCLOUD . '}share-type') {
71
-				$shareTypes[] = (int)$elem['value'];
72
-			}
73
-		}
74
-		return new self($shareTypes);
75
-	}
69
+        foreach ($reader->parseInnerTree() as $elem) {
70
+            if ($elem['name'] === '{' . self::NS_OWNCLOUD . '}share-type') {
71
+                $shareTypes[] = (int)$elem['value'];
72
+            }
73
+        }
74
+        return new self($shareTypes);
75
+    }
76 76
 
77
-	/**
78
-	 * The xmlSerialize metod is called during xml writing.
79
-	 *
80
-	 * @param Writer $writer
81
-	 * @return void
82
-	 */
83
-	function xmlSerialize(Writer $writer) {
84
-		foreach ($this->shareTypes as $shareType) {
85
-			$writer->writeElement('{' . self::NS_OWNCLOUD . '}share-type', $shareType);
86
-		}
87
-	}
77
+    /**
78
+     * The xmlSerialize metod is called during xml writing.
79
+     *
80
+     * @param Writer $writer
81
+     * @return void
82
+     */
83
+    function xmlSerialize(Writer $writer) {
84
+        foreach ($this->shareTypes as $shareType) {
85
+            $writer->writeElement('{' . self::NS_OWNCLOUD . '}share-type', $shareType);
86
+        }
87
+    }
88 88
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -67,8 +67,8 @@  discard block
 block discarded – undo
67 67
 		$shareTypes = [];
68 68
 
69 69
 		foreach ($reader->parseInnerTree() as $elem) {
70
-			if ($elem['name'] === '{' . self::NS_OWNCLOUD . '}share-type') {
71
-				$shareTypes[] = (int)$elem['value'];
70
+			if ($elem['name'] === '{'.self::NS_OWNCLOUD.'}share-type') {
71
+				$shareTypes[] = (int) $elem['value'];
72 72
 			}
73 73
 		}
74 74
 		return new self($shareTypes);
@@ -82,7 +82,7 @@  discard block
 block discarded – undo
82 82
 	 */
83 83
 	function xmlSerialize(Writer $writer) {
84 84
 		foreach ($this->shareTypes as $shareType) {
85
-			$writer->writeElement('{' . self::NS_OWNCLOUD . '}share-type', $shareType);
85
+			$writer->writeElement('{'.self::NS_OWNCLOUD.'}share-type', $shareType);
86 86
 		}
87 87
 	}
88 88
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/TagList.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -79,7 +79,7 @@
 block discarded – undo
79 79
 	 * the next element.
80 80
 	 *
81 81
 	 * @param Reader $reader
82
-	 * @return mixed
82
+	 * @return TagList
83 83
 	 */
84 84
 	static function xmlDeserialize(Reader $reader) {
85 85
 		$tags = [];
Please login to merge, or discard this patch.
Indentation   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -34,88 +34,88 @@
 block discarded – undo
34 34
  * This property contains multiple "tag" elements, each containing a tag name.
35 35
  */
36 36
 class TagList implements Element {
37
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
37
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
38 38
 
39
-	/**
40
-	 * tags
41
-	 *
42
-	 * @var array
43
-	 */
44
-	private $tags;
39
+    /**
40
+     * tags
41
+     *
42
+     * @var array
43
+     */
44
+    private $tags;
45 45
 
46
-	/**
47
-	 * @param array $tags
48
-	 */
49
-	public function __construct(array $tags) {
50
-		$this->tags = $tags;
51
-	}
46
+    /**
47
+     * @param array $tags
48
+     */
49
+    public function __construct(array $tags) {
50
+        $this->tags = $tags;
51
+    }
52 52
 
53
-	/**
54
-	 * Returns the tags
55
-	 *
56
-	 * @return array
57
-	 */
58
-	public function getTags() {
53
+    /**
54
+     * Returns the tags
55
+     *
56
+     * @return array
57
+     */
58
+    public function getTags() {
59 59
 
60
-		return $this->tags;
60
+        return $this->tags;
61 61
 
62
-	}
62
+    }
63 63
 
64
-	/**
65
-	 * The deserialize method is called during xml parsing.
66
-	 *
67
-	 * This method is called statictly, this is because in theory this method
68
-	 * may be used as a type of constructor, or factory method.
69
-	 *
70
-	 * Often you want to return an instance of the current class, but you are
71
-	 * free to return other data as well.
72
-	 *
73
-	 * You are responsible for advancing the reader to the next element. Not
74
-	 * doing anything will result in a never-ending loop.
75
-	 *
76
-	 * If you just want to skip parsing for this element altogether, you can
77
-	 * just call $reader->next();
78
-	 *
79
-	 * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
80
-	 * the next element.
81
-	 *
82
-	 * @param Reader $reader
83
-	 * @return mixed
84
-	 */
85
-	static function xmlDeserialize(Reader $reader) {
86
-		$tags = [];
64
+    /**
65
+     * The deserialize method is called during xml parsing.
66
+     *
67
+     * This method is called statictly, this is because in theory this method
68
+     * may be used as a type of constructor, or factory method.
69
+     *
70
+     * Often you want to return an instance of the current class, but you are
71
+     * free to return other data as well.
72
+     *
73
+     * You are responsible for advancing the reader to the next element. Not
74
+     * doing anything will result in a never-ending loop.
75
+     *
76
+     * If you just want to skip parsing for this element altogether, you can
77
+     * just call $reader->next();
78
+     *
79
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
80
+     * the next element.
81
+     *
82
+     * @param Reader $reader
83
+     * @return mixed
84
+     */
85
+    static function xmlDeserialize(Reader $reader) {
86
+        $tags = [];
87 87
 
88
-		foreach ($reader->parseInnerTree() as $elem) {
89
-			if ($elem['name'] === '{' . self::NS_OWNCLOUD . '}tag') {
90
-				$tags[] = $elem['value'];
91
-			}
92
-		}
93
-		return new self($tags);
94
-	}
88
+        foreach ($reader->parseInnerTree() as $elem) {
89
+            if ($elem['name'] === '{' . self::NS_OWNCLOUD . '}tag') {
90
+                $tags[] = $elem['value'];
91
+            }
92
+        }
93
+        return new self($tags);
94
+    }
95 95
 
96
-	/**
97
-	 * The xmlSerialize metod is called during xml writing.
98
-	 *
99
-	 * Use the $writer argument to write its own xml serialization.
100
-	 *
101
-	 * An important note: do _not_ create a parent element. Any element
102
-	 * implementing XmlSerializble should only ever write what's considered
103
-	 * its 'inner xml'.
104
-	 *
105
-	 * The parent of the current element is responsible for writing a
106
-	 * containing element.
107
-	 *
108
-	 * This allows serializers to be re-used for different element names.
109
-	 *
110
-	 * If you are opening new elements, you must also close them again.
111
-	 *
112
-	 * @param Writer $writer
113
-	 * @return void
114
-	 */
115
-	function xmlSerialize(Writer $writer) {
96
+    /**
97
+     * The xmlSerialize metod is called during xml writing.
98
+     *
99
+     * Use the $writer argument to write its own xml serialization.
100
+     *
101
+     * An important note: do _not_ create a parent element. Any element
102
+     * implementing XmlSerializble should only ever write what's considered
103
+     * its 'inner xml'.
104
+     *
105
+     * The parent of the current element is responsible for writing a
106
+     * containing element.
107
+     *
108
+     * This allows serializers to be re-used for different element names.
109
+     *
110
+     * If you are opening new elements, you must also close them again.
111
+     *
112
+     * @param Writer $writer
113
+     * @return void
114
+     */
115
+    function xmlSerialize(Writer $writer) {
116 116
 
117
-		foreach ($this->tags as $tag) {
118
-			$writer->writeElement('{' . self::NS_OWNCLOUD . '}tag', $tag);
119
-		}
120
-	}
117
+        foreach ($this->tags as $tag) {
118
+            $writer->writeElement('{' . self::NS_OWNCLOUD . '}tag', $tag);
119
+        }
120
+    }
121 121
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -86,7 +86,7 @@  discard block
 block discarded – undo
86 86
 		$tags = [];
87 87
 
88 88
 		foreach ($reader->parseInnerTree() as $elem) {
89
-			if ($elem['name'] === '{' . self::NS_OWNCLOUD . '}tag') {
89
+			if ($elem['name'] === '{'.self::NS_OWNCLOUD.'}tag') {
90 90
 				$tags[] = $elem['value'];
91 91
 			}
92 92
 		}
@@ -115,7 +115,7 @@  discard block
 block discarded – undo
115 115
 	function xmlSerialize(Writer $writer) {
116 116
 
117 117
 		foreach ($this->tags as $tag) {
118
-			$writer->writeElement('{' . self::NS_OWNCLOUD . '}tag', $tag);
118
+			$writer->writeElement('{'.self::NS_OWNCLOUD.'}tag', $tag);
119 119
 		}
120 120
 	}
121 121
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/TagsPlugin.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -85,7 +85,7 @@
 block discarded – undo
85 85
 	private $tree;
86 86
 
87 87
 	/**
88
-	 * @param \Sabre\DAV\Tree $tree tree
88
+	 * @param ObjectTree $tree tree
89 89
 	 * @param \OCP\ITagManager $tagManager tag manager
90 90
 	 */
91 91
 	public function __construct(\Sabre\DAV\Tree $tree, \OCP\ITagManager $tagManager) {
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) {
@@ -281,7 +281,7 @@  discard block
 block discarded – undo
281 281
 			if (is_null($node)) {
282 282
 				return 404;
283 283
 			}
284
-			if ((int)$favState === 1 || $favState === 'true') {
284
+			if ((int) $favState === 1 || $favState === 'true') {
285 285
 				$this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE);
286 286
 			} else {
287 287
 				$this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE);
Please login to merge, or discard this patch.
Indentation   +218 added lines, -218 removed lines patch added patch discarded remove patch
@@ -49,246 +49,246 @@
 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
-			return $isFav;
254
-		});
255
-	}
249
+        $propFind->handle(self::FAVORITE_PROPERTYNAME, function() use ($isFav, $node) {
250
+            if (is_null($isFav)) {
251
+                list(, $isFav) = $this->getTagsAndFav($node->getId());
252
+            }
253
+            return $isFav;
254
+        });
255
+    }
256 256
 
257
-	/**
258
-	 * Updates tags and favorites properties, if applicable.
259
-	 *
260
-	 * @param string $path
261
-	 * @param PropPatch $propPatch
262
-	 *
263
-	 * @return void
264
-	 */
265
-	public function handleUpdateProperties($path, PropPatch $propPatch) {
266
-		$propPatch->handle(self::TAGS_PROPERTYNAME, function($tagList) use ($path) {
267
-			$node = $this->tree->getNodeForPath($path);
268
-			if (is_null($node)) {
269
-				return 404;
270
-			}
271
-			$this->updateTags($node->getId(), $tagList->getTags());
272
-			return true;
273
-		});
257
+    /**
258
+     * Updates tags and favorites properties, if applicable.
259
+     *
260
+     * @param string $path
261
+     * @param PropPatch $propPatch
262
+     *
263
+     * @return void
264
+     */
265
+    public function handleUpdateProperties($path, PropPatch $propPatch) {
266
+        $propPatch->handle(self::TAGS_PROPERTYNAME, function($tagList) use ($path) {
267
+            $node = $this->tree->getNodeForPath($path);
268
+            if (is_null($node)) {
269
+                return 404;
270
+            }
271
+            $this->updateTags($node->getId(), $tagList->getTags());
272
+            return true;
273
+        });
274 274
 
275
-		$propPatch->handle(self::FAVORITE_PROPERTYNAME, function($favState) use ($path) {
276
-			$node = $this->tree->getNodeForPath($path);
277
-			if (is_null($node)) {
278
-				return 404;
279
-			}
280
-			if ((int)$favState === 1 || $favState === 'true') {
281
-				$this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE);
282
-			} else {
283
-				$this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE);
284
-			}
275
+        $propPatch->handle(self::FAVORITE_PROPERTYNAME, function($favState) use ($path) {
276
+            $node = $this->tree->getNodeForPath($path);
277
+            if (is_null($node)) {
278
+                return 404;
279
+            }
280
+            if ((int)$favState === 1 || $favState === 'true') {
281
+                $this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE);
282
+            } else {
283
+                $this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE);
284
+            }
285 285
 
286
-			if (is_null($favState)) {
287
-				// confirm deletion
288
-				return 204;
289
-			}
286
+            if (is_null($favState)) {
287
+                // confirm deletion
288
+                return 204;
289
+            }
290 290
 
291
-			return 200;
292
-		});
293
-	}
291
+            return 200;
292
+        });
293
+    }
294 294
 }
Please login to merge, or discard this patch.
apps/dav/lib/DAV/Sharing/Plugin.php 4 patches
Unused Use Statements   -1 removed lines patch added patch discarded remove patch
@@ -24,7 +24,6 @@
 block discarded – undo
24 24
 use OCA\DAV\Connector\Sabre\Auth;
25 25
 use OCA\DAV\DAV\Sharing\Xml\Invite;
26 26
 use OCP\IRequest;
27
-use Sabre\DAV\Exception\BadRequest;
28 27
 use Sabre\DAV\Exception\NotFound;
29 28
 use Sabre\DAV\INode;
30 29
 use Sabre\DAV\PropFind;
Please login to merge, or discard this patch.
Indentation   +161 added lines, -161 removed lines patch added patch discarded remove patch
@@ -36,166 +36,166 @@
 block discarded – undo
36 36
 
37 37
 class Plugin extends ServerPlugin {
38 38
 
39
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
40
-
41
-	/** @var Auth */
42
-	private $auth;
43
-
44
-	/** @var IRequest */
45
-	private $request;
46
-
47
-	/**
48
-	 * Plugin constructor.
49
-	 *
50
-	 * @param Auth $authBackEnd
51
-	 * @param IRequest $request
52
-	 */
53
-	public function __construct(Auth $authBackEnd, IRequest $request) {
54
-		$this->auth = $authBackEnd;
55
-		$this->request = $request;
56
-	}
57
-
58
-	/**
59
-	 * Reference to SabreDAV server object.
60
-	 *
61
-	 * @var \Sabre\DAV\Server
62
-	 */
63
-	protected $server;
64
-
65
-	/**
66
-	 * This method should return a list of server-features.
67
-	 *
68
-	 * This is for example 'versioning' and is added to the DAV: header
69
-	 * in an OPTIONS response.
70
-	 *
71
-	 * @return string[]
72
-	 */
73
-	function getFeatures() {
74
-		return ['oc-resource-sharing'];
75
-	}
76
-
77
-	/**
78
-	 * Returns a plugin name.
79
-	 *
80
-	 * Using this name other plugins will be able to access other plugins
81
-	 * using Sabre\DAV\Server::getPlugin
82
-	 *
83
-	 * @return string
84
-	 */
85
-	function getPluginName() {
86
-		return 'oc-resource-sharing';
87
-	}
88
-
89
-	/**
90
-	 * This initializes the plugin.
91
-	 *
92
-	 * This function is called by Sabre\DAV\Server, after
93
-	 * addPlugin is called.
94
-	 *
95
-	 * This method should set up the required event subscriptions.
96
-	 *
97
-	 * @param Server $server
98
-	 * @return void
99
-	 */
100
-	function initialize(Server $server) {
101
-		$this->server = $server;
102
-		$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}share'] = 'OCA\\DAV\\DAV\\Sharing\\Xml\\ShareRequest';
103
-		$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}invite'] = 'OCA\\DAV\\DAV\\Sharing\\Xml\\Invite';
104
-
105
-		$this->server->on('method:POST', [$this, 'httpPost']);
106
-		$this->server->on('propFind',    [$this, 'propFind']);
107
-	}
108
-
109
-	/**
110
-	 * We intercept this to handle POST requests on a dav resource.
111
-	 *
112
-	 * @param RequestInterface $request
113
-	 * @param ResponseInterface $response
114
-	 * @return null|false
115
-	 */
116
-	function httpPost(RequestInterface $request, ResponseInterface $response) {
117
-
118
-		$path = $request->getPath();
119
-
120
-		// Only handling xml
121
-		$contentType = $request->getHeader('Content-Type');
122
-		if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false)
123
-			return;
124
-
125
-		// Making sure the node exists
126
-		try {
127
-			$node = $this->server->tree->getNodeForPath($path);
128
-		} catch (NotFound $e) {
129
-			return;
130
-		}
131
-
132
-		$requestBody = $request->getBodyAsString();
133
-
134
-		// If this request handler could not deal with this POST request, it
135
-		// will return 'null' and other plugins get a chance to handle the
136
-		// request.
137
-		//
138
-		// However, we already requested the full body. This is a problem,
139
-		// because a body can only be read once. This is why we preemptively
140
-		// re-populated the request body with the existing data.
141
-		$request->setBody($requestBody);
142
-
143
-		$message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
144
-
145
-		switch ($documentType) {
146
-
147
-			// Dealing with the 'share' document, which modified invitees on a
148
-			// calendar.
149
-			case '{' . self::NS_OWNCLOUD . '}share' :
150
-
151
-				// We can only deal with IShareableCalendar objects
152
-				if (!$node instanceof IShareable) {
153
-					return;
154
-				}
155
-
156
-				$this->server->transactionType = 'post-oc-resource-share';
157
-
158
-				// Getting ACL info
159
-				$acl = $this->server->getPlugin('acl');
160
-
161
-				// If there's no ACL support, we allow everything
162
-				if ($acl) {
163
-					/** @var \Sabre\DAVACL\Plugin $acl */
164
-					$acl->checkPrivileges($path, '{DAV:}write');
165
-				}
166
-
167
-				$node->updateShares($message->set, $message->remove);
168
-
169
-				$response->setStatus(200);
170
-				// Adding this because sending a response body may cause issues,
171
-				// and I wanted some type of indicator the response was handled.
172
-				$response->setHeader('X-Sabre-Status', 'everything-went-well');
173
-
174
-				// Breaking the event chain
175
-				return false;
176
-		}
177
-	}
178
-
179
-	/**
180
-	 * This event is triggered when properties are requested for a certain
181
-	 * node.
182
-	 *
183
-	 * This allows us to inject any properties early.
184
-	 *
185
-	 * @param PropFind $propFind
186
-	 * @param INode $node
187
-	 * @return void
188
-	 */
189
-	function propFind(PropFind $propFind, INode $node) {
190
-		if ($node instanceof IShareable) {
191
-
192
-			$propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function() use ($node) {
193
-				return new Invite(
194
-					$node->getShares()
195
-				);
196
-			});
197
-
198
-		}
199
-	}
39
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
40
+
41
+    /** @var Auth */
42
+    private $auth;
43
+
44
+    /** @var IRequest */
45
+    private $request;
46
+
47
+    /**
48
+     * Plugin constructor.
49
+     *
50
+     * @param Auth $authBackEnd
51
+     * @param IRequest $request
52
+     */
53
+    public function __construct(Auth $authBackEnd, IRequest $request) {
54
+        $this->auth = $authBackEnd;
55
+        $this->request = $request;
56
+    }
57
+
58
+    /**
59
+     * Reference to SabreDAV server object.
60
+     *
61
+     * @var \Sabre\DAV\Server
62
+     */
63
+    protected $server;
64
+
65
+    /**
66
+     * This method should return a list of server-features.
67
+     *
68
+     * This is for example 'versioning' and is added to the DAV: header
69
+     * in an OPTIONS response.
70
+     *
71
+     * @return string[]
72
+     */
73
+    function getFeatures() {
74
+        return ['oc-resource-sharing'];
75
+    }
76
+
77
+    /**
78
+     * Returns a plugin name.
79
+     *
80
+     * Using this name other plugins will be able to access other plugins
81
+     * using Sabre\DAV\Server::getPlugin
82
+     *
83
+     * @return string
84
+     */
85
+    function getPluginName() {
86
+        return 'oc-resource-sharing';
87
+    }
88
+
89
+    /**
90
+     * This initializes the plugin.
91
+     *
92
+     * This function is called by Sabre\DAV\Server, after
93
+     * addPlugin is called.
94
+     *
95
+     * This method should set up the required event subscriptions.
96
+     *
97
+     * @param Server $server
98
+     * @return void
99
+     */
100
+    function initialize(Server $server) {
101
+        $this->server = $server;
102
+        $this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}share'] = 'OCA\\DAV\\DAV\\Sharing\\Xml\\ShareRequest';
103
+        $this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}invite'] = 'OCA\\DAV\\DAV\\Sharing\\Xml\\Invite';
104
+
105
+        $this->server->on('method:POST', [$this, 'httpPost']);
106
+        $this->server->on('propFind',    [$this, 'propFind']);
107
+    }
108
+
109
+    /**
110
+     * We intercept this to handle POST requests on a dav resource.
111
+     *
112
+     * @param RequestInterface $request
113
+     * @param ResponseInterface $response
114
+     * @return null|false
115
+     */
116
+    function httpPost(RequestInterface $request, ResponseInterface $response) {
117
+
118
+        $path = $request->getPath();
119
+
120
+        // Only handling xml
121
+        $contentType = $request->getHeader('Content-Type');
122
+        if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false)
123
+            return;
124
+
125
+        // Making sure the node exists
126
+        try {
127
+            $node = $this->server->tree->getNodeForPath($path);
128
+        } catch (NotFound $e) {
129
+            return;
130
+        }
131
+
132
+        $requestBody = $request->getBodyAsString();
133
+
134
+        // If this request handler could not deal with this POST request, it
135
+        // will return 'null' and other plugins get a chance to handle the
136
+        // request.
137
+        //
138
+        // However, we already requested the full body. This is a problem,
139
+        // because a body can only be read once. This is why we preemptively
140
+        // re-populated the request body with the existing data.
141
+        $request->setBody($requestBody);
142
+
143
+        $message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
144
+
145
+        switch ($documentType) {
146
+
147
+            // Dealing with the 'share' document, which modified invitees on a
148
+            // calendar.
149
+            case '{' . self::NS_OWNCLOUD . '}share' :
150
+
151
+                // We can only deal with IShareableCalendar objects
152
+                if (!$node instanceof IShareable) {
153
+                    return;
154
+                }
155
+
156
+                $this->server->transactionType = 'post-oc-resource-share';
157
+
158
+                // Getting ACL info
159
+                $acl = $this->server->getPlugin('acl');
160
+
161
+                // If there's no ACL support, we allow everything
162
+                if ($acl) {
163
+                    /** @var \Sabre\DAVACL\Plugin $acl */
164
+                    $acl->checkPrivileges($path, '{DAV:}write');
165
+                }
166
+
167
+                $node->updateShares($message->set, $message->remove);
168
+
169
+                $response->setStatus(200);
170
+                // Adding this because sending a response body may cause issues,
171
+                // and I wanted some type of indicator the response was handled.
172
+                $response->setHeader('X-Sabre-Status', 'everything-went-well');
173
+
174
+                // Breaking the event chain
175
+                return false;
176
+        }
177
+    }
178
+
179
+    /**
180
+     * This event is triggered when properties are requested for a certain
181
+     * node.
182
+     *
183
+     * This allows us to inject any properties early.
184
+     *
185
+     * @param PropFind $propFind
186
+     * @param INode $node
187
+     * @return void
188
+     */
189
+    function propFind(PropFind $propFind, INode $node) {
190
+        if ($node instanceof IShareable) {
191
+
192
+            $propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function() use ($node) {
193
+                return new Invite(
194
+                    $node->getShares()
195
+                );
196
+            });
197
+
198
+        }
199
+    }
200 200
 
201 201
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -99,11 +99,11 @@  discard block
 block discarded – undo
99 99
 	 */
100 100
 	function initialize(Server $server) {
101 101
 		$this->server = $server;
102
-		$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}share'] = 'OCA\\DAV\\DAV\\Sharing\\Xml\\ShareRequest';
103
-		$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}invite'] = 'OCA\\DAV\\DAV\\Sharing\\Xml\\Invite';
102
+		$this->server->xml->elementMap['{'.Plugin::NS_OWNCLOUD.'}share'] = 'OCA\\DAV\\DAV\\Sharing\\Xml\\ShareRequest';
103
+		$this->server->xml->elementMap['{'.Plugin::NS_OWNCLOUD.'}invite'] = 'OCA\\DAV\\DAV\\Sharing\\Xml\\Invite';
104 104
 
105 105
 		$this->server->on('method:POST', [$this, 'httpPost']);
106
-		$this->server->on('propFind',    [$this, 'propFind']);
106
+		$this->server->on('propFind', [$this, 'propFind']);
107 107
 	}
108 108
 
109 109
 	/**
@@ -146,7 +146,7 @@  discard block
 block discarded – undo
146 146
 
147 147
 			// Dealing with the 'share' document, which modified invitees on a
148 148
 			// calendar.
149
-			case '{' . self::NS_OWNCLOUD . '}share' :
149
+			case '{'.self::NS_OWNCLOUD.'}share' :
150 150
 
151 151
 				// We can only deal with IShareableCalendar objects
152 152
 				if (!$node instanceof IShareable) {
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
 	function propFind(PropFind $propFind, INode $node) {
190 190
 		if ($node instanceof IShareable) {
191 191
 
192
-			$propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function() use ($node) {
192
+			$propFind->handle('{'.Plugin::NS_OWNCLOUD.'}invite', function() use ($node) {
193 193
 				return new Invite(
194 194
 					$node->getShares()
195 195
 				);
Please login to merge, or discard this patch.
Braces   +3 added lines, -2 removed lines patch added patch discarded remove patch
@@ -119,8 +119,9 @@
 block discarded – undo
119 119
 
120 120
 		// Only handling xml
121 121
 		$contentType = $request->getHeader('Content-Type');
122
-		if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false)
123
-			return;
122
+		if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) {
123
+					return;
124
+		}
124 125
 
125 126
 		// Making sure the node exists
126 127
 		try {
Please login to merge, or discard this patch.
apps/dav/lib/DAV/SystemPrincipalBackend.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -132,7 +132,7 @@
 block discarded – undo
132 132
 	 * Returns the list of members for a group-principal
133 133
 	 *
134 134
 	 * @param string $principal
135
-	 * @return array
135
+	 * @return string[]
136 136
 	 */
137 137
 	function getGroupMemberSet($principal) {
138 138
 		// TODO: for now the group principal has only one member, the user itself
Please login to merge, or discard this patch.
Indentation   +150 added lines, -150 removed lines patch added patch discarded remove patch
@@ -27,154 +27,154 @@
 block discarded – undo
27 27
 
28 28
 class SystemPrincipalBackend extends AbstractBackend {
29 29
 
30
-	/**
31
-	 * Returns a list of principals based on a prefix.
32
-	 *
33
-	 * This prefix will often contain something like 'principals'. You are only
34
-	 * expected to return principals that are in this base path.
35
-	 *
36
-	 * You are expected to return at least a 'uri' for every user, you can
37
-	 * return any additional properties if you wish so. Common properties are:
38
-	 *   {DAV:}displayname
39
-	 *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV
40
-	 *     field that's actually injected in a number of other properties. If
41
-	 *     you have an email address, use this property.
42
-	 *
43
-	 * @param string $prefixPath
44
-	 * @return array
45
-	 */
46
-	function getPrincipalsByPrefix($prefixPath) {
47
-		$principals = [];
48
-
49
-		if ($prefixPath === 'principals/system') {
50
-			$principals[] = [
51
-				'uri' => 'principals/system/system',
52
-				'{DAV:}displayname' => 'system',
53
-			];
54
-		}
55
-
56
-		return $principals;
57
-	}
58
-
59
-	/**
60
-	 * Returns a specific principal, specified by it's path.
61
-	 * The returned structure should be the exact same as from
62
-	 * getPrincipalsByPrefix.
63
-	 *
64
-	 * @param string $path
65
-	 * @return array
66
-	 */
67
-	function getPrincipalByPath($path) {
68
-
69
-		if ($path === 'principals/system/system') {
70
-			$principal = [
71
-				'uri' => 'principals/system/system',
72
-				'{DAV:}displayname' => 'system',
73
-			];
74
-			return $principal;
75
-		}
76
-
77
-		return null;
78
-	}
79
-
80
-	/**
81
-	 * Updates one ore more webdav properties on a principal.
82
-	 *
83
-	 * The list of mutations is stored in a Sabre\DAV\PropPatch object.
84
-	 * To do the actual updates, you must tell this object which properties
85
-	 * you're going to process with the handle() method.
86
-	 *
87
-	 * Calling the handle method is like telling the PropPatch object "I
88
-	 * promise I can handle updating this property".
89
-	 *
90
-	 * Read the PropPatch documentation for more info and examples.
91
-	 *
92
-	 * @param string $path
93
-	 * @param \Sabre\DAV\PropPatch $propPatch
94
-	 * @return void
95
-	 */
96
-	function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch) {
97
-	}
98
-
99
-	/**
100
-	 * This method is used to search for principals matching a set of
101
-	 * properties.
102
-	 *
103
-	 * This search is specifically used by RFC3744's principal-property-search
104
-	 * REPORT.
105
-	 *
106
-	 * The actual search should be a unicode-non-case-sensitive search. The
107
-	 * keys in searchProperties are the WebDAV property names, while the values
108
-	 * are the property values to search on.
109
-	 *
110
-	 * By default, if multiple properties are submitted to this method, the
111
-	 * various properties should be combined with 'AND'. If $test is set to
112
-	 * 'anyof', it should be combined using 'OR'.
113
-	 *
114
-	 * This method should simply return an array with full principal uri's.
115
-	 *
116
-	 * If somebody attempted to search on a property the backend does not
117
-	 * support, you should simply return 0 results.
118
-	 *
119
-	 * You can also just return 0 results if you choose to not support
120
-	 * searching at all, but keep in mind that this may stop certain features
121
-	 * from working.
122
-	 *
123
-	 * @param string $prefixPath
124
-	 * @param array $searchProperties
125
-	 * @param string $test
126
-	 * @return array
127
-	 */
128
-	function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
129
-		return [];
130
-	}
131
-
132
-	/**
133
-	 * Returns the list of members for a group-principal
134
-	 *
135
-	 * @param string $principal
136
-	 * @return array
137
-	 */
138
-	function getGroupMemberSet($principal) {
139
-		// TODO: for now the group principal has only one member, the user itself
140
-		$principal = $this->getPrincipalByPath($principal);
141
-		if (!$principal) {
142
-			throw new \Sabre\DAV\Exception('Principal not found');
143
-		}
144
-
145
-		return [$principal['uri']];
146
-	}
147
-
148
-	/**
149
-	 * Returns the list of groups a principal is a member of
150
-	 *
151
-	 * @param string $principal
152
-	 * @return array
153
-	 */
154
-	function getGroupMembership($principal) {
155
-		list($prefix, $name) = URLUtil::splitPath($principal);
156
-
157
-		if ($prefix === 'principals/system') {
158
-			$principal = $this->getPrincipalByPath($principal);
159
-			if (!$principal) {
160
-				throw new \Sabre\DAV\Exception('Principal not found');
161
-			}
162
-
163
-			return [];
164
-		}
165
-		return [];
166
-	}
167
-
168
-	/**
169
-	 * Updates the list of group members for a group principal.
170
-	 *
171
-	 * The principals should be passed as a list of uri's.
172
-	 *
173
-	 * @param string $principal
174
-	 * @param array $members
175
-	 * @return void
176
-	 */
177
-	function setGroupMemberSet($principal, array $members) {
178
-		throw new \Sabre\DAV\Exception('Setting members of the group is not supported yet');
179
-	}
30
+    /**
31
+     * Returns a list of principals based on a prefix.
32
+     *
33
+     * This prefix will often contain something like 'principals'. You are only
34
+     * expected to return principals that are in this base path.
35
+     *
36
+     * You are expected to return at least a 'uri' for every user, you can
37
+     * return any additional properties if you wish so. Common properties are:
38
+     *   {DAV:}displayname
39
+     *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV
40
+     *     field that's actually injected in a number of other properties. If
41
+     *     you have an email address, use this property.
42
+     *
43
+     * @param string $prefixPath
44
+     * @return array
45
+     */
46
+    function getPrincipalsByPrefix($prefixPath) {
47
+        $principals = [];
48
+
49
+        if ($prefixPath === 'principals/system') {
50
+            $principals[] = [
51
+                'uri' => 'principals/system/system',
52
+                '{DAV:}displayname' => 'system',
53
+            ];
54
+        }
55
+
56
+        return $principals;
57
+    }
58
+
59
+    /**
60
+     * Returns a specific principal, specified by it's path.
61
+     * The returned structure should be the exact same as from
62
+     * getPrincipalsByPrefix.
63
+     *
64
+     * @param string $path
65
+     * @return array
66
+     */
67
+    function getPrincipalByPath($path) {
68
+
69
+        if ($path === 'principals/system/system') {
70
+            $principal = [
71
+                'uri' => 'principals/system/system',
72
+                '{DAV:}displayname' => 'system',
73
+            ];
74
+            return $principal;
75
+        }
76
+
77
+        return null;
78
+    }
79
+
80
+    /**
81
+     * Updates one ore more webdav properties on a principal.
82
+     *
83
+     * The list of mutations is stored in a Sabre\DAV\PropPatch object.
84
+     * To do the actual updates, you must tell this object which properties
85
+     * you're going to process with the handle() method.
86
+     *
87
+     * Calling the handle method is like telling the PropPatch object "I
88
+     * promise I can handle updating this property".
89
+     *
90
+     * Read the PropPatch documentation for more info and examples.
91
+     *
92
+     * @param string $path
93
+     * @param \Sabre\DAV\PropPatch $propPatch
94
+     * @return void
95
+     */
96
+    function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch) {
97
+    }
98
+
99
+    /**
100
+     * This method is used to search for principals matching a set of
101
+     * properties.
102
+     *
103
+     * This search is specifically used by RFC3744's principal-property-search
104
+     * REPORT.
105
+     *
106
+     * The actual search should be a unicode-non-case-sensitive search. The
107
+     * keys in searchProperties are the WebDAV property names, while the values
108
+     * are the property values to search on.
109
+     *
110
+     * By default, if multiple properties are submitted to this method, the
111
+     * various properties should be combined with 'AND'. If $test is set to
112
+     * 'anyof', it should be combined using 'OR'.
113
+     *
114
+     * This method should simply return an array with full principal uri's.
115
+     *
116
+     * If somebody attempted to search on a property the backend does not
117
+     * support, you should simply return 0 results.
118
+     *
119
+     * You can also just return 0 results if you choose to not support
120
+     * searching at all, but keep in mind that this may stop certain features
121
+     * from working.
122
+     *
123
+     * @param string $prefixPath
124
+     * @param array $searchProperties
125
+     * @param string $test
126
+     * @return array
127
+     */
128
+    function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
129
+        return [];
130
+    }
131
+
132
+    /**
133
+     * Returns the list of members for a group-principal
134
+     *
135
+     * @param string $principal
136
+     * @return array
137
+     */
138
+    function getGroupMemberSet($principal) {
139
+        // TODO: for now the group principal has only one member, the user itself
140
+        $principal = $this->getPrincipalByPath($principal);
141
+        if (!$principal) {
142
+            throw new \Sabre\DAV\Exception('Principal not found');
143
+        }
144
+
145
+        return [$principal['uri']];
146
+    }
147
+
148
+    /**
149
+     * Returns the list of groups a principal is a member of
150
+     *
151
+     * @param string $principal
152
+     * @return array
153
+     */
154
+    function getGroupMembership($principal) {
155
+        list($prefix, $name) = URLUtil::splitPath($principal);
156
+
157
+        if ($prefix === 'principals/system') {
158
+            $principal = $this->getPrincipalByPath($principal);
159
+            if (!$principal) {
160
+                throw new \Sabre\DAV\Exception('Principal not found');
161
+            }
162
+
163
+            return [];
164
+        }
165
+        return [];
166
+    }
167
+
168
+    /**
169
+     * Updates the list of group members for a group principal.
170
+     *
171
+     * The principals should be passed as a list of uri's.
172
+     *
173
+     * @param string $principal
174
+     * @param array $members
175
+     * @return void
176
+     */
177
+    function setGroupMemberSet($principal, array $members) {
178
+        throw new \Sabre\DAV\Exception('Setting members of the group is not supported yet');
179
+    }
180 180
 }
Please login to merge, or discard this patch.