Passed
Push — master ( cb2b38...37146c )
by Roeland
12:06 queued 11s
created
lib/private/Files/Storage/Wrapper/Encoding.php 2 patches
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
 				// no point in continuing if the section was not found, use original path
81 81
 				return $fullPath;
82 82
 			}
83
-			$path = $convertedPath . '/';
83
+			$path = $convertedPath.'/';
84 84
 		}
85 85
 		$path = rtrim($path, '/');
86 86
 		return $path;
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
 	 * @return string|null original or converted path, or null if none of the forms was found
97 97
 	 */
98 98
 	private function findPathToUseLastSection($basePath, $lastSection) {
99
-		$fullPath = $basePath . $lastSection;
99
+		$fullPath = $basePath.$lastSection;
100 100
 		if ($lastSection === '' || $this->isAscii($lastSection) || $this->storage->file_exists($fullPath)) {
101 101
 			$this->namesCache[$fullPath] = $fullPath;
102 102
 			return $fullPath;
@@ -108,7 +108,7 @@  discard block
 block discarded – undo
108 108
 		} else {
109 109
 			$otherFormPath = \Normalizer::normalize($lastSection, \Normalizer::FORM_C);
110 110
 		}
111
-		$otherFullPath = $basePath . $otherFormPath;
111
+		$otherFullPath = $basePath.$otherFormPath;
112 112
 		if ($this->storage->file_exists($otherFullPath)) {
113 113
 			$this->namesCache[$fullPath] = $otherFullPath;
114 114
 			return $otherFullPath;
Please login to merge, or discard this patch.
Indentation   +498 added lines, -498 removed lines patch added patch discarded remove patch
@@ -34,502 +34,502 @@
 block discarded – undo
34 34
  */
35 35
 class Encoding extends Wrapper {
36 36
 
37
-	/**
38
-	 * @var ICache
39
-	 */
40
-	private $namesCache;
41
-
42
-	/**
43
-	 * @param array $parameters
44
-	 */
45
-	public function __construct($parameters) {
46
-		$this->storage = $parameters['storage'];
47
-		$this->namesCache = new CappedMemoryCache();
48
-	}
49
-
50
-	/**
51
-	 * Returns whether the given string is only made of ASCII characters
52
-	 *
53
-	 * @param string $str string
54
-	 *
55
-	 * @return bool true if the string is all ASCII, false otherwise
56
-	 */
57
-	private function isAscii($str) {
58
-		return (bool) !preg_match('/[\\x80-\\xff]+/', $str);
59
-	}
60
-
61
-	/**
62
-	 * Checks whether the given path exists in NFC or NFD form after checking
63
-	 * each form for each path section and returns the correct form.
64
-	 * If no existing path found, returns the path as it was given.
65
-	 *
66
-	 * @param string $fullPath path to check
67
-	 *
68
-	 * @return string original or converted path
69
-	 */
70
-	private function findPathToUse($fullPath) {
71
-		$cachedPath = $this->namesCache[$fullPath];
72
-		if ($cachedPath !== null) {
73
-			return $cachedPath;
74
-		}
75
-
76
-		$sections = explode('/', $fullPath);
77
-		$path = '';
78
-		foreach ($sections as $section) {
79
-			$convertedPath = $this->findPathToUseLastSection($path, $section);
80
-			if ($convertedPath === null) {
81
-				// no point in continuing if the section was not found, use original path
82
-				return $fullPath;
83
-			}
84
-			$path = $convertedPath . '/';
85
-		}
86
-		$path = rtrim($path, '/');
87
-		return $path;
88
-	}
89
-
90
-	/**
91
-	 * Checks whether the last path section of the given path exists in NFC or NFD form
92
-	 * and returns the correct form. If no existing path found, returns null.
93
-	 *
94
-	 * @param string $basePath base path to check
95
-	 * @param string $lastSection last section of the path to check for NFD/NFC variations
96
-	 *
97
-	 * @return string|null original or converted path, or null if none of the forms was found
98
-	 */
99
-	private function findPathToUseLastSection($basePath, $lastSection) {
100
-		$fullPath = $basePath . $lastSection;
101
-		if ($lastSection === '' || $this->isAscii($lastSection) || $this->storage->file_exists($fullPath)) {
102
-			$this->namesCache[$fullPath] = $fullPath;
103
-			return $fullPath;
104
-		}
105
-
106
-		// swap encoding
107
-		if (\Normalizer::isNormalized($lastSection, \Normalizer::FORM_C)) {
108
-			$otherFormPath = \Normalizer::normalize($lastSection, \Normalizer::FORM_D);
109
-		} else {
110
-			$otherFormPath = \Normalizer::normalize($lastSection, \Normalizer::FORM_C);
111
-		}
112
-		$otherFullPath = $basePath . $otherFormPath;
113
-		if ($this->storage->file_exists($otherFullPath)) {
114
-			$this->namesCache[$fullPath] = $otherFullPath;
115
-			return $otherFullPath;
116
-		}
117
-
118
-		// return original path, file did not exist at all
119
-		$this->namesCache[$fullPath] = $fullPath;
120
-		return null;
121
-	}
122
-
123
-	/**
124
-	 * see http://php.net/manual/en/function.mkdir.php
125
-	 *
126
-	 * @param string $path
127
-	 * @return bool
128
-	 */
129
-	public function mkdir($path) {
130
-		// note: no conversion here, method should not be called with non-NFC names!
131
-		$result = $this->storage->mkdir($path);
132
-		if ($result) {
133
-			$this->namesCache[$path] = $path;
134
-		}
135
-		return $result;
136
-	}
137
-
138
-	/**
139
-	 * see http://php.net/manual/en/function.rmdir.php
140
-	 *
141
-	 * @param string $path
142
-	 * @return bool
143
-	 */
144
-	public function rmdir($path) {
145
-		$result = $this->storage->rmdir($this->findPathToUse($path));
146
-		if ($result) {
147
-			unset($this->namesCache[$path]);
148
-		}
149
-		return $result;
150
-	}
151
-
152
-	/**
153
-	 * see http://php.net/manual/en/function.opendir.php
154
-	 *
155
-	 * @param string $path
156
-	 * @return resource
157
-	 */
158
-	public function opendir($path) {
159
-		return $this->storage->opendir($this->findPathToUse($path));
160
-	}
161
-
162
-	/**
163
-	 * see http://php.net/manual/en/function.is_dir.php
164
-	 *
165
-	 * @param string $path
166
-	 * @return bool
167
-	 */
168
-	public function is_dir($path) {
169
-		return $this->storage->is_dir($this->findPathToUse($path));
170
-	}
171
-
172
-	/**
173
-	 * see http://php.net/manual/en/function.is_file.php
174
-	 *
175
-	 * @param string $path
176
-	 * @return bool
177
-	 */
178
-	public function is_file($path) {
179
-		return $this->storage->is_file($this->findPathToUse($path));
180
-	}
181
-
182
-	/**
183
-	 * see http://php.net/manual/en/function.stat.php
184
-	 * only the following keys are required in the result: size and mtime
185
-	 *
186
-	 * @param string $path
187
-	 * @return array
188
-	 */
189
-	public function stat($path) {
190
-		return $this->storage->stat($this->findPathToUse($path));
191
-	}
192
-
193
-	/**
194
-	 * see http://php.net/manual/en/function.filetype.php
195
-	 *
196
-	 * @param string $path
197
-	 * @return bool
198
-	 */
199
-	public function filetype($path) {
200
-		return $this->storage->filetype($this->findPathToUse($path));
201
-	}
202
-
203
-	/**
204
-	 * see http://php.net/manual/en/function.filesize.php
205
-	 * The result for filesize when called on a folder is required to be 0
206
-	 *
207
-	 * @param string $path
208
-	 * @return int
209
-	 */
210
-	public function filesize($path) {
211
-		return $this->storage->filesize($this->findPathToUse($path));
212
-	}
213
-
214
-	/**
215
-	 * check if a file can be created in $path
216
-	 *
217
-	 * @param string $path
218
-	 * @return bool
219
-	 */
220
-	public function isCreatable($path) {
221
-		return $this->storage->isCreatable($this->findPathToUse($path));
222
-	}
223
-
224
-	/**
225
-	 * check if a file can be read
226
-	 *
227
-	 * @param string $path
228
-	 * @return bool
229
-	 */
230
-	public function isReadable($path) {
231
-		return $this->storage->isReadable($this->findPathToUse($path));
232
-	}
233
-
234
-	/**
235
-	 * check if a file can be written to
236
-	 *
237
-	 * @param string $path
238
-	 * @return bool
239
-	 */
240
-	public function isUpdatable($path) {
241
-		return $this->storage->isUpdatable($this->findPathToUse($path));
242
-	}
243
-
244
-	/**
245
-	 * check if a file can be deleted
246
-	 *
247
-	 * @param string $path
248
-	 * @return bool
249
-	 */
250
-	public function isDeletable($path) {
251
-		return $this->storage->isDeletable($this->findPathToUse($path));
252
-	}
253
-
254
-	/**
255
-	 * check if a file can be shared
256
-	 *
257
-	 * @param string $path
258
-	 * @return bool
259
-	 */
260
-	public function isSharable($path) {
261
-		return $this->storage->isSharable($this->findPathToUse($path));
262
-	}
263
-
264
-	/**
265
-	 * get the full permissions of a path.
266
-	 * Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php
267
-	 *
268
-	 * @param string $path
269
-	 * @return int
270
-	 */
271
-	public function getPermissions($path) {
272
-		return $this->storage->getPermissions($this->findPathToUse($path));
273
-	}
274
-
275
-	/**
276
-	 * see http://php.net/manual/en/function.file_exists.php
277
-	 *
278
-	 * @param string $path
279
-	 * @return bool
280
-	 */
281
-	public function file_exists($path) {
282
-		return $this->storage->file_exists($this->findPathToUse($path));
283
-	}
284
-
285
-	/**
286
-	 * see http://php.net/manual/en/function.filemtime.php
287
-	 *
288
-	 * @param string $path
289
-	 * @return int
290
-	 */
291
-	public function filemtime($path) {
292
-		return $this->storage->filemtime($this->findPathToUse($path));
293
-	}
294
-
295
-	/**
296
-	 * see http://php.net/manual/en/function.file_get_contents.php
297
-	 *
298
-	 * @param string $path
299
-	 * @return string
300
-	 */
301
-	public function file_get_contents($path) {
302
-		return $this->storage->file_get_contents($this->findPathToUse($path));
303
-	}
304
-
305
-	/**
306
-	 * see http://php.net/manual/en/function.file_put_contents.php
307
-	 *
308
-	 * @param string $path
309
-	 * @param string $data
310
-	 * @return bool
311
-	 */
312
-	public function file_put_contents($path, $data) {
313
-		return $this->storage->file_put_contents($this->findPathToUse($path), $data);
314
-	}
315
-
316
-	/**
317
-	 * see http://php.net/manual/en/function.unlink.php
318
-	 *
319
-	 * @param string $path
320
-	 * @return bool
321
-	 */
322
-	public function unlink($path) {
323
-		$result = $this->storage->unlink($this->findPathToUse($path));
324
-		if ($result) {
325
-			unset($this->namesCache[$path]);
326
-		}
327
-		return $result;
328
-	}
329
-
330
-	/**
331
-	 * see http://php.net/manual/en/function.rename.php
332
-	 *
333
-	 * @param string $path1
334
-	 * @param string $path2
335
-	 * @return bool
336
-	 */
337
-	public function rename($path1, $path2) {
338
-		// second name always NFC
339
-		return $this->storage->rename($this->findPathToUse($path1), $this->findPathToUse($path2));
340
-	}
341
-
342
-	/**
343
-	 * see http://php.net/manual/en/function.copy.php
344
-	 *
345
-	 * @param string $path1
346
-	 * @param string $path2
347
-	 * @return bool
348
-	 */
349
-	public function copy($path1, $path2) {
350
-		return $this->storage->copy($this->findPathToUse($path1), $this->findPathToUse($path2));
351
-	}
352
-
353
-	/**
354
-	 * see http://php.net/manual/en/function.fopen.php
355
-	 *
356
-	 * @param string $path
357
-	 * @param string $mode
358
-	 * @return resource
359
-	 */
360
-	public function fopen($path, $mode) {
361
-		$result = $this->storage->fopen($this->findPathToUse($path), $mode);
362
-		if ($result && $mode !== 'r' && $mode !== 'rb') {
363
-			unset($this->namesCache[$path]);
364
-		}
365
-		return $result;
366
-	}
367
-
368
-	/**
369
-	 * get the mimetype for a file or folder
370
-	 * The mimetype for a folder is required to be "httpd/unix-directory"
371
-	 *
372
-	 * @param string $path
373
-	 * @return string
374
-	 */
375
-	public function getMimeType($path) {
376
-		return $this->storage->getMimeType($this->findPathToUse($path));
377
-	}
378
-
379
-	/**
380
-	 * see http://php.net/manual/en/function.hash.php
381
-	 *
382
-	 * @param string $type
383
-	 * @param string $path
384
-	 * @param bool $raw
385
-	 * @return string
386
-	 */
387
-	public function hash($type, $path, $raw = false) {
388
-		return $this->storage->hash($type, $this->findPathToUse($path), $raw);
389
-	}
390
-
391
-	/**
392
-	 * see http://php.net/manual/en/function.free_space.php
393
-	 *
394
-	 * @param string $path
395
-	 * @return int
396
-	 */
397
-	public function free_space($path) {
398
-		return $this->storage->free_space($this->findPathToUse($path));
399
-	}
400
-
401
-	/**
402
-	 * search for occurrences of $query in file names
403
-	 *
404
-	 * @param string $query
405
-	 * @return array
406
-	 */
407
-	public function search($query) {
408
-		return $this->storage->search($query);
409
-	}
410
-
411
-	/**
412
-	 * see http://php.net/manual/en/function.touch.php
413
-	 * If the backend does not support the operation, false should be returned
414
-	 *
415
-	 * @param string $path
416
-	 * @param int $mtime
417
-	 * @return bool
418
-	 */
419
-	public function touch($path, $mtime = null) {
420
-		return $this->storage->touch($this->findPathToUse($path), $mtime);
421
-	}
422
-
423
-	/**
424
-	 * get the path to a local version of the file.
425
-	 * The local version of the file can be temporary and doesn't have to be persistent across requests
426
-	 *
427
-	 * @param string $path
428
-	 * @return string
429
-	 */
430
-	public function getLocalFile($path) {
431
-		return $this->storage->getLocalFile($this->findPathToUse($path));
432
-	}
433
-
434
-	/**
435
-	 * check if a file or folder has been updated since $time
436
-	 *
437
-	 * @param string $path
438
-	 * @param int $time
439
-	 * @return bool
440
-	 *
441
-	 * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed.
442
-	 * returning true for other changes in the folder is optional
443
-	 */
444
-	public function hasUpdated($path, $time) {
445
-		return $this->storage->hasUpdated($this->findPathToUse($path), $time);
446
-	}
447
-
448
-	/**
449
-	 * get a cache instance for the storage
450
-	 *
451
-	 * @param string $path
452
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache
453
-	 * @return \OC\Files\Cache\Cache
454
-	 */
455
-	public function getCache($path = '', $storage = null) {
456
-		if (!$storage) {
457
-			$storage = $this;
458
-		}
459
-		return $this->storage->getCache($this->findPathToUse($path), $storage);
460
-	}
461
-
462
-	/**
463
-	 * get a scanner instance for the storage
464
-	 *
465
-	 * @param string $path
466
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
467
-	 * @return \OC\Files\Cache\Scanner
468
-	 */
469
-	public function getScanner($path = '', $storage = null) {
470
-		if (!$storage) {
471
-			$storage = $this;
472
-		}
473
-		return $this->storage->getScanner($this->findPathToUse($path), $storage);
474
-	}
475
-
476
-	/**
477
-	 * get the ETag for a file or folder
478
-	 *
479
-	 * @param string $path
480
-	 * @return string
481
-	 */
482
-	public function getETag($path) {
483
-		return $this->storage->getETag($this->findPathToUse($path));
484
-	}
485
-
486
-	/**
487
-	 * @param IStorage $sourceStorage
488
-	 * @param string $sourceInternalPath
489
-	 * @param string $targetInternalPath
490
-	 * @return bool
491
-	 */
492
-	public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
493
-		if ($sourceStorage === $this) {
494
-			return $this->copy($sourceInternalPath, $this->findPathToUse($targetInternalPath));
495
-		}
496
-
497
-		$result = $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $this->findPathToUse($targetInternalPath));
498
-		if ($result) {
499
-			unset($this->namesCache[$targetInternalPath]);
500
-		}
501
-		return $result;
502
-	}
503
-
504
-	/**
505
-	 * @param IStorage $sourceStorage
506
-	 * @param string $sourceInternalPath
507
-	 * @param string $targetInternalPath
508
-	 * @return bool
509
-	 */
510
-	public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
511
-		if ($sourceStorage === $this) {
512
-			$result = $this->rename($sourceInternalPath, $this->findPathToUse($targetInternalPath));
513
-			if ($result) {
514
-				unset($this->namesCache[$sourceInternalPath]);
515
-				unset($this->namesCache[$targetInternalPath]);
516
-			}
517
-			return $result;
518
-		}
519
-
520
-		$result = $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $this->findPathToUse($targetInternalPath));
521
-		if ($result) {
522
-			unset($this->namesCache[$sourceInternalPath]);
523
-			unset($this->namesCache[$targetInternalPath]);
524
-		}
525
-		return $result;
526
-	}
527
-
528
-	/**
529
-	 * @param string $path
530
-	 * @return array
531
-	 */
532
-	public function getMetaData($path) {
533
-		return $this->storage->getMetaData($this->findPathToUse($path));
534
-	}
37
+    /**
38
+     * @var ICache
39
+     */
40
+    private $namesCache;
41
+
42
+    /**
43
+     * @param array $parameters
44
+     */
45
+    public function __construct($parameters) {
46
+        $this->storage = $parameters['storage'];
47
+        $this->namesCache = new CappedMemoryCache();
48
+    }
49
+
50
+    /**
51
+     * Returns whether the given string is only made of ASCII characters
52
+     *
53
+     * @param string $str string
54
+     *
55
+     * @return bool true if the string is all ASCII, false otherwise
56
+     */
57
+    private function isAscii($str) {
58
+        return (bool) !preg_match('/[\\x80-\\xff]+/', $str);
59
+    }
60
+
61
+    /**
62
+     * Checks whether the given path exists in NFC or NFD form after checking
63
+     * each form for each path section and returns the correct form.
64
+     * If no existing path found, returns the path as it was given.
65
+     *
66
+     * @param string $fullPath path to check
67
+     *
68
+     * @return string original or converted path
69
+     */
70
+    private function findPathToUse($fullPath) {
71
+        $cachedPath = $this->namesCache[$fullPath];
72
+        if ($cachedPath !== null) {
73
+            return $cachedPath;
74
+        }
75
+
76
+        $sections = explode('/', $fullPath);
77
+        $path = '';
78
+        foreach ($sections as $section) {
79
+            $convertedPath = $this->findPathToUseLastSection($path, $section);
80
+            if ($convertedPath === null) {
81
+                // no point in continuing if the section was not found, use original path
82
+                return $fullPath;
83
+            }
84
+            $path = $convertedPath . '/';
85
+        }
86
+        $path = rtrim($path, '/');
87
+        return $path;
88
+    }
89
+
90
+    /**
91
+     * Checks whether the last path section of the given path exists in NFC or NFD form
92
+     * and returns the correct form. If no existing path found, returns null.
93
+     *
94
+     * @param string $basePath base path to check
95
+     * @param string $lastSection last section of the path to check for NFD/NFC variations
96
+     *
97
+     * @return string|null original or converted path, or null if none of the forms was found
98
+     */
99
+    private function findPathToUseLastSection($basePath, $lastSection) {
100
+        $fullPath = $basePath . $lastSection;
101
+        if ($lastSection === '' || $this->isAscii($lastSection) || $this->storage->file_exists($fullPath)) {
102
+            $this->namesCache[$fullPath] = $fullPath;
103
+            return $fullPath;
104
+        }
105
+
106
+        // swap encoding
107
+        if (\Normalizer::isNormalized($lastSection, \Normalizer::FORM_C)) {
108
+            $otherFormPath = \Normalizer::normalize($lastSection, \Normalizer::FORM_D);
109
+        } else {
110
+            $otherFormPath = \Normalizer::normalize($lastSection, \Normalizer::FORM_C);
111
+        }
112
+        $otherFullPath = $basePath . $otherFormPath;
113
+        if ($this->storage->file_exists($otherFullPath)) {
114
+            $this->namesCache[$fullPath] = $otherFullPath;
115
+            return $otherFullPath;
116
+        }
117
+
118
+        // return original path, file did not exist at all
119
+        $this->namesCache[$fullPath] = $fullPath;
120
+        return null;
121
+    }
122
+
123
+    /**
124
+     * see http://php.net/manual/en/function.mkdir.php
125
+     *
126
+     * @param string $path
127
+     * @return bool
128
+     */
129
+    public function mkdir($path) {
130
+        // note: no conversion here, method should not be called with non-NFC names!
131
+        $result = $this->storage->mkdir($path);
132
+        if ($result) {
133
+            $this->namesCache[$path] = $path;
134
+        }
135
+        return $result;
136
+    }
137
+
138
+    /**
139
+     * see http://php.net/manual/en/function.rmdir.php
140
+     *
141
+     * @param string $path
142
+     * @return bool
143
+     */
144
+    public function rmdir($path) {
145
+        $result = $this->storage->rmdir($this->findPathToUse($path));
146
+        if ($result) {
147
+            unset($this->namesCache[$path]);
148
+        }
149
+        return $result;
150
+    }
151
+
152
+    /**
153
+     * see http://php.net/manual/en/function.opendir.php
154
+     *
155
+     * @param string $path
156
+     * @return resource
157
+     */
158
+    public function opendir($path) {
159
+        return $this->storage->opendir($this->findPathToUse($path));
160
+    }
161
+
162
+    /**
163
+     * see http://php.net/manual/en/function.is_dir.php
164
+     *
165
+     * @param string $path
166
+     * @return bool
167
+     */
168
+    public function is_dir($path) {
169
+        return $this->storage->is_dir($this->findPathToUse($path));
170
+    }
171
+
172
+    /**
173
+     * see http://php.net/manual/en/function.is_file.php
174
+     *
175
+     * @param string $path
176
+     * @return bool
177
+     */
178
+    public function is_file($path) {
179
+        return $this->storage->is_file($this->findPathToUse($path));
180
+    }
181
+
182
+    /**
183
+     * see http://php.net/manual/en/function.stat.php
184
+     * only the following keys are required in the result: size and mtime
185
+     *
186
+     * @param string $path
187
+     * @return array
188
+     */
189
+    public function stat($path) {
190
+        return $this->storage->stat($this->findPathToUse($path));
191
+    }
192
+
193
+    /**
194
+     * see http://php.net/manual/en/function.filetype.php
195
+     *
196
+     * @param string $path
197
+     * @return bool
198
+     */
199
+    public function filetype($path) {
200
+        return $this->storage->filetype($this->findPathToUse($path));
201
+    }
202
+
203
+    /**
204
+     * see http://php.net/manual/en/function.filesize.php
205
+     * The result for filesize when called on a folder is required to be 0
206
+     *
207
+     * @param string $path
208
+     * @return int
209
+     */
210
+    public function filesize($path) {
211
+        return $this->storage->filesize($this->findPathToUse($path));
212
+    }
213
+
214
+    /**
215
+     * check if a file can be created in $path
216
+     *
217
+     * @param string $path
218
+     * @return bool
219
+     */
220
+    public function isCreatable($path) {
221
+        return $this->storage->isCreatable($this->findPathToUse($path));
222
+    }
223
+
224
+    /**
225
+     * check if a file can be read
226
+     *
227
+     * @param string $path
228
+     * @return bool
229
+     */
230
+    public function isReadable($path) {
231
+        return $this->storage->isReadable($this->findPathToUse($path));
232
+    }
233
+
234
+    /**
235
+     * check if a file can be written to
236
+     *
237
+     * @param string $path
238
+     * @return bool
239
+     */
240
+    public function isUpdatable($path) {
241
+        return $this->storage->isUpdatable($this->findPathToUse($path));
242
+    }
243
+
244
+    /**
245
+     * check if a file can be deleted
246
+     *
247
+     * @param string $path
248
+     * @return bool
249
+     */
250
+    public function isDeletable($path) {
251
+        return $this->storage->isDeletable($this->findPathToUse($path));
252
+    }
253
+
254
+    /**
255
+     * check if a file can be shared
256
+     *
257
+     * @param string $path
258
+     * @return bool
259
+     */
260
+    public function isSharable($path) {
261
+        return $this->storage->isSharable($this->findPathToUse($path));
262
+    }
263
+
264
+    /**
265
+     * get the full permissions of a path.
266
+     * Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php
267
+     *
268
+     * @param string $path
269
+     * @return int
270
+     */
271
+    public function getPermissions($path) {
272
+        return $this->storage->getPermissions($this->findPathToUse($path));
273
+    }
274
+
275
+    /**
276
+     * see http://php.net/manual/en/function.file_exists.php
277
+     *
278
+     * @param string $path
279
+     * @return bool
280
+     */
281
+    public function file_exists($path) {
282
+        return $this->storage->file_exists($this->findPathToUse($path));
283
+    }
284
+
285
+    /**
286
+     * see http://php.net/manual/en/function.filemtime.php
287
+     *
288
+     * @param string $path
289
+     * @return int
290
+     */
291
+    public function filemtime($path) {
292
+        return $this->storage->filemtime($this->findPathToUse($path));
293
+    }
294
+
295
+    /**
296
+     * see http://php.net/manual/en/function.file_get_contents.php
297
+     *
298
+     * @param string $path
299
+     * @return string
300
+     */
301
+    public function file_get_contents($path) {
302
+        return $this->storage->file_get_contents($this->findPathToUse($path));
303
+    }
304
+
305
+    /**
306
+     * see http://php.net/manual/en/function.file_put_contents.php
307
+     *
308
+     * @param string $path
309
+     * @param string $data
310
+     * @return bool
311
+     */
312
+    public function file_put_contents($path, $data) {
313
+        return $this->storage->file_put_contents($this->findPathToUse($path), $data);
314
+    }
315
+
316
+    /**
317
+     * see http://php.net/manual/en/function.unlink.php
318
+     *
319
+     * @param string $path
320
+     * @return bool
321
+     */
322
+    public function unlink($path) {
323
+        $result = $this->storage->unlink($this->findPathToUse($path));
324
+        if ($result) {
325
+            unset($this->namesCache[$path]);
326
+        }
327
+        return $result;
328
+    }
329
+
330
+    /**
331
+     * see http://php.net/manual/en/function.rename.php
332
+     *
333
+     * @param string $path1
334
+     * @param string $path2
335
+     * @return bool
336
+     */
337
+    public function rename($path1, $path2) {
338
+        // second name always NFC
339
+        return $this->storage->rename($this->findPathToUse($path1), $this->findPathToUse($path2));
340
+    }
341
+
342
+    /**
343
+     * see http://php.net/manual/en/function.copy.php
344
+     *
345
+     * @param string $path1
346
+     * @param string $path2
347
+     * @return bool
348
+     */
349
+    public function copy($path1, $path2) {
350
+        return $this->storage->copy($this->findPathToUse($path1), $this->findPathToUse($path2));
351
+    }
352
+
353
+    /**
354
+     * see http://php.net/manual/en/function.fopen.php
355
+     *
356
+     * @param string $path
357
+     * @param string $mode
358
+     * @return resource
359
+     */
360
+    public function fopen($path, $mode) {
361
+        $result = $this->storage->fopen($this->findPathToUse($path), $mode);
362
+        if ($result && $mode !== 'r' && $mode !== 'rb') {
363
+            unset($this->namesCache[$path]);
364
+        }
365
+        return $result;
366
+    }
367
+
368
+    /**
369
+     * get the mimetype for a file or folder
370
+     * The mimetype for a folder is required to be "httpd/unix-directory"
371
+     *
372
+     * @param string $path
373
+     * @return string
374
+     */
375
+    public function getMimeType($path) {
376
+        return $this->storage->getMimeType($this->findPathToUse($path));
377
+    }
378
+
379
+    /**
380
+     * see http://php.net/manual/en/function.hash.php
381
+     *
382
+     * @param string $type
383
+     * @param string $path
384
+     * @param bool $raw
385
+     * @return string
386
+     */
387
+    public function hash($type, $path, $raw = false) {
388
+        return $this->storage->hash($type, $this->findPathToUse($path), $raw);
389
+    }
390
+
391
+    /**
392
+     * see http://php.net/manual/en/function.free_space.php
393
+     *
394
+     * @param string $path
395
+     * @return int
396
+     */
397
+    public function free_space($path) {
398
+        return $this->storage->free_space($this->findPathToUse($path));
399
+    }
400
+
401
+    /**
402
+     * search for occurrences of $query in file names
403
+     *
404
+     * @param string $query
405
+     * @return array
406
+     */
407
+    public function search($query) {
408
+        return $this->storage->search($query);
409
+    }
410
+
411
+    /**
412
+     * see http://php.net/manual/en/function.touch.php
413
+     * If the backend does not support the operation, false should be returned
414
+     *
415
+     * @param string $path
416
+     * @param int $mtime
417
+     * @return bool
418
+     */
419
+    public function touch($path, $mtime = null) {
420
+        return $this->storage->touch($this->findPathToUse($path), $mtime);
421
+    }
422
+
423
+    /**
424
+     * get the path to a local version of the file.
425
+     * The local version of the file can be temporary and doesn't have to be persistent across requests
426
+     *
427
+     * @param string $path
428
+     * @return string
429
+     */
430
+    public function getLocalFile($path) {
431
+        return $this->storage->getLocalFile($this->findPathToUse($path));
432
+    }
433
+
434
+    /**
435
+     * check if a file or folder has been updated since $time
436
+     *
437
+     * @param string $path
438
+     * @param int $time
439
+     * @return bool
440
+     *
441
+     * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed.
442
+     * returning true for other changes in the folder is optional
443
+     */
444
+    public function hasUpdated($path, $time) {
445
+        return $this->storage->hasUpdated($this->findPathToUse($path), $time);
446
+    }
447
+
448
+    /**
449
+     * get a cache instance for the storage
450
+     *
451
+     * @param string $path
452
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache
453
+     * @return \OC\Files\Cache\Cache
454
+     */
455
+    public function getCache($path = '', $storage = null) {
456
+        if (!$storage) {
457
+            $storage = $this;
458
+        }
459
+        return $this->storage->getCache($this->findPathToUse($path), $storage);
460
+    }
461
+
462
+    /**
463
+     * get a scanner instance for the storage
464
+     *
465
+     * @param string $path
466
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
467
+     * @return \OC\Files\Cache\Scanner
468
+     */
469
+    public function getScanner($path = '', $storage = null) {
470
+        if (!$storage) {
471
+            $storage = $this;
472
+        }
473
+        return $this->storage->getScanner($this->findPathToUse($path), $storage);
474
+    }
475
+
476
+    /**
477
+     * get the ETag for a file or folder
478
+     *
479
+     * @param string $path
480
+     * @return string
481
+     */
482
+    public function getETag($path) {
483
+        return $this->storage->getETag($this->findPathToUse($path));
484
+    }
485
+
486
+    /**
487
+     * @param IStorage $sourceStorage
488
+     * @param string $sourceInternalPath
489
+     * @param string $targetInternalPath
490
+     * @return bool
491
+     */
492
+    public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
493
+        if ($sourceStorage === $this) {
494
+            return $this->copy($sourceInternalPath, $this->findPathToUse($targetInternalPath));
495
+        }
496
+
497
+        $result = $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $this->findPathToUse($targetInternalPath));
498
+        if ($result) {
499
+            unset($this->namesCache[$targetInternalPath]);
500
+        }
501
+        return $result;
502
+    }
503
+
504
+    /**
505
+     * @param IStorage $sourceStorage
506
+     * @param string $sourceInternalPath
507
+     * @param string $targetInternalPath
508
+     * @return bool
509
+     */
510
+    public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
511
+        if ($sourceStorage === $this) {
512
+            $result = $this->rename($sourceInternalPath, $this->findPathToUse($targetInternalPath));
513
+            if ($result) {
514
+                unset($this->namesCache[$sourceInternalPath]);
515
+                unset($this->namesCache[$targetInternalPath]);
516
+            }
517
+            return $result;
518
+        }
519
+
520
+        $result = $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $this->findPathToUse($targetInternalPath));
521
+        if ($result) {
522
+            unset($this->namesCache[$sourceInternalPath]);
523
+            unset($this->namesCache[$targetInternalPath]);
524
+        }
525
+        return $result;
526
+    }
527
+
528
+    /**
529
+     * @param string $path
530
+     * @return array
531
+     */
532
+    public function getMetaData($path) {
533
+        return $this->storage->getMetaData($this->findPathToUse($path));
534
+    }
535 535
 }
Please login to merge, or discard this patch.
lib/private/Files/Storage/DAV.php 3 patches
Braces   +5 added lines, -2 removed lines patch added patch discarded remove patch
@@ -90,8 +90,11 @@
 block discarded – undo
90 90
 		if (isset($params['host']) && isset($params['user']) && isset($params['password'])) {
91 91
 			$host = $params['host'];
92 92
 			//remove leading http[s], will be generated in createBaseUri()
93
-			if (substr($host, 0, 8) == "https://") $host = substr($host, 8);
94
-			else if (substr($host, 0, 7) == "http://") $host = substr($host, 7);
93
+			if (substr($host, 0, 8) == "https://") {
94
+			    $host = substr($host, 8);
95
+			} else if (substr($host, 0, 7) == "http://") {
96
+			    $host = substr($host, 7);
97
+			}
95 98
 			$this->host = $host;
96 99
 			$this->user = $params['user'];
97 100
 			$this->password = $params['password'];
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -107,7 +107,7 @@  discard block
 block discarded – undo
107 107
 				if (is_string($params['secure'])) {
108 108
 					$this->secure = ($params['secure'] === 'true');
109 109
 				} else {
110
-					$this->secure = (bool)$params['secure'];
110
+					$this->secure = (bool) $params['secure'];
111 111
 				}
112 112
 			} else {
113 113
 				$this->secure = false;
@@ -120,8 +120,8 @@  discard block
 block discarded – undo
120 120
 				}
121 121
 			}
122 122
 			$this->root = $params['root'] ?? '/';
123
-			$this->root = '/' . ltrim($this->root, '/');
124
-			$this->root = rtrim($this->root, '/') . '/';
123
+			$this->root = '/'.ltrim($this->root, '/');
124
+			$this->root = rtrim($this->root, '/').'/';
125 125
 		} else {
126 126
 			throw new \Exception('Invalid webdav storage configuration');
127 127
 		}
@@ -150,7 +150,7 @@  discard block
 block discarded – undo
150 150
 		$this->client = new Client($settings);
151 151
 		$this->client->setThrowExceptions(true);
152 152
 
153
-		if($this->secure === true) {
153
+		if ($this->secure === true) {
154 154
 			$certPath = $this->certManager->getAbsoluteBundlePath();
155 155
 			if (file_exists($certPath)) {
156 156
 				$this->certPath = $certPath;
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
 
171 171
 	/** {@inheritdoc} */
172 172
 	public function getId() {
173
-		return 'webdav::' . $this->user . '@' . $this->host . '/' . $this->root;
173
+		return 'webdav::'.$this->user.'@'.$this->host.'/'.$this->root;
174 174
 	}
175 175
 
176 176
 	/** {@inheritdoc} */
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
 		if ($this->secure) {
180 180
 			$baseUri .= 's';
181 181
 		}
182
-		$baseUri .= '://' . $this->host . $this->root;
182
+		$baseUri .= '://'.$this->host.$this->root;
183 183
 		return $baseUri;
184 184
 	}
185 185
 
@@ -200,8 +200,8 @@  discard block
 block discarded – undo
200 200
 		$path = $this->cleanPath($path);
201 201
 		// FIXME: some WebDAV impl return 403 when trying to DELETE
202 202
 		// a non-empty folder
203
-		$result = $this->simpleResponse('DELETE', $path . '/', null, 204);
204
-		$this->statCache->clear($path . '/');
203
+		$result = $this->simpleResponse('DELETE', $path.'/', null, 204);
204
+		$this->statCache->clear($path.'/');
205 205
 		$this->statCache->remove($path);
206 206
 		return $result;
207 207
 	}
@@ -276,7 +276,7 @@  discard block
 block discarded – undo
276 276
 				$this->statCache->set($path, $response);
277 277
 			} catch (ClientHttpException $e) {
278 278
 				if ($e->getHttpStatus() === 404 || $e->getHttpStatus() === 405) {
279
-					$this->statCache->clear($path . '/');
279
+					$this->statCache->clear($path.'/');
280 280
 					$this->statCache->set($path, false);
281 281
 					return false;
282 282
 				}
@@ -333,7 +333,7 @@  discard block
 block discarded – undo
333 333
 		$this->init();
334 334
 		$path = $this->cleanPath($path);
335 335
 		$result = $this->simpleResponse('DELETE', $path, null, 204);
336
-		$this->statCache->clear($path . '/');
336
+		$this->statCache->clear($path.'/');
337 337
 		$this->statCache->remove($path);
338 338
 		return $result;
339 339
 	}
@@ -348,7 +348,7 @@  discard block
 block discarded – undo
348 348
 				try {
349 349
 					$response = $this->httpClientService
350 350
 						->newClient()
351
-						->get($this->createBaseUri() . $this->encodePath($path), [
351
+						->get($this->createBaseUri().$this->encodePath($path), [
352 352
 							'auth' => [$this->user, $this->password],
353 353
 							'stream' => true
354 354
 						]);
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
 					if ($response->getStatusCode() === Http::STATUS_LOCKED) {
366 366
 						throw new \OCP\Lock\LockedException($path);
367 367
 					} else {
368
-						Util::writeLog("webdav client", 'Guzzle get returned status code ' . $response->getStatusCode(), ILogger::ERROR);
368
+						Util::writeLog("webdav client", 'Guzzle get returned status code '.$response->getStatusCode(), ILogger::ERROR);
369 369
 					}
370 370
 				}
371 371
 
@@ -405,7 +405,7 @@  discard block
 block discarded – undo
405 405
 					$tmpFile = $tempManager->getTemporaryFile($ext);
406 406
 				}
407 407
 				$handle = fopen($tmpFile, $mode);
408
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
408
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
409 409
 					$this->writeBack($tmpFile, $path);
410 410
 				});
411 411
 		}
@@ -430,7 +430,7 @@  discard block
 block discarded – undo
430 430
 				return FileInfo::SPACE_UNKNOWN;
431 431
 			}
432 432
 			if (isset($response['{DAV:}quota-available-bytes'])) {
433
-				return (int)$response['{DAV:}quota-available-bytes'];
433
+				return (int) $response['{DAV:}quota-available-bytes'];
434 434
 			} else {
435 435
 				return FileInfo::SPACE_UNKNOWN;
436 436
 			}
@@ -506,7 +506,7 @@  discard block
 block discarded – undo
506 506
 
507 507
 		$this->httpClientService
508 508
 			->newClient()
509
-			->put($this->createBaseUri() . $this->encodePath($target), [
509
+			->put($this->createBaseUri().$this->encodePath($target), [
510 510
 				'body' => $source,
511 511
 				'auth' => [$this->user, $this->password]
512 512
 			]);
@@ -523,18 +523,18 @@  discard block
 block discarded – undo
523 523
 			// overwrite directory ?
524 524
 			if ($this->is_dir($path2)) {
525 525
 				// needs trailing slash in destination
526
-				$path2 = rtrim($path2, '/') . '/';
526
+				$path2 = rtrim($path2, '/').'/';
527 527
 			}
528 528
 			$this->client->request(
529 529
 				'MOVE',
530 530
 				$this->encodePath($path1),
531 531
 				null,
532 532
 				[
533
-					'Destination' => $this->createBaseUri() . $this->encodePath($path2),
533
+					'Destination' => $this->createBaseUri().$this->encodePath($path2),
534 534
 				]
535 535
 			);
536
-			$this->statCache->clear($path1 . '/');
537
-			$this->statCache->clear($path2 . '/');
536
+			$this->statCache->clear($path1.'/');
537
+			$this->statCache->clear($path2.'/');
538 538
 			$this->statCache->set($path1, false);
539 539
 			$this->statCache->set($path2, true);
540 540
 			$this->removeCachedFile($path1);
@@ -555,17 +555,17 @@  discard block
 block discarded – undo
555 555
 			// overwrite directory ?
556 556
 			if ($this->is_dir($path2)) {
557 557
 				// needs trailing slash in destination
558
-				$path2 = rtrim($path2, '/') . '/';
558
+				$path2 = rtrim($path2, '/').'/';
559 559
 			}
560 560
 			$this->client->request(
561 561
 				'COPY',
562 562
 				$this->encodePath($path1),
563 563
 				null,
564 564
 				[
565
-					'Destination' => $this->createBaseUri() . $this->encodePath($path2),
565
+					'Destination' => $this->createBaseUri().$this->encodePath($path2),
566 566
 				]
567 567
 			);
568
-			$this->statCache->clear($path2 . '/');
568
+			$this->statCache->clear($path2.'/');
569 569
 			$this->statCache->set($path2, true);
570 570
 			$this->removeCachedFile($path2);
571 571
 			return true;
@@ -584,7 +584,7 @@  discard block
 block discarded – undo
584 584
 			}
585 585
 			return [
586 586
 				'mtime' => strtotime($response['{DAV:}getlastmodified']),
587
-				'size' => (int)isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0,
587
+				'size' => (int) isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0,
588 588
 			];
589 589
 		} catch (\Exception $e) {
590 590
 			$this->convertException($e, $path);
@@ -666,7 +666,7 @@  discard block
 block discarded – undo
666 666
 			return $response['statusCode'] == $expected;
667 667
 		} catch (ClientHttpException $e) {
668 668
 			if ($e->getHttpStatus() === 404 && $method === 'DELETE') {
669
-				$this->statCache->clear($path . '/');
669
+				$this->statCache->clear($path.'/');
670 670
 				$this->statCache->set($path, false);
671 671
 				return false;
672 672
 			}
@@ -687,22 +687,22 @@  discard block
 block discarded – undo
687 687
 
688 688
 	/** {@inheritdoc} */
689 689
 	public function isUpdatable($path) {
690
-		return (bool)($this->getPermissions($path) & Constants::PERMISSION_UPDATE);
690
+		return (bool) ($this->getPermissions($path) & Constants::PERMISSION_UPDATE);
691 691
 	}
692 692
 
693 693
 	/** {@inheritdoc} */
694 694
 	public function isCreatable($path) {
695
-		return (bool)($this->getPermissions($path) & Constants::PERMISSION_CREATE);
695
+		return (bool) ($this->getPermissions($path) & Constants::PERMISSION_CREATE);
696 696
 	}
697 697
 
698 698
 	/** {@inheritdoc} */
699 699
 	public function isSharable($path) {
700
-		return (bool)($this->getPermissions($path) & Constants::PERMISSION_SHARE);
700
+		return (bool) ($this->getPermissions($path) & Constants::PERMISSION_SHARE);
701 701
 	}
702 702
 
703 703
 	/** {@inheritdoc} */
704 704
 	public function isDeletable($path) {
705
-		return (bool)($this->getPermissions($path) & Constants::PERMISSION_DELETE);
705
+		return (bool) ($this->getPermissions($path) & Constants::PERMISSION_DELETE);
706 706
 	}
707 707
 
708 708
 	/** {@inheritdoc} */
@@ -795,7 +795,7 @@  discard block
 block discarded – undo
795 795
 				if (!empty($etag) && $cachedData['etag'] !== $etag) {
796 796
 					return true;
797 797
 				} else if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
798
-					$sharePermissions = (int)$response['{http://open-collaboration-services.org/ns}share-permissions'];
798
+					$sharePermissions = (int) $response['{http://open-collaboration-services.org/ns}share-permissions'];
799 799
 					return $sharePermissions !== $cachedData['permissions'];
800 800
 				} else if (isset($response['{http://owncloud.org/ns}permissions'])) {
801 801
 					$permissions = $this->parsePermissions($response['{http://owncloud.org/ns}permissions']);
@@ -811,7 +811,7 @@  discard block
 block discarded – undo
811 811
 			if ($e->getHttpStatus() === 405) {
812 812
 				if ($path === '') {
813 813
 					// if root is gone it means the storage is not available
814
-					throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
814
+					throw new StorageNotAvailableException(get_class($e).': '.$e->getMessage());
815 815
 				}
816 816
 				return false;
817 817
 			}
@@ -846,22 +846,22 @@  discard block
 block discarded – undo
846 846
 			}
847 847
 			if ($e->getHttpStatus() === Http::STATUS_UNAUTHORIZED) {
848 848
 				// either password was changed or was invalid all along
849
-				throw new StorageInvalidException(get_class($e) . ': ' . $e->getMessage());
849
+				throw new StorageInvalidException(get_class($e).': '.$e->getMessage());
850 850
 			} else if ($e->getHttpStatus() === Http::STATUS_METHOD_NOT_ALLOWED) {
851 851
 				// ignore exception for MethodNotAllowed, false will be returned
852 852
 				return;
853
-			} else if ($e->getHttpStatus() === Http::STATUS_FORBIDDEN){
853
+			} else if ($e->getHttpStatus() === Http::STATUS_FORBIDDEN) {
854 854
 				// The operation is forbidden. Fail somewhat gracefully
855
-				throw new ForbiddenException(get_class($e) . ':' . $e->getMessage());
855
+				throw new ForbiddenException(get_class($e).':'.$e->getMessage());
856 856
 			}
857
-			throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
857
+			throw new StorageNotAvailableException(get_class($e).': '.$e->getMessage());
858 858
 		} else if ($e instanceof ClientException) {
859 859
 			// connection timeout or refused, server could be temporarily down
860
-			throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
860
+			throw new StorageNotAvailableException(get_class($e).': '.$e->getMessage());
861 861
 		} else if ($e instanceof \InvalidArgumentException) {
862 862
 			// parse error because the server returned HTML instead of XML,
863 863
 			// possibly temporarily down
864
-			throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
864
+			throw new StorageNotAvailableException(get_class($e).': '.$e->getMessage());
865 865
 		} else if (($e instanceof StorageNotAvailableException) || ($e instanceof StorageInvalidException)) {
866 866
 			// rethrow
867 867
 			throw $e;
Please login to merge, or discard this patch.
Indentation   +809 added lines, -809 removed lines patch added patch discarded remove patch
@@ -62,813 +62,813 @@
 block discarded – undo
62 62
  * @package OC\Files\Storage
63 63
  */
64 64
 class DAV extends Common {
65
-	/** @var string */
66
-	protected $password;
67
-	/** @var string */
68
-	protected $user;
69
-	/** @var string */
70
-	protected $authType;
71
-	/** @var string */
72
-	protected $host;
73
-	/** @var bool */
74
-	protected $secure;
75
-	/** @var string */
76
-	protected $root;
77
-	/** @var string */
78
-	protected $certPath;
79
-	/** @var bool */
80
-	protected $ready;
81
-	/** @var Client */
82
-	protected $client;
83
-	/** @var ArrayCache */
84
-	protected $statCache;
85
-	/** @var IClientService */
86
-	protected $httpClientService;
87
-	/** @var ICertificateManager */
88
-	protected $certManager;
89
-
90
-	/**
91
-	 * @param array $params
92
-	 * @throws \Exception
93
-	 */
94
-	public function __construct($params) {
95
-		$this->statCache = new ArrayCache();
96
-		$this->httpClientService = \OC::$server->getHTTPClientService();
97
-		if (isset($params['host']) && isset($params['user']) && isset($params['password'])) {
98
-			$host = $params['host'];
99
-			//remove leading http[s], will be generated in createBaseUri()
100
-			if (substr($host, 0, 8) == "https://") $host = substr($host, 8);
101
-			else if (substr($host, 0, 7) == "http://") $host = substr($host, 7);
102
-			$this->host = $host;
103
-			$this->user = $params['user'];
104
-			$this->password = $params['password'];
105
-			if (isset($params['authType'])) {
106
-				$this->authType = $params['authType'];
107
-			}
108
-			if (isset($params['secure'])) {
109
-				if (is_string($params['secure'])) {
110
-					$this->secure = ($params['secure'] === 'true');
111
-				} else {
112
-					$this->secure = (bool)$params['secure'];
113
-				}
114
-			} else {
115
-				$this->secure = false;
116
-			}
117
-			if ($this->secure === true) {
118
-				// inject mock for testing
119
-				$this->certManager = \OC::$server->getCertificateManager();
120
-				if (is_null($this->certManager)) { //no user
121
-					$this->certManager = \OC::$server->getCertificateManager(null);
122
-				}
123
-			}
124
-			$this->root = $params['root'] ?? '/';
125
-			$this->root = '/' . ltrim($this->root, '/');
126
-			$this->root = rtrim($this->root, '/') . '/';
127
-		} else {
128
-			throw new \Exception('Invalid webdav storage configuration');
129
-		}
130
-	}
131
-
132
-	protected function init() {
133
-		if ($this->ready) {
134
-			return;
135
-		}
136
-		$this->ready = true;
137
-
138
-		$settings = [
139
-			'baseUri' => $this->createBaseUri(),
140
-			'userName' => $this->user,
141
-			'password' => $this->password,
142
-		];
143
-		if (isset($this->authType)) {
144
-			$settings['authType'] = $this->authType;
145
-		}
146
-
147
-		$proxy = \OC::$server->getConfig()->getSystemValue('proxy', '');
148
-		if ($proxy !== '') {
149
-			$settings['proxy'] = $proxy;
150
-		}
151
-
152
-		$this->client = new Client($settings);
153
-		$this->client->setThrowExceptions(true);
154
-
155
-		if($this->secure === true) {
156
-			$certPath = $this->certManager->getAbsoluteBundlePath();
157
-			if (file_exists($certPath)) {
158
-				$this->certPath = $certPath;
159
-			}
160
-			if ($this->certPath) {
161
-				$this->client->addCurlSetting(CURLOPT_CAINFO, $this->certPath);
162
-			}
163
-		}
164
-	}
165
-
166
-	/**
167
-	 * Clear the stat cache
168
-	 */
169
-	public function clearStatCache() {
170
-		$this->statCache->clear();
171
-	}
172
-
173
-	/** {@inheritdoc} */
174
-	public function getId() {
175
-		return 'webdav::' . $this->user . '@' . $this->host . '/' . $this->root;
176
-	}
177
-
178
-	/** {@inheritdoc} */
179
-	public function createBaseUri() {
180
-		$baseUri = 'http';
181
-		if ($this->secure) {
182
-			$baseUri .= 's';
183
-		}
184
-		$baseUri .= '://' . $this->host . $this->root;
185
-		return $baseUri;
186
-	}
187
-
188
-	/** {@inheritdoc} */
189
-	public function mkdir($path) {
190
-		$this->init();
191
-		$path = $this->cleanPath($path);
192
-		$result = $this->simpleResponse('MKCOL', $path, null, 201);
193
-		if ($result) {
194
-			$this->statCache->set($path, true);
195
-		}
196
-		return $result;
197
-	}
198
-
199
-	/** {@inheritdoc} */
200
-	public function rmdir($path) {
201
-		$this->init();
202
-		$path = $this->cleanPath($path);
203
-		// FIXME: some WebDAV impl return 403 when trying to DELETE
204
-		// a non-empty folder
205
-		$result = $this->simpleResponse('DELETE', $path . '/', null, 204);
206
-		$this->statCache->clear($path . '/');
207
-		$this->statCache->remove($path);
208
-		return $result;
209
-	}
210
-
211
-	/** {@inheritdoc} */
212
-	public function opendir($path) {
213
-		$this->init();
214
-		$path = $this->cleanPath($path);
215
-		try {
216
-			$response = $this->client->propFind(
217
-				$this->encodePath($path),
218
-				['{DAV:}getetag'],
219
-				1
220
-			);
221
-			if ($response === false) {
222
-				return false;
223
-			}
224
-			$content = [];
225
-			$files = array_keys($response);
226
-			array_shift($files); //the first entry is the current directory
227
-
228
-			if (!$this->statCache->hasKey($path)) {
229
-				$this->statCache->set($path, true);
230
-			}
231
-			foreach ($files as $file) {
232
-				$file = urldecode($file);
233
-				// do not store the real entry, we might not have all properties
234
-				if (!$this->statCache->hasKey($path)) {
235
-					$this->statCache->set($file, true);
236
-				}
237
-				$file = basename($file);
238
-				$content[] = $file;
239
-			}
240
-			return IteratorDirectory::wrap($content);
241
-		} catch (\Exception $e) {
242
-			$this->convertException($e, $path);
243
-		}
244
-		return false;
245
-	}
246
-
247
-	/**
248
-	 * Propfind call with cache handling.
249
-	 *
250
-	 * First checks if information is cached.
251
-	 * If not, request it from the server then store to cache.
252
-	 *
253
-	 * @param string $path path to propfind
254
-	 *
255
-	 * @return array|boolean propfind response or false if the entry was not found
256
-	 *
257
-	 * @throws ClientHttpException
258
-	 */
259
-	protected function propfind($path) {
260
-		$path = $this->cleanPath($path);
261
-		$cachedResponse = $this->statCache->get($path);
262
-		// we either don't know it, or we know it exists but need more details
263
-		if (is_null($cachedResponse) || $cachedResponse === true) {
264
-			$this->init();
265
-			try {
266
-				$response = $this->client->propFind(
267
-					$this->encodePath($path),
268
-					[
269
-						'{DAV:}getlastmodified',
270
-						'{DAV:}getcontentlength',
271
-						'{DAV:}getcontenttype',
272
-						'{http://owncloud.org/ns}permissions',
273
-						'{http://open-collaboration-services.org/ns}share-permissions',
274
-						'{DAV:}resourcetype',
275
-						'{DAV:}getetag',
276
-					]
277
-				);
278
-				$this->statCache->set($path, $response);
279
-			} catch (ClientHttpException $e) {
280
-				if ($e->getHttpStatus() === 404 || $e->getHttpStatus() === 405) {
281
-					$this->statCache->clear($path . '/');
282
-					$this->statCache->set($path, false);
283
-					return false;
284
-				}
285
-				$this->convertException($e, $path);
286
-			} catch (\Exception $e) {
287
-				$this->convertException($e, $path);
288
-			}
289
-		} else {
290
-			$response = $cachedResponse;
291
-		}
292
-		return $response;
293
-	}
294
-
295
-	/** {@inheritdoc} */
296
-	public function filetype($path) {
297
-		try {
298
-			$response = $this->propfind($path);
299
-			if ($response === false) {
300
-				return false;
301
-			}
302
-			$responseType = [];
303
-			if (isset($response["{DAV:}resourcetype"])) {
304
-				/** @var ResourceType[] $response */
305
-				$responseType = $response["{DAV:}resourcetype"]->getValue();
306
-			}
307
-			return (count($responseType) > 0 and $responseType[0] == "{DAV:}collection") ? 'dir' : 'file';
308
-		} catch (\Exception $e) {
309
-			$this->convertException($e, $path);
310
-		}
311
-		return false;
312
-	}
313
-
314
-	/** {@inheritdoc} */
315
-	public function file_exists($path) {
316
-		try {
317
-			$path = $this->cleanPath($path);
318
-			$cachedState = $this->statCache->get($path);
319
-			if ($cachedState === false) {
320
-				// we know the file doesn't exist
321
-				return false;
322
-			} else if (!is_null($cachedState)) {
323
-				return true;
324
-			}
325
-			// need to get from server
326
-			return ($this->propfind($path) !== false);
327
-		} catch (\Exception $e) {
328
-			$this->convertException($e, $path);
329
-		}
330
-		return false;
331
-	}
332
-
333
-	/** {@inheritdoc} */
334
-	public function unlink($path) {
335
-		$this->init();
336
-		$path = $this->cleanPath($path);
337
-		$result = $this->simpleResponse('DELETE', $path, null, 204);
338
-		$this->statCache->clear($path . '/');
339
-		$this->statCache->remove($path);
340
-		return $result;
341
-	}
342
-
343
-	/** {@inheritdoc} */
344
-	public function fopen($path, $mode) {
345
-		$this->init();
346
-		$path = $this->cleanPath($path);
347
-		switch ($mode) {
348
-			case 'r':
349
-			case 'rb':
350
-				try {
351
-					$response = $this->httpClientService
352
-						->newClient()
353
-						->get($this->createBaseUri() . $this->encodePath($path), [
354
-							'auth' => [$this->user, $this->password],
355
-							'stream' => true
356
-						]);
357
-				} catch (\GuzzleHttp\Exception\ClientException $e) {
358
-					if ($e->getResponse() instanceof ResponseInterface
359
-						&& $e->getResponse()->getStatusCode() === 404) {
360
-						return false;
361
-					} else {
362
-						throw $e;
363
-					}
364
-				}
365
-
366
-				if ($response->getStatusCode() !== Http::STATUS_OK) {
367
-					if ($response->getStatusCode() === Http::STATUS_LOCKED) {
368
-						throw new \OCP\Lock\LockedException($path);
369
-					} else {
370
-						Util::writeLog("webdav client", 'Guzzle get returned status code ' . $response->getStatusCode(), ILogger::ERROR);
371
-					}
372
-				}
373
-
374
-				return $response->getBody();
375
-			case 'w':
376
-			case 'wb':
377
-			case 'a':
378
-			case 'ab':
379
-			case 'r+':
380
-			case 'w+':
381
-			case 'wb+':
382
-			case 'a+':
383
-			case 'x':
384
-			case 'x+':
385
-			case 'c':
386
-			case 'c+':
387
-				//emulate these
388
-				$tempManager = \OC::$server->getTempManager();
389
-				if (strrpos($path, '.') !== false) {
390
-					$ext = substr($path, strrpos($path, '.'));
391
-				} else {
392
-					$ext = '';
393
-				}
394
-				if ($this->file_exists($path)) {
395
-					if (!$this->isUpdatable($path)) {
396
-						return false;
397
-					}
398
-					if ($mode === 'w' or $mode === 'w+') {
399
-						$tmpFile = $tempManager->getTemporaryFile($ext);
400
-					} else {
401
-						$tmpFile = $this->getCachedFile($path);
402
-					}
403
-				} else {
404
-					if (!$this->isCreatable(dirname($path))) {
405
-						return false;
406
-					}
407
-					$tmpFile = $tempManager->getTemporaryFile($ext);
408
-				}
409
-				$handle = fopen($tmpFile, $mode);
410
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
411
-					$this->writeBack($tmpFile, $path);
412
-				});
413
-		}
414
-	}
415
-
416
-	/**
417
-	 * @param string $tmpFile
418
-	 */
419
-	public function writeBack($tmpFile, $path) {
420
-		$this->uploadFile($tmpFile, $path);
421
-		unlink($tmpFile);
422
-	}
423
-
424
-	/** {@inheritdoc} */
425
-	public function free_space($path) {
426
-		$this->init();
427
-		$path = $this->cleanPath($path);
428
-		try {
429
-			// TODO: cacheable ?
430
-			$response = $this->client->propfind($this->encodePath($path), ['{DAV:}quota-available-bytes']);
431
-			if ($response === false) {
432
-				return FileInfo::SPACE_UNKNOWN;
433
-			}
434
-			if (isset($response['{DAV:}quota-available-bytes'])) {
435
-				return (int)$response['{DAV:}quota-available-bytes'];
436
-			} else {
437
-				return FileInfo::SPACE_UNKNOWN;
438
-			}
439
-		} catch (\Exception $e) {
440
-			return FileInfo::SPACE_UNKNOWN;
441
-		}
442
-	}
443
-
444
-	/** {@inheritdoc} */
445
-	public function touch($path, $mtime = null) {
446
-		$this->init();
447
-		if (is_null($mtime)) {
448
-			$mtime = time();
449
-		}
450
-		$path = $this->cleanPath($path);
451
-
452
-		// if file exists, update the mtime, else create a new empty file
453
-		if ($this->file_exists($path)) {
454
-			try {
455
-				$this->statCache->remove($path);
456
-				$this->client->proppatch($this->encodePath($path), ['{DAV:}lastmodified' => $mtime]);
457
-				// non-owncloud clients might not have accepted the property, need to recheck it
458
-				$response = $this->client->propfind($this->encodePath($path), ['{DAV:}getlastmodified'], 0);
459
-				if ($response === false) {
460
-					return false;
461
-				}
462
-				if (isset($response['{DAV:}getlastmodified'])) {
463
-					$remoteMtime = strtotime($response['{DAV:}getlastmodified']);
464
-					if ($remoteMtime !== $mtime) {
465
-						// server has not accepted the mtime
466
-						return false;
467
-					}
468
-				}
469
-			} catch (ClientHttpException $e) {
470
-				if ($e->getHttpStatus() === 501) {
471
-					return false;
472
-				}
473
-				$this->convertException($e, $path);
474
-				return false;
475
-			} catch (\Exception $e) {
476
-				$this->convertException($e, $path);
477
-				return false;
478
-			}
479
-		} else {
480
-			$this->file_put_contents($path, '');
481
-		}
482
-		return true;
483
-	}
484
-
485
-	/**
486
-	 * @param string $path
487
-	 * @param string $data
488
-	 * @return int
489
-	 */
490
-	public function file_put_contents($path, $data) {
491
-		$path = $this->cleanPath($path);
492
-		$result = parent::file_put_contents($path, $data);
493
-		$this->statCache->remove($path);
494
-		return $result;
495
-	}
496
-
497
-	/**
498
-	 * @param string $path
499
-	 * @param string $target
500
-	 */
501
-	protected function uploadFile($path, $target) {
502
-		$this->init();
503
-
504
-		// invalidate
505
-		$target = $this->cleanPath($target);
506
-		$this->statCache->remove($target);
507
-		$source = fopen($path, 'r');
508
-
509
-		$this->httpClientService
510
-			->newClient()
511
-			->put($this->createBaseUri() . $this->encodePath($target), [
512
-				'body' => $source,
513
-				'auth' => [$this->user, $this->password]
514
-			]);
515
-
516
-		$this->removeCachedFile($target);
517
-	}
518
-
519
-	/** {@inheritdoc} */
520
-	public function rename($path1, $path2) {
521
-		$this->init();
522
-		$path1 = $this->cleanPath($path1);
523
-		$path2 = $this->cleanPath($path2);
524
-		try {
525
-			// overwrite directory ?
526
-			if ($this->is_dir($path2)) {
527
-				// needs trailing slash in destination
528
-				$path2 = rtrim($path2, '/') . '/';
529
-			}
530
-			$this->client->request(
531
-				'MOVE',
532
-				$this->encodePath($path1),
533
-				null,
534
-				[
535
-					'Destination' => $this->createBaseUri() . $this->encodePath($path2),
536
-				]
537
-			);
538
-			$this->statCache->clear($path1 . '/');
539
-			$this->statCache->clear($path2 . '/');
540
-			$this->statCache->set($path1, false);
541
-			$this->statCache->set($path2, true);
542
-			$this->removeCachedFile($path1);
543
-			$this->removeCachedFile($path2);
544
-			return true;
545
-		} catch (\Exception $e) {
546
-			$this->convertException($e);
547
-		}
548
-		return false;
549
-	}
550
-
551
-	/** {@inheritdoc} */
552
-	public function copy($path1, $path2) {
553
-		$this->init();
554
-		$path1 = $this->cleanPath($path1);
555
-		$path2 = $this->cleanPath($path2);
556
-		try {
557
-			// overwrite directory ?
558
-			if ($this->is_dir($path2)) {
559
-				// needs trailing slash in destination
560
-				$path2 = rtrim($path2, '/') . '/';
561
-			}
562
-			$this->client->request(
563
-				'COPY',
564
-				$this->encodePath($path1),
565
-				null,
566
-				[
567
-					'Destination' => $this->createBaseUri() . $this->encodePath($path2),
568
-				]
569
-			);
570
-			$this->statCache->clear($path2 . '/');
571
-			$this->statCache->set($path2, true);
572
-			$this->removeCachedFile($path2);
573
-			return true;
574
-		} catch (\Exception $e) {
575
-			$this->convertException($e);
576
-		}
577
-		return false;
578
-	}
579
-
580
-	/** {@inheritdoc} */
581
-	public function stat($path) {
582
-		try {
583
-			$response = $this->propfind($path);
584
-			if (!$response) {
585
-				return false;
586
-			}
587
-			return [
588
-				'mtime' => strtotime($response['{DAV:}getlastmodified']),
589
-				'size' => (int)isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0,
590
-			];
591
-		} catch (\Exception $e) {
592
-			$this->convertException($e, $path);
593
-		}
594
-		return [];
595
-	}
596
-
597
-	/** {@inheritdoc} */
598
-	public function getMimeType($path) {
599
-		$remoteMimetype = $this->getMimeTypeFromRemote($path);
600
-		if ($remoteMimetype === 'application/octet-stream') {
601
-			return \OC::$server->getMimeTypeDetector()->detectPath($path);
602
-		} else {
603
-			return $remoteMimetype;
604
-		}
605
-	}
606
-
607
-	public function getMimeTypeFromRemote($path) {
608
-		try {
609
-			$response = $this->propfind($path);
610
-			if ($response === false) {
611
-				return false;
612
-			}
613
-			$responseType = [];
614
-			if (isset($response["{DAV:}resourcetype"])) {
615
-				/** @var ResourceType[] $response */
616
-				$responseType = $response["{DAV:}resourcetype"]->getValue();
617
-			}
618
-			$type = (count($responseType) > 0 and $responseType[0] == "{DAV:}collection") ? 'dir' : 'file';
619
-			if ($type == 'dir') {
620
-				return 'httpd/unix-directory';
621
-			} elseif (isset($response['{DAV:}getcontenttype'])) {
622
-				return $response['{DAV:}getcontenttype'];
623
-			} else {
624
-				return 'application/octet-stream';
625
-			}
626
-		} catch (\Exception $e) {
627
-			return false;
628
-		}
629
-	}
630
-
631
-	/**
632
-	 * @param string $path
633
-	 * @return string
634
-	 */
635
-	public function cleanPath($path) {
636
-		if ($path === '') {
637
-			return $path;
638
-		}
639
-		$path = Filesystem::normalizePath($path);
640
-		// remove leading slash
641
-		return substr($path, 1);
642
-	}
643
-
644
-	/**
645
-	 * URL encodes the given path but keeps the slashes
646
-	 *
647
-	 * @param string $path to encode
648
-	 * @return string encoded path
649
-	 */
650
-	protected function encodePath($path) {
651
-		// slashes need to stay
652
-		return str_replace('%2F', '/', rawurlencode($path));
653
-	}
654
-
655
-	/**
656
-	 * @param string $method
657
-	 * @param string $path
658
-	 * @param string|resource|null $body
659
-	 * @param int $expected
660
-	 * @return bool
661
-	 * @throws StorageInvalidException
662
-	 * @throws StorageNotAvailableException
663
-	 */
664
-	protected function simpleResponse($method, $path, $body, $expected) {
665
-		$path = $this->cleanPath($path);
666
-		try {
667
-			$response = $this->client->request($method, $this->encodePath($path), $body);
668
-			return $response['statusCode'] == $expected;
669
-		} catch (ClientHttpException $e) {
670
-			if ($e->getHttpStatus() === 404 && $method === 'DELETE') {
671
-				$this->statCache->clear($path . '/');
672
-				$this->statCache->set($path, false);
673
-				return false;
674
-			}
675
-
676
-			$this->convertException($e, $path);
677
-		} catch (\Exception $e) {
678
-			$this->convertException($e, $path);
679
-		}
680
-		return false;
681
-	}
682
-
683
-	/**
684
-	 * check if curl is installed
685
-	 */
686
-	public static function checkDependencies() {
687
-		return true;
688
-	}
689
-
690
-	/** {@inheritdoc} */
691
-	public function isUpdatable($path) {
692
-		return (bool)($this->getPermissions($path) & Constants::PERMISSION_UPDATE);
693
-	}
694
-
695
-	/** {@inheritdoc} */
696
-	public function isCreatable($path) {
697
-		return (bool)($this->getPermissions($path) & Constants::PERMISSION_CREATE);
698
-	}
699
-
700
-	/** {@inheritdoc} */
701
-	public function isSharable($path) {
702
-		return (bool)($this->getPermissions($path) & Constants::PERMISSION_SHARE);
703
-	}
704
-
705
-	/** {@inheritdoc} */
706
-	public function isDeletable($path) {
707
-		return (bool)($this->getPermissions($path) & Constants::PERMISSION_DELETE);
708
-	}
709
-
710
-	/** {@inheritdoc} */
711
-	public function getPermissions($path) {
712
-		$this->init();
713
-		$path = $this->cleanPath($path);
714
-		$response = $this->propfind($path);
715
-		if ($response === false) {
716
-			return 0;
717
-		}
718
-		if (isset($response['{http://owncloud.org/ns}permissions'])) {
719
-			return $this->parsePermissions($response['{http://owncloud.org/ns}permissions']);
720
-		} else if ($this->is_dir($path)) {
721
-			return Constants::PERMISSION_ALL;
722
-		} else if ($this->file_exists($path)) {
723
-			return Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE;
724
-		} else {
725
-			return 0;
726
-		}
727
-	}
728
-
729
-	/** {@inheritdoc} */
730
-	public function getETag($path) {
731
-		$this->init();
732
-		$path = $this->cleanPath($path);
733
-		$response = $this->propfind($path);
734
-		if ($response === false) {
735
-			return null;
736
-		}
737
-		if (isset($response['{DAV:}getetag'])) {
738
-			$etag = trim($response['{DAV:}getetag'], '"');
739
-			if (strlen($etag) > 40) {
740
-				$etag = md5($etag);
741
-			}
742
-			return $etag;
743
-		}
744
-		return parent::getEtag($path);
745
-	}
746
-
747
-	/**
748
-	 * @param string $permissionsString
749
-	 * @return int
750
-	 */
751
-	protected function parsePermissions($permissionsString) {
752
-		$permissions = Constants::PERMISSION_READ;
753
-		if (strpos($permissionsString, 'R') !== false) {
754
-			$permissions |= Constants::PERMISSION_SHARE;
755
-		}
756
-		if (strpos($permissionsString, 'D') !== false) {
757
-			$permissions |= Constants::PERMISSION_DELETE;
758
-		}
759
-		if (strpos($permissionsString, 'W') !== false) {
760
-			$permissions |= Constants::PERMISSION_UPDATE;
761
-		}
762
-		if (strpos($permissionsString, 'CK') !== false) {
763
-			$permissions |= Constants::PERMISSION_CREATE;
764
-			$permissions |= Constants::PERMISSION_UPDATE;
765
-		}
766
-		return $permissions;
767
-	}
768
-
769
-	/**
770
-	 * check if a file or folder has been updated since $time
771
-	 *
772
-	 * @param string $path
773
-	 * @param int $time
774
-	 * @throws \OCP\Files\StorageNotAvailableException
775
-	 * @return bool
776
-	 */
777
-	public function hasUpdated($path, $time) {
778
-		$this->init();
779
-		$path = $this->cleanPath($path);
780
-		try {
781
-			// force refresh for $path
782
-			$this->statCache->remove($path);
783
-			$response = $this->propfind($path);
784
-			if ($response === false) {
785
-				if ($path === '') {
786
-					// if root is gone it means the storage is not available
787
-					throw new StorageNotAvailableException('root is gone');
788
-				}
789
-				return false;
790
-			}
791
-			if (isset($response['{DAV:}getetag'])) {
792
-				$cachedData = $this->getCache()->get($path);
793
-				$etag = null;
794
-				if (isset($response['{DAV:}getetag'])) {
795
-					$etag = trim($response['{DAV:}getetag'], '"');
796
-				}
797
-				if (!empty($etag) && $cachedData['etag'] !== $etag) {
798
-					return true;
799
-				} else if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
800
-					$sharePermissions = (int)$response['{http://open-collaboration-services.org/ns}share-permissions'];
801
-					return $sharePermissions !== $cachedData['permissions'];
802
-				} else if (isset($response['{http://owncloud.org/ns}permissions'])) {
803
-					$permissions = $this->parsePermissions($response['{http://owncloud.org/ns}permissions']);
804
-					return $permissions !== $cachedData['permissions'];
805
-				} else {
806
-					return false;
807
-				}
808
-			} else {
809
-				$remoteMtime = strtotime($response['{DAV:}getlastmodified']);
810
-				return $remoteMtime > $time;
811
-			}
812
-		} catch (ClientHttpException $e) {
813
-			if ($e->getHttpStatus() === 405) {
814
-				if ($path === '') {
815
-					// if root is gone it means the storage is not available
816
-					throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
817
-				}
818
-				return false;
819
-			}
820
-			$this->convertException($e, $path);
821
-			return false;
822
-		} catch (\Exception $e) {
823
-			$this->convertException($e, $path);
824
-			return false;
825
-		}
826
-	}
827
-
828
-	/**
829
-	 * Interpret the given exception and decide whether it is due to an
830
-	 * unavailable storage, invalid storage or other.
831
-	 * This will either throw StorageInvalidException, StorageNotAvailableException
832
-	 * or do nothing.
833
-	 *
834
-	 * @param Exception $e sabre exception
835
-	 * @param string $path optional path from the operation
836
-	 *
837
-	 * @throws StorageInvalidException if the storage is invalid, for example
838
-	 * when the authentication expired or is invalid
839
-	 * @throws StorageNotAvailableException if the storage is not available,
840
-	 * which might be temporary
841
-	 * @throws ForbiddenException if the action is not allowed
842
-	 */
843
-	protected function convertException(Exception $e, $path = '') {
844
-		\OC::$server->getLogger()->logException($e, ['app' => 'files_external', 'level' => ILogger::DEBUG]);
845
-		if ($e instanceof ClientHttpException) {
846
-			if ($e->getHttpStatus() === Http::STATUS_LOCKED) {
847
-				throw new \OCP\Lock\LockedException($path);
848
-			}
849
-			if ($e->getHttpStatus() === Http::STATUS_UNAUTHORIZED) {
850
-				// either password was changed or was invalid all along
851
-				throw new StorageInvalidException(get_class($e) . ': ' . $e->getMessage());
852
-			} else if ($e->getHttpStatus() === Http::STATUS_METHOD_NOT_ALLOWED) {
853
-				// ignore exception for MethodNotAllowed, false will be returned
854
-				return;
855
-			} else if ($e->getHttpStatus() === Http::STATUS_FORBIDDEN){
856
-				// The operation is forbidden. Fail somewhat gracefully
857
-				throw new ForbiddenException(get_class($e) . ':' . $e->getMessage());
858
-			}
859
-			throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
860
-		} else if ($e instanceof ClientException) {
861
-			// connection timeout or refused, server could be temporarily down
862
-			throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
863
-		} else if ($e instanceof \InvalidArgumentException) {
864
-			// parse error because the server returned HTML instead of XML,
865
-			// possibly temporarily down
866
-			throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
867
-		} else if (($e instanceof StorageNotAvailableException) || ($e instanceof StorageInvalidException)) {
868
-			// rethrow
869
-			throw $e;
870
-		}
871
-
872
-		// TODO: only log for now, but in the future need to wrap/rethrow exception
873
-	}
65
+    /** @var string */
66
+    protected $password;
67
+    /** @var string */
68
+    protected $user;
69
+    /** @var string */
70
+    protected $authType;
71
+    /** @var string */
72
+    protected $host;
73
+    /** @var bool */
74
+    protected $secure;
75
+    /** @var string */
76
+    protected $root;
77
+    /** @var string */
78
+    protected $certPath;
79
+    /** @var bool */
80
+    protected $ready;
81
+    /** @var Client */
82
+    protected $client;
83
+    /** @var ArrayCache */
84
+    protected $statCache;
85
+    /** @var IClientService */
86
+    protected $httpClientService;
87
+    /** @var ICertificateManager */
88
+    protected $certManager;
89
+
90
+    /**
91
+     * @param array $params
92
+     * @throws \Exception
93
+     */
94
+    public function __construct($params) {
95
+        $this->statCache = new ArrayCache();
96
+        $this->httpClientService = \OC::$server->getHTTPClientService();
97
+        if (isset($params['host']) && isset($params['user']) && isset($params['password'])) {
98
+            $host = $params['host'];
99
+            //remove leading http[s], will be generated in createBaseUri()
100
+            if (substr($host, 0, 8) == "https://") $host = substr($host, 8);
101
+            else if (substr($host, 0, 7) == "http://") $host = substr($host, 7);
102
+            $this->host = $host;
103
+            $this->user = $params['user'];
104
+            $this->password = $params['password'];
105
+            if (isset($params['authType'])) {
106
+                $this->authType = $params['authType'];
107
+            }
108
+            if (isset($params['secure'])) {
109
+                if (is_string($params['secure'])) {
110
+                    $this->secure = ($params['secure'] === 'true');
111
+                } else {
112
+                    $this->secure = (bool)$params['secure'];
113
+                }
114
+            } else {
115
+                $this->secure = false;
116
+            }
117
+            if ($this->secure === true) {
118
+                // inject mock for testing
119
+                $this->certManager = \OC::$server->getCertificateManager();
120
+                if (is_null($this->certManager)) { //no user
121
+                    $this->certManager = \OC::$server->getCertificateManager(null);
122
+                }
123
+            }
124
+            $this->root = $params['root'] ?? '/';
125
+            $this->root = '/' . ltrim($this->root, '/');
126
+            $this->root = rtrim($this->root, '/') . '/';
127
+        } else {
128
+            throw new \Exception('Invalid webdav storage configuration');
129
+        }
130
+    }
131
+
132
+    protected function init() {
133
+        if ($this->ready) {
134
+            return;
135
+        }
136
+        $this->ready = true;
137
+
138
+        $settings = [
139
+            'baseUri' => $this->createBaseUri(),
140
+            'userName' => $this->user,
141
+            'password' => $this->password,
142
+        ];
143
+        if (isset($this->authType)) {
144
+            $settings['authType'] = $this->authType;
145
+        }
146
+
147
+        $proxy = \OC::$server->getConfig()->getSystemValue('proxy', '');
148
+        if ($proxy !== '') {
149
+            $settings['proxy'] = $proxy;
150
+        }
151
+
152
+        $this->client = new Client($settings);
153
+        $this->client->setThrowExceptions(true);
154
+
155
+        if($this->secure === true) {
156
+            $certPath = $this->certManager->getAbsoluteBundlePath();
157
+            if (file_exists($certPath)) {
158
+                $this->certPath = $certPath;
159
+            }
160
+            if ($this->certPath) {
161
+                $this->client->addCurlSetting(CURLOPT_CAINFO, $this->certPath);
162
+            }
163
+        }
164
+    }
165
+
166
+    /**
167
+     * Clear the stat cache
168
+     */
169
+    public function clearStatCache() {
170
+        $this->statCache->clear();
171
+    }
172
+
173
+    /** {@inheritdoc} */
174
+    public function getId() {
175
+        return 'webdav::' . $this->user . '@' . $this->host . '/' . $this->root;
176
+    }
177
+
178
+    /** {@inheritdoc} */
179
+    public function createBaseUri() {
180
+        $baseUri = 'http';
181
+        if ($this->secure) {
182
+            $baseUri .= 's';
183
+        }
184
+        $baseUri .= '://' . $this->host . $this->root;
185
+        return $baseUri;
186
+    }
187
+
188
+    /** {@inheritdoc} */
189
+    public function mkdir($path) {
190
+        $this->init();
191
+        $path = $this->cleanPath($path);
192
+        $result = $this->simpleResponse('MKCOL', $path, null, 201);
193
+        if ($result) {
194
+            $this->statCache->set($path, true);
195
+        }
196
+        return $result;
197
+    }
198
+
199
+    /** {@inheritdoc} */
200
+    public function rmdir($path) {
201
+        $this->init();
202
+        $path = $this->cleanPath($path);
203
+        // FIXME: some WebDAV impl return 403 when trying to DELETE
204
+        // a non-empty folder
205
+        $result = $this->simpleResponse('DELETE', $path . '/', null, 204);
206
+        $this->statCache->clear($path . '/');
207
+        $this->statCache->remove($path);
208
+        return $result;
209
+    }
210
+
211
+    /** {@inheritdoc} */
212
+    public function opendir($path) {
213
+        $this->init();
214
+        $path = $this->cleanPath($path);
215
+        try {
216
+            $response = $this->client->propFind(
217
+                $this->encodePath($path),
218
+                ['{DAV:}getetag'],
219
+                1
220
+            );
221
+            if ($response === false) {
222
+                return false;
223
+            }
224
+            $content = [];
225
+            $files = array_keys($response);
226
+            array_shift($files); //the first entry is the current directory
227
+
228
+            if (!$this->statCache->hasKey($path)) {
229
+                $this->statCache->set($path, true);
230
+            }
231
+            foreach ($files as $file) {
232
+                $file = urldecode($file);
233
+                // do not store the real entry, we might not have all properties
234
+                if (!$this->statCache->hasKey($path)) {
235
+                    $this->statCache->set($file, true);
236
+                }
237
+                $file = basename($file);
238
+                $content[] = $file;
239
+            }
240
+            return IteratorDirectory::wrap($content);
241
+        } catch (\Exception $e) {
242
+            $this->convertException($e, $path);
243
+        }
244
+        return false;
245
+    }
246
+
247
+    /**
248
+     * Propfind call with cache handling.
249
+     *
250
+     * First checks if information is cached.
251
+     * If not, request it from the server then store to cache.
252
+     *
253
+     * @param string $path path to propfind
254
+     *
255
+     * @return array|boolean propfind response or false if the entry was not found
256
+     *
257
+     * @throws ClientHttpException
258
+     */
259
+    protected function propfind($path) {
260
+        $path = $this->cleanPath($path);
261
+        $cachedResponse = $this->statCache->get($path);
262
+        // we either don't know it, or we know it exists but need more details
263
+        if (is_null($cachedResponse) || $cachedResponse === true) {
264
+            $this->init();
265
+            try {
266
+                $response = $this->client->propFind(
267
+                    $this->encodePath($path),
268
+                    [
269
+                        '{DAV:}getlastmodified',
270
+                        '{DAV:}getcontentlength',
271
+                        '{DAV:}getcontenttype',
272
+                        '{http://owncloud.org/ns}permissions',
273
+                        '{http://open-collaboration-services.org/ns}share-permissions',
274
+                        '{DAV:}resourcetype',
275
+                        '{DAV:}getetag',
276
+                    ]
277
+                );
278
+                $this->statCache->set($path, $response);
279
+            } catch (ClientHttpException $e) {
280
+                if ($e->getHttpStatus() === 404 || $e->getHttpStatus() === 405) {
281
+                    $this->statCache->clear($path . '/');
282
+                    $this->statCache->set($path, false);
283
+                    return false;
284
+                }
285
+                $this->convertException($e, $path);
286
+            } catch (\Exception $e) {
287
+                $this->convertException($e, $path);
288
+            }
289
+        } else {
290
+            $response = $cachedResponse;
291
+        }
292
+        return $response;
293
+    }
294
+
295
+    /** {@inheritdoc} */
296
+    public function filetype($path) {
297
+        try {
298
+            $response = $this->propfind($path);
299
+            if ($response === false) {
300
+                return false;
301
+            }
302
+            $responseType = [];
303
+            if (isset($response["{DAV:}resourcetype"])) {
304
+                /** @var ResourceType[] $response */
305
+                $responseType = $response["{DAV:}resourcetype"]->getValue();
306
+            }
307
+            return (count($responseType) > 0 and $responseType[0] == "{DAV:}collection") ? 'dir' : 'file';
308
+        } catch (\Exception $e) {
309
+            $this->convertException($e, $path);
310
+        }
311
+        return false;
312
+    }
313
+
314
+    /** {@inheritdoc} */
315
+    public function file_exists($path) {
316
+        try {
317
+            $path = $this->cleanPath($path);
318
+            $cachedState = $this->statCache->get($path);
319
+            if ($cachedState === false) {
320
+                // we know the file doesn't exist
321
+                return false;
322
+            } else if (!is_null($cachedState)) {
323
+                return true;
324
+            }
325
+            // need to get from server
326
+            return ($this->propfind($path) !== false);
327
+        } catch (\Exception $e) {
328
+            $this->convertException($e, $path);
329
+        }
330
+        return false;
331
+    }
332
+
333
+    /** {@inheritdoc} */
334
+    public function unlink($path) {
335
+        $this->init();
336
+        $path = $this->cleanPath($path);
337
+        $result = $this->simpleResponse('DELETE', $path, null, 204);
338
+        $this->statCache->clear($path . '/');
339
+        $this->statCache->remove($path);
340
+        return $result;
341
+    }
342
+
343
+    /** {@inheritdoc} */
344
+    public function fopen($path, $mode) {
345
+        $this->init();
346
+        $path = $this->cleanPath($path);
347
+        switch ($mode) {
348
+            case 'r':
349
+            case 'rb':
350
+                try {
351
+                    $response = $this->httpClientService
352
+                        ->newClient()
353
+                        ->get($this->createBaseUri() . $this->encodePath($path), [
354
+                            'auth' => [$this->user, $this->password],
355
+                            'stream' => true
356
+                        ]);
357
+                } catch (\GuzzleHttp\Exception\ClientException $e) {
358
+                    if ($e->getResponse() instanceof ResponseInterface
359
+                        && $e->getResponse()->getStatusCode() === 404) {
360
+                        return false;
361
+                    } else {
362
+                        throw $e;
363
+                    }
364
+                }
365
+
366
+                if ($response->getStatusCode() !== Http::STATUS_OK) {
367
+                    if ($response->getStatusCode() === Http::STATUS_LOCKED) {
368
+                        throw new \OCP\Lock\LockedException($path);
369
+                    } else {
370
+                        Util::writeLog("webdav client", 'Guzzle get returned status code ' . $response->getStatusCode(), ILogger::ERROR);
371
+                    }
372
+                }
373
+
374
+                return $response->getBody();
375
+            case 'w':
376
+            case 'wb':
377
+            case 'a':
378
+            case 'ab':
379
+            case 'r+':
380
+            case 'w+':
381
+            case 'wb+':
382
+            case 'a+':
383
+            case 'x':
384
+            case 'x+':
385
+            case 'c':
386
+            case 'c+':
387
+                //emulate these
388
+                $tempManager = \OC::$server->getTempManager();
389
+                if (strrpos($path, '.') !== false) {
390
+                    $ext = substr($path, strrpos($path, '.'));
391
+                } else {
392
+                    $ext = '';
393
+                }
394
+                if ($this->file_exists($path)) {
395
+                    if (!$this->isUpdatable($path)) {
396
+                        return false;
397
+                    }
398
+                    if ($mode === 'w' or $mode === 'w+') {
399
+                        $tmpFile = $tempManager->getTemporaryFile($ext);
400
+                    } else {
401
+                        $tmpFile = $this->getCachedFile($path);
402
+                    }
403
+                } else {
404
+                    if (!$this->isCreatable(dirname($path))) {
405
+                        return false;
406
+                    }
407
+                    $tmpFile = $tempManager->getTemporaryFile($ext);
408
+                }
409
+                $handle = fopen($tmpFile, $mode);
410
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
411
+                    $this->writeBack($tmpFile, $path);
412
+                });
413
+        }
414
+    }
415
+
416
+    /**
417
+     * @param string $tmpFile
418
+     */
419
+    public function writeBack($tmpFile, $path) {
420
+        $this->uploadFile($tmpFile, $path);
421
+        unlink($tmpFile);
422
+    }
423
+
424
+    /** {@inheritdoc} */
425
+    public function free_space($path) {
426
+        $this->init();
427
+        $path = $this->cleanPath($path);
428
+        try {
429
+            // TODO: cacheable ?
430
+            $response = $this->client->propfind($this->encodePath($path), ['{DAV:}quota-available-bytes']);
431
+            if ($response === false) {
432
+                return FileInfo::SPACE_UNKNOWN;
433
+            }
434
+            if (isset($response['{DAV:}quota-available-bytes'])) {
435
+                return (int)$response['{DAV:}quota-available-bytes'];
436
+            } else {
437
+                return FileInfo::SPACE_UNKNOWN;
438
+            }
439
+        } catch (\Exception $e) {
440
+            return FileInfo::SPACE_UNKNOWN;
441
+        }
442
+    }
443
+
444
+    /** {@inheritdoc} */
445
+    public function touch($path, $mtime = null) {
446
+        $this->init();
447
+        if (is_null($mtime)) {
448
+            $mtime = time();
449
+        }
450
+        $path = $this->cleanPath($path);
451
+
452
+        // if file exists, update the mtime, else create a new empty file
453
+        if ($this->file_exists($path)) {
454
+            try {
455
+                $this->statCache->remove($path);
456
+                $this->client->proppatch($this->encodePath($path), ['{DAV:}lastmodified' => $mtime]);
457
+                // non-owncloud clients might not have accepted the property, need to recheck it
458
+                $response = $this->client->propfind($this->encodePath($path), ['{DAV:}getlastmodified'], 0);
459
+                if ($response === false) {
460
+                    return false;
461
+                }
462
+                if (isset($response['{DAV:}getlastmodified'])) {
463
+                    $remoteMtime = strtotime($response['{DAV:}getlastmodified']);
464
+                    if ($remoteMtime !== $mtime) {
465
+                        // server has not accepted the mtime
466
+                        return false;
467
+                    }
468
+                }
469
+            } catch (ClientHttpException $e) {
470
+                if ($e->getHttpStatus() === 501) {
471
+                    return false;
472
+                }
473
+                $this->convertException($e, $path);
474
+                return false;
475
+            } catch (\Exception $e) {
476
+                $this->convertException($e, $path);
477
+                return false;
478
+            }
479
+        } else {
480
+            $this->file_put_contents($path, '');
481
+        }
482
+        return true;
483
+    }
484
+
485
+    /**
486
+     * @param string $path
487
+     * @param string $data
488
+     * @return int
489
+     */
490
+    public function file_put_contents($path, $data) {
491
+        $path = $this->cleanPath($path);
492
+        $result = parent::file_put_contents($path, $data);
493
+        $this->statCache->remove($path);
494
+        return $result;
495
+    }
496
+
497
+    /**
498
+     * @param string $path
499
+     * @param string $target
500
+     */
501
+    protected function uploadFile($path, $target) {
502
+        $this->init();
503
+
504
+        // invalidate
505
+        $target = $this->cleanPath($target);
506
+        $this->statCache->remove($target);
507
+        $source = fopen($path, 'r');
508
+
509
+        $this->httpClientService
510
+            ->newClient()
511
+            ->put($this->createBaseUri() . $this->encodePath($target), [
512
+                'body' => $source,
513
+                'auth' => [$this->user, $this->password]
514
+            ]);
515
+
516
+        $this->removeCachedFile($target);
517
+    }
518
+
519
+    /** {@inheritdoc} */
520
+    public function rename($path1, $path2) {
521
+        $this->init();
522
+        $path1 = $this->cleanPath($path1);
523
+        $path2 = $this->cleanPath($path2);
524
+        try {
525
+            // overwrite directory ?
526
+            if ($this->is_dir($path2)) {
527
+                // needs trailing slash in destination
528
+                $path2 = rtrim($path2, '/') . '/';
529
+            }
530
+            $this->client->request(
531
+                'MOVE',
532
+                $this->encodePath($path1),
533
+                null,
534
+                [
535
+                    'Destination' => $this->createBaseUri() . $this->encodePath($path2),
536
+                ]
537
+            );
538
+            $this->statCache->clear($path1 . '/');
539
+            $this->statCache->clear($path2 . '/');
540
+            $this->statCache->set($path1, false);
541
+            $this->statCache->set($path2, true);
542
+            $this->removeCachedFile($path1);
543
+            $this->removeCachedFile($path2);
544
+            return true;
545
+        } catch (\Exception $e) {
546
+            $this->convertException($e);
547
+        }
548
+        return false;
549
+    }
550
+
551
+    /** {@inheritdoc} */
552
+    public function copy($path1, $path2) {
553
+        $this->init();
554
+        $path1 = $this->cleanPath($path1);
555
+        $path2 = $this->cleanPath($path2);
556
+        try {
557
+            // overwrite directory ?
558
+            if ($this->is_dir($path2)) {
559
+                // needs trailing slash in destination
560
+                $path2 = rtrim($path2, '/') . '/';
561
+            }
562
+            $this->client->request(
563
+                'COPY',
564
+                $this->encodePath($path1),
565
+                null,
566
+                [
567
+                    'Destination' => $this->createBaseUri() . $this->encodePath($path2),
568
+                ]
569
+            );
570
+            $this->statCache->clear($path2 . '/');
571
+            $this->statCache->set($path2, true);
572
+            $this->removeCachedFile($path2);
573
+            return true;
574
+        } catch (\Exception $e) {
575
+            $this->convertException($e);
576
+        }
577
+        return false;
578
+    }
579
+
580
+    /** {@inheritdoc} */
581
+    public function stat($path) {
582
+        try {
583
+            $response = $this->propfind($path);
584
+            if (!$response) {
585
+                return false;
586
+            }
587
+            return [
588
+                'mtime' => strtotime($response['{DAV:}getlastmodified']),
589
+                'size' => (int)isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0,
590
+            ];
591
+        } catch (\Exception $e) {
592
+            $this->convertException($e, $path);
593
+        }
594
+        return [];
595
+    }
596
+
597
+    /** {@inheritdoc} */
598
+    public function getMimeType($path) {
599
+        $remoteMimetype = $this->getMimeTypeFromRemote($path);
600
+        if ($remoteMimetype === 'application/octet-stream') {
601
+            return \OC::$server->getMimeTypeDetector()->detectPath($path);
602
+        } else {
603
+            return $remoteMimetype;
604
+        }
605
+    }
606
+
607
+    public function getMimeTypeFromRemote($path) {
608
+        try {
609
+            $response = $this->propfind($path);
610
+            if ($response === false) {
611
+                return false;
612
+            }
613
+            $responseType = [];
614
+            if (isset($response["{DAV:}resourcetype"])) {
615
+                /** @var ResourceType[] $response */
616
+                $responseType = $response["{DAV:}resourcetype"]->getValue();
617
+            }
618
+            $type = (count($responseType) > 0 and $responseType[0] == "{DAV:}collection") ? 'dir' : 'file';
619
+            if ($type == 'dir') {
620
+                return 'httpd/unix-directory';
621
+            } elseif (isset($response['{DAV:}getcontenttype'])) {
622
+                return $response['{DAV:}getcontenttype'];
623
+            } else {
624
+                return 'application/octet-stream';
625
+            }
626
+        } catch (\Exception $e) {
627
+            return false;
628
+        }
629
+    }
630
+
631
+    /**
632
+     * @param string $path
633
+     * @return string
634
+     */
635
+    public function cleanPath($path) {
636
+        if ($path === '') {
637
+            return $path;
638
+        }
639
+        $path = Filesystem::normalizePath($path);
640
+        // remove leading slash
641
+        return substr($path, 1);
642
+    }
643
+
644
+    /**
645
+     * URL encodes the given path but keeps the slashes
646
+     *
647
+     * @param string $path to encode
648
+     * @return string encoded path
649
+     */
650
+    protected function encodePath($path) {
651
+        // slashes need to stay
652
+        return str_replace('%2F', '/', rawurlencode($path));
653
+    }
654
+
655
+    /**
656
+     * @param string $method
657
+     * @param string $path
658
+     * @param string|resource|null $body
659
+     * @param int $expected
660
+     * @return bool
661
+     * @throws StorageInvalidException
662
+     * @throws StorageNotAvailableException
663
+     */
664
+    protected function simpleResponse($method, $path, $body, $expected) {
665
+        $path = $this->cleanPath($path);
666
+        try {
667
+            $response = $this->client->request($method, $this->encodePath($path), $body);
668
+            return $response['statusCode'] == $expected;
669
+        } catch (ClientHttpException $e) {
670
+            if ($e->getHttpStatus() === 404 && $method === 'DELETE') {
671
+                $this->statCache->clear($path . '/');
672
+                $this->statCache->set($path, false);
673
+                return false;
674
+            }
675
+
676
+            $this->convertException($e, $path);
677
+        } catch (\Exception $e) {
678
+            $this->convertException($e, $path);
679
+        }
680
+        return false;
681
+    }
682
+
683
+    /**
684
+     * check if curl is installed
685
+     */
686
+    public static function checkDependencies() {
687
+        return true;
688
+    }
689
+
690
+    /** {@inheritdoc} */
691
+    public function isUpdatable($path) {
692
+        return (bool)($this->getPermissions($path) & Constants::PERMISSION_UPDATE);
693
+    }
694
+
695
+    /** {@inheritdoc} */
696
+    public function isCreatable($path) {
697
+        return (bool)($this->getPermissions($path) & Constants::PERMISSION_CREATE);
698
+    }
699
+
700
+    /** {@inheritdoc} */
701
+    public function isSharable($path) {
702
+        return (bool)($this->getPermissions($path) & Constants::PERMISSION_SHARE);
703
+    }
704
+
705
+    /** {@inheritdoc} */
706
+    public function isDeletable($path) {
707
+        return (bool)($this->getPermissions($path) & Constants::PERMISSION_DELETE);
708
+    }
709
+
710
+    /** {@inheritdoc} */
711
+    public function getPermissions($path) {
712
+        $this->init();
713
+        $path = $this->cleanPath($path);
714
+        $response = $this->propfind($path);
715
+        if ($response === false) {
716
+            return 0;
717
+        }
718
+        if (isset($response['{http://owncloud.org/ns}permissions'])) {
719
+            return $this->parsePermissions($response['{http://owncloud.org/ns}permissions']);
720
+        } else if ($this->is_dir($path)) {
721
+            return Constants::PERMISSION_ALL;
722
+        } else if ($this->file_exists($path)) {
723
+            return Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE;
724
+        } else {
725
+            return 0;
726
+        }
727
+    }
728
+
729
+    /** {@inheritdoc} */
730
+    public function getETag($path) {
731
+        $this->init();
732
+        $path = $this->cleanPath($path);
733
+        $response = $this->propfind($path);
734
+        if ($response === false) {
735
+            return null;
736
+        }
737
+        if (isset($response['{DAV:}getetag'])) {
738
+            $etag = trim($response['{DAV:}getetag'], '"');
739
+            if (strlen($etag) > 40) {
740
+                $etag = md5($etag);
741
+            }
742
+            return $etag;
743
+        }
744
+        return parent::getEtag($path);
745
+    }
746
+
747
+    /**
748
+     * @param string $permissionsString
749
+     * @return int
750
+     */
751
+    protected function parsePermissions($permissionsString) {
752
+        $permissions = Constants::PERMISSION_READ;
753
+        if (strpos($permissionsString, 'R') !== false) {
754
+            $permissions |= Constants::PERMISSION_SHARE;
755
+        }
756
+        if (strpos($permissionsString, 'D') !== false) {
757
+            $permissions |= Constants::PERMISSION_DELETE;
758
+        }
759
+        if (strpos($permissionsString, 'W') !== false) {
760
+            $permissions |= Constants::PERMISSION_UPDATE;
761
+        }
762
+        if (strpos($permissionsString, 'CK') !== false) {
763
+            $permissions |= Constants::PERMISSION_CREATE;
764
+            $permissions |= Constants::PERMISSION_UPDATE;
765
+        }
766
+        return $permissions;
767
+    }
768
+
769
+    /**
770
+     * check if a file or folder has been updated since $time
771
+     *
772
+     * @param string $path
773
+     * @param int $time
774
+     * @throws \OCP\Files\StorageNotAvailableException
775
+     * @return bool
776
+     */
777
+    public function hasUpdated($path, $time) {
778
+        $this->init();
779
+        $path = $this->cleanPath($path);
780
+        try {
781
+            // force refresh for $path
782
+            $this->statCache->remove($path);
783
+            $response = $this->propfind($path);
784
+            if ($response === false) {
785
+                if ($path === '') {
786
+                    // if root is gone it means the storage is not available
787
+                    throw new StorageNotAvailableException('root is gone');
788
+                }
789
+                return false;
790
+            }
791
+            if (isset($response['{DAV:}getetag'])) {
792
+                $cachedData = $this->getCache()->get($path);
793
+                $etag = null;
794
+                if (isset($response['{DAV:}getetag'])) {
795
+                    $etag = trim($response['{DAV:}getetag'], '"');
796
+                }
797
+                if (!empty($etag) && $cachedData['etag'] !== $etag) {
798
+                    return true;
799
+                } else if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
800
+                    $sharePermissions = (int)$response['{http://open-collaboration-services.org/ns}share-permissions'];
801
+                    return $sharePermissions !== $cachedData['permissions'];
802
+                } else if (isset($response['{http://owncloud.org/ns}permissions'])) {
803
+                    $permissions = $this->parsePermissions($response['{http://owncloud.org/ns}permissions']);
804
+                    return $permissions !== $cachedData['permissions'];
805
+                } else {
806
+                    return false;
807
+                }
808
+            } else {
809
+                $remoteMtime = strtotime($response['{DAV:}getlastmodified']);
810
+                return $remoteMtime > $time;
811
+            }
812
+        } catch (ClientHttpException $e) {
813
+            if ($e->getHttpStatus() === 405) {
814
+                if ($path === '') {
815
+                    // if root is gone it means the storage is not available
816
+                    throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
817
+                }
818
+                return false;
819
+            }
820
+            $this->convertException($e, $path);
821
+            return false;
822
+        } catch (\Exception $e) {
823
+            $this->convertException($e, $path);
824
+            return false;
825
+        }
826
+    }
827
+
828
+    /**
829
+     * Interpret the given exception and decide whether it is due to an
830
+     * unavailable storage, invalid storage or other.
831
+     * This will either throw StorageInvalidException, StorageNotAvailableException
832
+     * or do nothing.
833
+     *
834
+     * @param Exception $e sabre exception
835
+     * @param string $path optional path from the operation
836
+     *
837
+     * @throws StorageInvalidException if the storage is invalid, for example
838
+     * when the authentication expired or is invalid
839
+     * @throws StorageNotAvailableException if the storage is not available,
840
+     * which might be temporary
841
+     * @throws ForbiddenException if the action is not allowed
842
+     */
843
+    protected function convertException(Exception $e, $path = '') {
844
+        \OC::$server->getLogger()->logException($e, ['app' => 'files_external', 'level' => ILogger::DEBUG]);
845
+        if ($e instanceof ClientHttpException) {
846
+            if ($e->getHttpStatus() === Http::STATUS_LOCKED) {
847
+                throw new \OCP\Lock\LockedException($path);
848
+            }
849
+            if ($e->getHttpStatus() === Http::STATUS_UNAUTHORIZED) {
850
+                // either password was changed or was invalid all along
851
+                throw new StorageInvalidException(get_class($e) . ': ' . $e->getMessage());
852
+            } else if ($e->getHttpStatus() === Http::STATUS_METHOD_NOT_ALLOWED) {
853
+                // ignore exception for MethodNotAllowed, false will be returned
854
+                return;
855
+            } else if ($e->getHttpStatus() === Http::STATUS_FORBIDDEN){
856
+                // The operation is forbidden. Fail somewhat gracefully
857
+                throw new ForbiddenException(get_class($e) . ':' . $e->getMessage());
858
+            }
859
+            throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
860
+        } else if ($e instanceof ClientException) {
861
+            // connection timeout or refused, server could be temporarily down
862
+            throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
863
+        } else if ($e instanceof \InvalidArgumentException) {
864
+            // parse error because the server returned HTML instead of XML,
865
+            // possibly temporarily down
866
+            throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
867
+        } else if (($e instanceof StorageNotAvailableException) || ($e instanceof StorageInvalidException)) {
868
+            // rethrow
869
+            throw $e;
870
+        }
871
+
872
+        // TODO: only log for now, but in the future need to wrap/rethrow exception
873
+    }
874 874
 }
Please login to merge, or discard this patch.
lib/private/Files/Storage/Storage.php 1 patch
Indentation   +75 added lines, -75 removed lines patch added patch discarded remove patch
@@ -32,90 +32,90 @@
 block discarded – undo
32 32
  */
33 33
 interface Storage extends \OCP\Files\Storage {
34 34
 
35
-	/**
36
-	 * get a cache instance for the storage
37
-	 *
38
-	 * @param string $path
39
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache
40
-	 * @return \OC\Files\Cache\Cache
41
-	 */
42
-	public function getCache($path = '', $storage = null);
35
+    /**
36
+     * get a cache instance for the storage
37
+     *
38
+     * @param string $path
39
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache
40
+     * @return \OC\Files\Cache\Cache
41
+     */
42
+    public function getCache($path = '', $storage = null);
43 43
 
44
-	/**
45
-	 * get a scanner instance for the storage
46
-	 *
47
-	 * @param string $path
48
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
49
-	 * @return \OC\Files\Cache\Scanner
50
-	 */
51
-	public function getScanner($path = '', $storage = null);
44
+    /**
45
+     * get a scanner instance for the storage
46
+     *
47
+     * @param string $path
48
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
49
+     * @return \OC\Files\Cache\Scanner
50
+     */
51
+    public function getScanner($path = '', $storage = null);
52 52
 
53 53
 
54
-	/**
55
-	 * get the user id of the owner of a file or folder
56
-	 *
57
-	 * @param string $path
58
-	 * @return string
59
-	 */
60
-	public function getOwner($path);
54
+    /**
55
+     * get the user id of the owner of a file or folder
56
+     *
57
+     * @param string $path
58
+     * @return string
59
+     */
60
+    public function getOwner($path);
61 61
 
62
-	/**
63
-	 * get a watcher instance for the cache
64
-	 *
65
-	 * @param string $path
66
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
67
-	 * @return \OC\Files\Cache\Watcher
68
-	 */
69
-	public function getWatcher($path = '', $storage = null);
62
+    /**
63
+     * get a watcher instance for the cache
64
+     *
65
+     * @param string $path
66
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
67
+     * @return \OC\Files\Cache\Watcher
68
+     */
69
+    public function getWatcher($path = '', $storage = null);
70 70
 
71
-	/**
72
-	 * get a propagator instance for the cache
73
-	 *
74
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
75
-	 * @return \OC\Files\Cache\Propagator
76
-	 */
77
-	public function getPropagator($storage = null);
71
+    /**
72
+     * get a propagator instance for the cache
73
+     *
74
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
75
+     * @return \OC\Files\Cache\Propagator
76
+     */
77
+    public function getPropagator($storage = null);
78 78
 
79
-	/**
80
-	 * get a updater instance for the cache
81
-	 *
82
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
83
-	 * @return \OC\Files\Cache\Updater
84
-	 */
85
-	public function getUpdater($storage = null);
79
+    /**
80
+     * get a updater instance for the cache
81
+     *
82
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
83
+     * @return \OC\Files\Cache\Updater
84
+     */
85
+    public function getUpdater($storage = null);
86 86
 
87
-	/**
88
-	 * @return \OC\Files\Cache\Storage
89
-	 */
90
-	public function getStorageCache();
87
+    /**
88
+     * @return \OC\Files\Cache\Storage
89
+     */
90
+    public function getStorageCache();
91 91
 
92
-	/**
93
-	 * @param string $path
94
-	 * @return array
95
-	 */
96
-	public function getMetaData($path);
92
+    /**
93
+     * @param string $path
94
+     * @return array
95
+     */
96
+    public function getMetaData($path);
97 97
 
98
-	/**
99
-	 * @param string $path The path of the file to acquire the lock for
100
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
101
-	 * @param \OCP\Lock\ILockingProvider $provider
102
-	 * @throws \OCP\Lock\LockedException
103
-	 */
104
-	public function acquireLock($path, $type, ILockingProvider $provider);
98
+    /**
99
+     * @param string $path The path of the file to acquire the lock for
100
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
101
+     * @param \OCP\Lock\ILockingProvider $provider
102
+     * @throws \OCP\Lock\LockedException
103
+     */
104
+    public function acquireLock($path, $type, ILockingProvider $provider);
105 105
 
106
-	/**
107
-	 * @param string $path The path of the file to release the lock for
108
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
109
-	 * @param \OCP\Lock\ILockingProvider $provider
110
-	 * @throws \OCP\Lock\LockedException
111
-	 */
112
-	public function releaseLock($path, $type, ILockingProvider $provider);
106
+    /**
107
+     * @param string $path The path of the file to release the lock for
108
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
109
+     * @param \OCP\Lock\ILockingProvider $provider
110
+     * @throws \OCP\Lock\LockedException
111
+     */
112
+    public function releaseLock($path, $type, ILockingProvider $provider);
113 113
 
114
-	/**
115
-	 * @param string $path The path of the file to change the lock for
116
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
117
-	 * @param \OCP\Lock\ILockingProvider $provider
118
-	 * @throws \OCP\Lock\LockedException
119
-	 */
120
-	public function changeLock($path, $type, ILockingProvider $provider);
114
+    /**
115
+     * @param string $path The path of the file to change the lock for
116
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
117
+     * @param \OCP\Lock\ILockingProvider $provider
118
+     * @throws \OCP\Lock\LockedException
119
+     */
120
+    public function changeLock($path, $type, ILockingProvider $provider);
121 121
 }
Please login to merge, or discard this patch.
lib/private/Files/Storage/LocalTempFileTrait.php 1 patch
Indentation   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -37,45 +37,45 @@
 block discarded – undo
37 37
  */
38 38
 trait LocalTempFileTrait {
39 39
 
40
-	/** @var string[] */
41
-	protected $cachedFiles = [];
40
+    /** @var string[] */
41
+    protected $cachedFiles = [];
42 42
 
43
-	/**
44
-	 * @param string $path
45
-	 * @return string
46
-	 */
47
-	protected function getCachedFile($path) {
48
-		if (!isset($this->cachedFiles[$path])) {
49
-			$this->cachedFiles[$path] = $this->toTmpFile($path);
50
-		}
51
-		return $this->cachedFiles[$path];
52
-	}
43
+    /**
44
+     * @param string $path
45
+     * @return string
46
+     */
47
+    protected function getCachedFile($path) {
48
+        if (!isset($this->cachedFiles[$path])) {
49
+            $this->cachedFiles[$path] = $this->toTmpFile($path);
50
+        }
51
+        return $this->cachedFiles[$path];
52
+    }
53 53
 
54
-	/**
55
-	 * @param string $path
56
-	 */
57
-	protected function removeCachedFile($path) {
58
-		unset($this->cachedFiles[$path]);
59
-	}
54
+    /**
55
+     * @param string $path
56
+     */
57
+    protected function removeCachedFile($path) {
58
+        unset($this->cachedFiles[$path]);
59
+    }
60 60
 
61
-	/**
62
-	 * @param string $path
63
-	 * @return string
64
-	 */
65
-	protected function toTmpFile($path) { //no longer in the storage api, still useful here
66
-		$source = $this->fopen($path, 'r');
67
-		if (!$source) {
68
-			return false;
69
-		}
70
-		if ($pos = strrpos($path, '.')) {
71
-			$extension = substr($path, $pos);
72
-		} else {
73
-			$extension = '';
74
-		}
75
-		$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($extension);
76
-		$target = fopen($tmpFile, 'w');
77
-		\OC_Helper::streamCopy($source, $target);
78
-		fclose($target);
79
-		return $tmpFile;
80
-	}
61
+    /**
62
+     * @param string $path
63
+     * @return string
64
+     */
65
+    protected function toTmpFile($path) { //no longer in the storage api, still useful here
66
+        $source = $this->fopen($path, 'r');
67
+        if (!$source) {
68
+            return false;
69
+        }
70
+        if ($pos = strrpos($path, '.')) {
71
+            $extension = substr($path, $pos);
72
+        } else {
73
+            $extension = '';
74
+        }
75
+        $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($extension);
76
+        $target = fopen($tmpFile, 'w');
77
+        \OC_Helper::streamCopy($source, $target);
78
+        fclose($target);
79
+        return $tmpFile;
80
+    }
81 81
 }
Please login to merge, or discard this patch.
lib/private/Files/Storage/Common.php 3 patches
Braces   +3 added lines, -1 removed lines patch added patch discarded remove patch
@@ -289,7 +289,9 @@
 block discarded – undo
289 289
 		$dh = $this->opendir($dir);
290 290
 		if (is_resource($dh)) {
291 291
 			while (($item = readdir($dh)) !== false) {
292
-				if (\OC\Files\Filesystem::isIgnoredDir($item)) continue;
292
+				if (\OC\Files\Filesystem::isIgnoredDir($item)) {
293
+				    continue;
294
+				}
293 295
 				if (strstr(strtolower($item), strtolower($query)) !== false) {
294 296
 					$files[] = $dir . '/' . $item;
295 297
 				}
Please login to merge, or discard this patch.
Indentation   +782 added lines, -782 removed lines patch added patch discarded remove patch
@@ -76,790 +76,790 @@
 block discarded – undo
76 76
  */
77 77
 abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
78 78
 
79
-	use LocalTempFileTrait;
80
-
81
-	protected $cache;
82
-	protected $scanner;
83
-	protected $watcher;
84
-	protected $propagator;
85
-	protected $storageCache;
86
-	protected $updater;
87
-
88
-	protected $mountOptions = [];
89
-	protected $owner = null;
90
-
91
-	private $shouldLogLocks = null;
92
-	private $logger;
93
-
94
-	public function __construct($parameters) {
95
-	}
96
-
97
-	/**
98
-	 * Remove a file or folder
99
-	 *
100
-	 * @param string $path
101
-	 * @return bool
102
-	 */
103
-	protected function remove($path) {
104
-		if ($this->is_dir($path)) {
105
-			return $this->rmdir($path);
106
-		} else if ($this->is_file($path)) {
107
-			return $this->unlink($path);
108
-		} else {
109
-			return false;
110
-		}
111
-	}
112
-
113
-	public function is_dir($path) {
114
-		return $this->filetype($path) === 'dir';
115
-	}
116
-
117
-	public function is_file($path) {
118
-		return $this->filetype($path) === 'file';
119
-	}
120
-
121
-	public function filesize($path) {
122
-		if ($this->is_dir($path)) {
123
-			return 0; //by definition
124
-		} else {
125
-			$stat = $this->stat($path);
126
-			if (isset($stat['size'])) {
127
-				return $stat['size'];
128
-			} else {
129
-				return 0;
130
-			}
131
-		}
132
-	}
133
-
134
-	public function isReadable($path) {
135
-		// at least check whether it exists
136
-		// subclasses might want to implement this more thoroughly
137
-		return $this->file_exists($path);
138
-	}
139
-
140
-	public function isUpdatable($path) {
141
-		// at least check whether it exists
142
-		// subclasses might want to implement this more thoroughly
143
-		// a non-existing file/folder isn't updatable
144
-		return $this->file_exists($path);
145
-	}
146
-
147
-	public function isCreatable($path) {
148
-		if ($this->is_dir($path) && $this->isUpdatable($path)) {
149
-			return true;
150
-		}
151
-		return false;
152
-	}
153
-
154
-	public function isDeletable($path) {
155
-		if ($path === '' || $path === '/') {
156
-			return false;
157
-		}
158
-		$parent = dirname($path);
159
-		return $this->isUpdatable($parent) && $this->isUpdatable($path);
160
-	}
161
-
162
-	public function isSharable($path) {
163
-		return $this->isReadable($path);
164
-	}
165
-
166
-	public function getPermissions($path) {
167
-		$permissions = 0;
168
-		if ($this->isCreatable($path)) {
169
-			$permissions |= \OCP\Constants::PERMISSION_CREATE;
170
-		}
171
-		if ($this->isReadable($path)) {
172
-			$permissions |= \OCP\Constants::PERMISSION_READ;
173
-		}
174
-		if ($this->isUpdatable($path)) {
175
-			$permissions |= \OCP\Constants::PERMISSION_UPDATE;
176
-		}
177
-		if ($this->isDeletable($path)) {
178
-			$permissions |= \OCP\Constants::PERMISSION_DELETE;
179
-		}
180
-		if ($this->isSharable($path)) {
181
-			$permissions |= \OCP\Constants::PERMISSION_SHARE;
182
-		}
183
-		return $permissions;
184
-	}
185
-
186
-	public function filemtime($path) {
187
-		$stat = $this->stat($path);
188
-		if (isset($stat['mtime']) && $stat['mtime'] > 0) {
189
-			return $stat['mtime'];
190
-		} else {
191
-			return 0;
192
-		}
193
-	}
194
-
195
-	public function file_get_contents($path) {
196
-		$handle = $this->fopen($path, "r");
197
-		if (!$handle) {
198
-			return false;
199
-		}
200
-		$data = stream_get_contents($handle);
201
-		fclose($handle);
202
-		return $data;
203
-	}
204
-
205
-	public function file_put_contents($path, $data) {
206
-		$handle = $this->fopen($path, "w");
207
-		$this->removeCachedFile($path);
208
-		$count = fwrite($handle, $data);
209
-		fclose($handle);
210
-		return $count;
211
-	}
212
-
213
-	public function rename($path1, $path2) {
214
-		$this->remove($path2);
215
-
216
-		$this->removeCachedFile($path1);
217
-		return $this->copy($path1, $path2) and $this->remove($path1);
218
-	}
219
-
220
-	public function copy($path1, $path2) {
221
-		if ($this->is_dir($path1)) {
222
-			$this->remove($path2);
223
-			$dir = $this->opendir($path1);
224
-			$this->mkdir($path2);
225
-			while ($file = readdir($dir)) {
226
-				if (!Filesystem::isIgnoredDir($file)) {
227
-					if (!$this->copy($path1 . '/' . $file, $path2 . '/' . $file)) {
228
-						return false;
229
-					}
230
-				}
231
-			}
232
-			closedir($dir);
233
-			return true;
234
-		} else {
235
-			$source = $this->fopen($path1, 'r');
236
-			$target = $this->fopen($path2, 'w');
237
-			list(, $result) = \OC_Helper::streamCopy($source, $target);
238
-			if (!$result) {
239
-				\OC::$server->getLogger()->warning("Failed to write data while copying $path1 to $path2");
240
-			}
241
-			$this->removeCachedFile($path2);
242
-			return $result;
243
-		}
244
-	}
245
-
246
-	public function getMimeType($path) {
247
-		if ($this->is_dir($path)) {
248
-			return 'httpd/unix-directory';
249
-		} elseif ($this->file_exists($path)) {
250
-			return \OC::$server->getMimeTypeDetector()->detectPath($path);
251
-		} else {
252
-			return false;
253
-		}
254
-	}
255
-
256
-	public function hash($type, $path, $raw = false) {
257
-		$fh = $this->fopen($path, 'rb');
258
-		$ctx = hash_init($type);
259
-		hash_update_stream($ctx, $fh);
260
-		fclose($fh);
261
-		return hash_final($ctx, $raw);
262
-	}
263
-
264
-	public function search($query) {
265
-		return $this->searchInDir($query);
266
-	}
267
-
268
-	public function getLocalFile($path) {
269
-		return $this->getCachedFile($path);
270
-	}
271
-
272
-	/**
273
-	 * @param string $path
274
-	 * @param string $target
275
-	 */
276
-	private function addLocalFolder($path, $target) {
277
-		$dh = $this->opendir($path);
278
-		if (is_resource($dh)) {
279
-			while (($file = readdir($dh)) !== false) {
280
-				if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
281
-					if ($this->is_dir($path . '/' . $file)) {
282
-						mkdir($target . '/' . $file);
283
-						$this->addLocalFolder($path . '/' . $file, $target . '/' . $file);
284
-					} else {
285
-						$tmp = $this->toTmpFile($path . '/' . $file);
286
-						rename($tmp, $target . '/' . $file);
287
-					}
288
-				}
289
-			}
290
-		}
291
-	}
292
-
293
-	/**
294
-	 * @param string $query
295
-	 * @param string $dir
296
-	 * @return array
297
-	 */
298
-	protected function searchInDir($query, $dir = '') {
299
-		$files = [];
300
-		$dh = $this->opendir($dir);
301
-		if (is_resource($dh)) {
302
-			while (($item = readdir($dh)) !== false) {
303
-				if (\OC\Files\Filesystem::isIgnoredDir($item)) continue;
304
-				if (strstr(strtolower($item), strtolower($query)) !== false) {
305
-					$files[] = $dir . '/' . $item;
306
-				}
307
-				if ($this->is_dir($dir . '/' . $item)) {
308
-					$files = array_merge($files, $this->searchInDir($query, $dir . '/' . $item));
309
-				}
310
-			}
311
-		}
312
-		closedir($dh);
313
-		return $files;
314
-	}
315
-
316
-	/**
317
-	 * check if a file or folder has been updated since $time
318
-	 *
319
-	 * The method is only used to check if the cache needs to be updated. Storage backends that don't support checking
320
-	 * the mtime should always return false here. As a result storage implementations that always return false expect
321
-	 * exclusive access to the backend and will not pick up files that have been added in a way that circumvents
322
-	 * ownClouds filesystem.
323
-	 *
324
-	 * @param string $path
325
-	 * @param int $time
326
-	 * @return bool
327
-	 */
328
-	public function hasUpdated($path, $time) {
329
-		return $this->filemtime($path) > $time;
330
-	}
331
-
332
-	public function getCache($path = '', $storage = null) {
333
-		if (!$storage) {
334
-			$storage = $this;
335
-		}
336
-		if (!isset($storage->cache)) {
337
-			$storage->cache = new Cache($storage);
338
-		}
339
-		return $storage->cache;
340
-	}
341
-
342
-	public function getScanner($path = '', $storage = null) {
343
-		if (!$storage) {
344
-			$storage = $this;
345
-		}
346
-		if (!isset($storage->scanner)) {
347
-			$storage->scanner = new Scanner($storage);
348
-		}
349
-		return $storage->scanner;
350
-	}
351
-
352
-	public function getWatcher($path = '', $storage = null) {
353
-		if (!$storage) {
354
-			$storage = $this;
355
-		}
356
-		if (!isset($this->watcher)) {
357
-			$this->watcher = new Watcher($storage);
358
-			$globalPolicy = \OC::$server->getConfig()->getSystemValue('filesystem_check_changes', Watcher::CHECK_NEVER);
359
-			$this->watcher->setPolicy((int)$this->getMountOption('filesystem_check_changes', $globalPolicy));
360
-		}
361
-		return $this->watcher;
362
-	}
363
-
364
-	/**
365
-	 * get a propagator instance for the cache
366
-	 *
367
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
368
-	 * @return \OC\Files\Cache\Propagator
369
-	 */
370
-	public function getPropagator($storage = null) {
371
-		if (!$storage) {
372
-			$storage = $this;
373
-		}
374
-		if (!isset($storage->propagator)) {
375
-			$config = \OC::$server->getSystemConfig();
376
-			$storage->propagator = new Propagator($storage, \OC::$server->getDatabaseConnection(), ['appdata_' . $config->getValue('instanceid')]);
377
-		}
378
-		return $storage->propagator;
379
-	}
380
-
381
-	public function getUpdater($storage = null) {
382
-		if (!$storage) {
383
-			$storage = $this;
384
-		}
385
-		if (!isset($storage->updater)) {
386
-			$storage->updater = new Updater($storage);
387
-		}
388
-		return $storage->updater;
389
-	}
390
-
391
-	public function getStorageCache($storage = null) {
392
-		if (!$storage) {
393
-			$storage = $this;
394
-		}
395
-		if (!isset($this->storageCache)) {
396
-			$this->storageCache = new \OC\Files\Cache\Storage($storage);
397
-		}
398
-		return $this->storageCache;
399
-	}
400
-
401
-	/**
402
-	 * get the owner of a path
403
-	 *
404
-	 * @param string $path The path to get the owner
405
-	 * @return string|false uid or false
406
-	 */
407
-	public function getOwner($path) {
408
-		if ($this->owner === null) {
409
-			$this->owner = \OC_User::getUser();
410
-		}
411
-
412
-		return $this->owner;
413
-	}
414
-
415
-	/**
416
-	 * get the ETag for a file or folder
417
-	 *
418
-	 * @param string $path
419
-	 * @return string
420
-	 */
421
-	public function getETag($path) {
422
-		return uniqid();
423
-	}
424
-
425
-	/**
426
-	 * clean a path, i.e. remove all redundant '.' and '..'
427
-	 * making sure that it can't point to higher than '/'
428
-	 *
429
-	 * @param string $path The path to clean
430
-	 * @return string cleaned path
431
-	 */
432
-	public function cleanPath($path) {
433
-		if (strlen($path) == 0 or $path[0] != '/') {
434
-			$path = '/' . $path;
435
-		}
436
-
437
-		$output = [];
438
-		foreach (explode('/', $path) as $chunk) {
439
-			if ($chunk == '..') {
440
-				array_pop($output);
441
-			} else if ($chunk == '.') {
442
-			} else {
443
-				$output[] = $chunk;
444
-			}
445
-		}
446
-		return implode('/', $output);
447
-	}
448
-
449
-	/**
450
-	 * Test a storage for availability
451
-	 *
452
-	 * @return bool
453
-	 */
454
-	public function test() {
455
-		try {
456
-			if ($this->stat('')) {
457
-				return true;
458
-			}
459
-			\OC::$server->getLogger()->info("External storage not available: stat() failed");
460
-			return false;
461
-		} catch (\Exception $e) {
462
-			\OC::$server->getLogger()->info("External storage not available: " . $e->getMessage());
463
-			\OC::$server->getLogger()->logException($e, ['level' => ILogger::DEBUG]);
464
-			return false;
465
-		}
466
-	}
467
-
468
-	/**
469
-	 * get the free space in the storage
470
-	 *
471
-	 * @param string $path
472
-	 * @return int|false
473
-	 */
474
-	public function free_space($path) {
475
-		return \OCP\Files\FileInfo::SPACE_UNKNOWN;
476
-	}
477
-
478
-	/**
479
-	 * {@inheritdoc}
480
-	 */
481
-	public function isLocal() {
482
-		// the common implementation returns a temporary file by
483
-		// default, which is not local
484
-		return false;
485
-	}
486
-
487
-	/**
488
-	 * Check if the storage is an instance of $class or is a wrapper for a storage that is an instance of $class
489
-	 *
490
-	 * @param string $class
491
-	 * @return bool
492
-	 */
493
-	public function instanceOfStorage($class) {
494
-		if (ltrim($class, '\\') === 'OC\Files\Storage\Shared') {
495
-			// FIXME Temporary fix to keep existing checks working
496
-			$class = '\OCA\Files_Sharing\SharedStorage';
497
-		}
498
-		return is_a($this, $class);
499
-	}
500
-
501
-	/**
502
-	 * A custom storage implementation can return an url for direct download of a give file.
503
-	 *
504
-	 * For now the returned array can hold the parameter url - in future more attributes might follow.
505
-	 *
506
-	 * @param string $path
507
-	 * @return array|false
508
-	 */
509
-	public function getDirectDownload($path) {
510
-		return [];
511
-	}
512
-
513
-	/**
514
-	 * @inheritdoc
515
-	 * @throws InvalidPathException
516
-	 */
517
-	public function verifyPath($path, $fileName) {
518
-
519
-		// verify empty and dot files
520
-		$trimmed = trim($fileName);
521
-		if ($trimmed === '') {
522
-			throw new EmptyFileNameException();
523
-		}
524
-
525
-		if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) {
526
-			throw new InvalidDirectoryException();
527
-		}
528
-
529
-		if (!\OC::$server->getDatabaseConnection()->supports4ByteText()) {
530
-			// verify database - e.g. mysql only 3-byte chars
531
-			if (preg_match('%(?:
79
+    use LocalTempFileTrait;
80
+
81
+    protected $cache;
82
+    protected $scanner;
83
+    protected $watcher;
84
+    protected $propagator;
85
+    protected $storageCache;
86
+    protected $updater;
87
+
88
+    protected $mountOptions = [];
89
+    protected $owner = null;
90
+
91
+    private $shouldLogLocks = null;
92
+    private $logger;
93
+
94
+    public function __construct($parameters) {
95
+    }
96
+
97
+    /**
98
+     * Remove a file or folder
99
+     *
100
+     * @param string $path
101
+     * @return bool
102
+     */
103
+    protected function remove($path) {
104
+        if ($this->is_dir($path)) {
105
+            return $this->rmdir($path);
106
+        } else if ($this->is_file($path)) {
107
+            return $this->unlink($path);
108
+        } else {
109
+            return false;
110
+        }
111
+    }
112
+
113
+    public function is_dir($path) {
114
+        return $this->filetype($path) === 'dir';
115
+    }
116
+
117
+    public function is_file($path) {
118
+        return $this->filetype($path) === 'file';
119
+    }
120
+
121
+    public function filesize($path) {
122
+        if ($this->is_dir($path)) {
123
+            return 0; //by definition
124
+        } else {
125
+            $stat = $this->stat($path);
126
+            if (isset($stat['size'])) {
127
+                return $stat['size'];
128
+            } else {
129
+                return 0;
130
+            }
131
+        }
132
+    }
133
+
134
+    public function isReadable($path) {
135
+        // at least check whether it exists
136
+        // subclasses might want to implement this more thoroughly
137
+        return $this->file_exists($path);
138
+    }
139
+
140
+    public function isUpdatable($path) {
141
+        // at least check whether it exists
142
+        // subclasses might want to implement this more thoroughly
143
+        // a non-existing file/folder isn't updatable
144
+        return $this->file_exists($path);
145
+    }
146
+
147
+    public function isCreatable($path) {
148
+        if ($this->is_dir($path) && $this->isUpdatable($path)) {
149
+            return true;
150
+        }
151
+        return false;
152
+    }
153
+
154
+    public function isDeletable($path) {
155
+        if ($path === '' || $path === '/') {
156
+            return false;
157
+        }
158
+        $parent = dirname($path);
159
+        return $this->isUpdatable($parent) && $this->isUpdatable($path);
160
+    }
161
+
162
+    public function isSharable($path) {
163
+        return $this->isReadable($path);
164
+    }
165
+
166
+    public function getPermissions($path) {
167
+        $permissions = 0;
168
+        if ($this->isCreatable($path)) {
169
+            $permissions |= \OCP\Constants::PERMISSION_CREATE;
170
+        }
171
+        if ($this->isReadable($path)) {
172
+            $permissions |= \OCP\Constants::PERMISSION_READ;
173
+        }
174
+        if ($this->isUpdatable($path)) {
175
+            $permissions |= \OCP\Constants::PERMISSION_UPDATE;
176
+        }
177
+        if ($this->isDeletable($path)) {
178
+            $permissions |= \OCP\Constants::PERMISSION_DELETE;
179
+        }
180
+        if ($this->isSharable($path)) {
181
+            $permissions |= \OCP\Constants::PERMISSION_SHARE;
182
+        }
183
+        return $permissions;
184
+    }
185
+
186
+    public function filemtime($path) {
187
+        $stat = $this->stat($path);
188
+        if (isset($stat['mtime']) && $stat['mtime'] > 0) {
189
+            return $stat['mtime'];
190
+        } else {
191
+            return 0;
192
+        }
193
+    }
194
+
195
+    public function file_get_contents($path) {
196
+        $handle = $this->fopen($path, "r");
197
+        if (!$handle) {
198
+            return false;
199
+        }
200
+        $data = stream_get_contents($handle);
201
+        fclose($handle);
202
+        return $data;
203
+    }
204
+
205
+    public function file_put_contents($path, $data) {
206
+        $handle = $this->fopen($path, "w");
207
+        $this->removeCachedFile($path);
208
+        $count = fwrite($handle, $data);
209
+        fclose($handle);
210
+        return $count;
211
+    }
212
+
213
+    public function rename($path1, $path2) {
214
+        $this->remove($path2);
215
+
216
+        $this->removeCachedFile($path1);
217
+        return $this->copy($path1, $path2) and $this->remove($path1);
218
+    }
219
+
220
+    public function copy($path1, $path2) {
221
+        if ($this->is_dir($path1)) {
222
+            $this->remove($path2);
223
+            $dir = $this->opendir($path1);
224
+            $this->mkdir($path2);
225
+            while ($file = readdir($dir)) {
226
+                if (!Filesystem::isIgnoredDir($file)) {
227
+                    if (!$this->copy($path1 . '/' . $file, $path2 . '/' . $file)) {
228
+                        return false;
229
+                    }
230
+                }
231
+            }
232
+            closedir($dir);
233
+            return true;
234
+        } else {
235
+            $source = $this->fopen($path1, 'r');
236
+            $target = $this->fopen($path2, 'w');
237
+            list(, $result) = \OC_Helper::streamCopy($source, $target);
238
+            if (!$result) {
239
+                \OC::$server->getLogger()->warning("Failed to write data while copying $path1 to $path2");
240
+            }
241
+            $this->removeCachedFile($path2);
242
+            return $result;
243
+        }
244
+    }
245
+
246
+    public function getMimeType($path) {
247
+        if ($this->is_dir($path)) {
248
+            return 'httpd/unix-directory';
249
+        } elseif ($this->file_exists($path)) {
250
+            return \OC::$server->getMimeTypeDetector()->detectPath($path);
251
+        } else {
252
+            return false;
253
+        }
254
+    }
255
+
256
+    public function hash($type, $path, $raw = false) {
257
+        $fh = $this->fopen($path, 'rb');
258
+        $ctx = hash_init($type);
259
+        hash_update_stream($ctx, $fh);
260
+        fclose($fh);
261
+        return hash_final($ctx, $raw);
262
+    }
263
+
264
+    public function search($query) {
265
+        return $this->searchInDir($query);
266
+    }
267
+
268
+    public function getLocalFile($path) {
269
+        return $this->getCachedFile($path);
270
+    }
271
+
272
+    /**
273
+     * @param string $path
274
+     * @param string $target
275
+     */
276
+    private function addLocalFolder($path, $target) {
277
+        $dh = $this->opendir($path);
278
+        if (is_resource($dh)) {
279
+            while (($file = readdir($dh)) !== false) {
280
+                if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
281
+                    if ($this->is_dir($path . '/' . $file)) {
282
+                        mkdir($target . '/' . $file);
283
+                        $this->addLocalFolder($path . '/' . $file, $target . '/' . $file);
284
+                    } else {
285
+                        $tmp = $this->toTmpFile($path . '/' . $file);
286
+                        rename($tmp, $target . '/' . $file);
287
+                    }
288
+                }
289
+            }
290
+        }
291
+    }
292
+
293
+    /**
294
+     * @param string $query
295
+     * @param string $dir
296
+     * @return array
297
+     */
298
+    protected function searchInDir($query, $dir = '') {
299
+        $files = [];
300
+        $dh = $this->opendir($dir);
301
+        if (is_resource($dh)) {
302
+            while (($item = readdir($dh)) !== false) {
303
+                if (\OC\Files\Filesystem::isIgnoredDir($item)) continue;
304
+                if (strstr(strtolower($item), strtolower($query)) !== false) {
305
+                    $files[] = $dir . '/' . $item;
306
+                }
307
+                if ($this->is_dir($dir . '/' . $item)) {
308
+                    $files = array_merge($files, $this->searchInDir($query, $dir . '/' . $item));
309
+                }
310
+            }
311
+        }
312
+        closedir($dh);
313
+        return $files;
314
+    }
315
+
316
+    /**
317
+     * check if a file or folder has been updated since $time
318
+     *
319
+     * The method is only used to check if the cache needs to be updated. Storage backends that don't support checking
320
+     * the mtime should always return false here. As a result storage implementations that always return false expect
321
+     * exclusive access to the backend and will not pick up files that have been added in a way that circumvents
322
+     * ownClouds filesystem.
323
+     *
324
+     * @param string $path
325
+     * @param int $time
326
+     * @return bool
327
+     */
328
+    public function hasUpdated($path, $time) {
329
+        return $this->filemtime($path) > $time;
330
+    }
331
+
332
+    public function getCache($path = '', $storage = null) {
333
+        if (!$storage) {
334
+            $storage = $this;
335
+        }
336
+        if (!isset($storage->cache)) {
337
+            $storage->cache = new Cache($storage);
338
+        }
339
+        return $storage->cache;
340
+    }
341
+
342
+    public function getScanner($path = '', $storage = null) {
343
+        if (!$storage) {
344
+            $storage = $this;
345
+        }
346
+        if (!isset($storage->scanner)) {
347
+            $storage->scanner = new Scanner($storage);
348
+        }
349
+        return $storage->scanner;
350
+    }
351
+
352
+    public function getWatcher($path = '', $storage = null) {
353
+        if (!$storage) {
354
+            $storage = $this;
355
+        }
356
+        if (!isset($this->watcher)) {
357
+            $this->watcher = new Watcher($storage);
358
+            $globalPolicy = \OC::$server->getConfig()->getSystemValue('filesystem_check_changes', Watcher::CHECK_NEVER);
359
+            $this->watcher->setPolicy((int)$this->getMountOption('filesystem_check_changes', $globalPolicy));
360
+        }
361
+        return $this->watcher;
362
+    }
363
+
364
+    /**
365
+     * get a propagator instance for the cache
366
+     *
367
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
368
+     * @return \OC\Files\Cache\Propagator
369
+     */
370
+    public function getPropagator($storage = null) {
371
+        if (!$storage) {
372
+            $storage = $this;
373
+        }
374
+        if (!isset($storage->propagator)) {
375
+            $config = \OC::$server->getSystemConfig();
376
+            $storage->propagator = new Propagator($storage, \OC::$server->getDatabaseConnection(), ['appdata_' . $config->getValue('instanceid')]);
377
+        }
378
+        return $storage->propagator;
379
+    }
380
+
381
+    public function getUpdater($storage = null) {
382
+        if (!$storage) {
383
+            $storage = $this;
384
+        }
385
+        if (!isset($storage->updater)) {
386
+            $storage->updater = new Updater($storage);
387
+        }
388
+        return $storage->updater;
389
+    }
390
+
391
+    public function getStorageCache($storage = null) {
392
+        if (!$storage) {
393
+            $storage = $this;
394
+        }
395
+        if (!isset($this->storageCache)) {
396
+            $this->storageCache = new \OC\Files\Cache\Storage($storage);
397
+        }
398
+        return $this->storageCache;
399
+    }
400
+
401
+    /**
402
+     * get the owner of a path
403
+     *
404
+     * @param string $path The path to get the owner
405
+     * @return string|false uid or false
406
+     */
407
+    public function getOwner($path) {
408
+        if ($this->owner === null) {
409
+            $this->owner = \OC_User::getUser();
410
+        }
411
+
412
+        return $this->owner;
413
+    }
414
+
415
+    /**
416
+     * get the ETag for a file or folder
417
+     *
418
+     * @param string $path
419
+     * @return string
420
+     */
421
+    public function getETag($path) {
422
+        return uniqid();
423
+    }
424
+
425
+    /**
426
+     * clean a path, i.e. remove all redundant '.' and '..'
427
+     * making sure that it can't point to higher than '/'
428
+     *
429
+     * @param string $path The path to clean
430
+     * @return string cleaned path
431
+     */
432
+    public function cleanPath($path) {
433
+        if (strlen($path) == 0 or $path[0] != '/') {
434
+            $path = '/' . $path;
435
+        }
436
+
437
+        $output = [];
438
+        foreach (explode('/', $path) as $chunk) {
439
+            if ($chunk == '..') {
440
+                array_pop($output);
441
+            } else if ($chunk == '.') {
442
+            } else {
443
+                $output[] = $chunk;
444
+            }
445
+        }
446
+        return implode('/', $output);
447
+    }
448
+
449
+    /**
450
+     * Test a storage for availability
451
+     *
452
+     * @return bool
453
+     */
454
+    public function test() {
455
+        try {
456
+            if ($this->stat('')) {
457
+                return true;
458
+            }
459
+            \OC::$server->getLogger()->info("External storage not available: stat() failed");
460
+            return false;
461
+        } catch (\Exception $e) {
462
+            \OC::$server->getLogger()->info("External storage not available: " . $e->getMessage());
463
+            \OC::$server->getLogger()->logException($e, ['level' => ILogger::DEBUG]);
464
+            return false;
465
+        }
466
+    }
467
+
468
+    /**
469
+     * get the free space in the storage
470
+     *
471
+     * @param string $path
472
+     * @return int|false
473
+     */
474
+    public function free_space($path) {
475
+        return \OCP\Files\FileInfo::SPACE_UNKNOWN;
476
+    }
477
+
478
+    /**
479
+     * {@inheritdoc}
480
+     */
481
+    public function isLocal() {
482
+        // the common implementation returns a temporary file by
483
+        // default, which is not local
484
+        return false;
485
+    }
486
+
487
+    /**
488
+     * Check if the storage is an instance of $class or is a wrapper for a storage that is an instance of $class
489
+     *
490
+     * @param string $class
491
+     * @return bool
492
+     */
493
+    public function instanceOfStorage($class) {
494
+        if (ltrim($class, '\\') === 'OC\Files\Storage\Shared') {
495
+            // FIXME Temporary fix to keep existing checks working
496
+            $class = '\OCA\Files_Sharing\SharedStorage';
497
+        }
498
+        return is_a($this, $class);
499
+    }
500
+
501
+    /**
502
+     * A custom storage implementation can return an url for direct download of a give file.
503
+     *
504
+     * For now the returned array can hold the parameter url - in future more attributes might follow.
505
+     *
506
+     * @param string $path
507
+     * @return array|false
508
+     */
509
+    public function getDirectDownload($path) {
510
+        return [];
511
+    }
512
+
513
+    /**
514
+     * @inheritdoc
515
+     * @throws InvalidPathException
516
+     */
517
+    public function verifyPath($path, $fileName) {
518
+
519
+        // verify empty and dot files
520
+        $trimmed = trim($fileName);
521
+        if ($trimmed === '') {
522
+            throw new EmptyFileNameException();
523
+        }
524
+
525
+        if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) {
526
+            throw new InvalidDirectoryException();
527
+        }
528
+
529
+        if (!\OC::$server->getDatabaseConnection()->supports4ByteText()) {
530
+            // verify database - e.g. mysql only 3-byte chars
531
+            if (preg_match('%(?:
532 532
       \xF0[\x90-\xBF][\x80-\xBF]{2}      # planes 1-3
533 533
     | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
534 534
     | \xF4[\x80-\x8F][\x80-\xBF]{2}      # plane 16
535 535
 )%xs', $fileName)) {
536
-				throw new InvalidCharacterInPathException();
537
-			}
538
-		}
539
-
540
-		// 255 characters is the limit on common file systems (ext/xfs)
541
-		// oc_filecache has a 250 char length limit for the filename
542
-		if (isset($fileName[250])) {
543
-			throw new FileNameTooLongException();
544
-		}
545
-
546
-		// NOTE: $path will remain unverified for now
547
-		$this->verifyPosixPath($fileName);
548
-	}
549
-
550
-	/**
551
-	 * @param string $fileName
552
-	 * @throws InvalidPathException
553
-	 */
554
-	protected function verifyPosixPath($fileName) {
555
-		$fileName = trim($fileName);
556
-		$this->scanForInvalidCharacters($fileName, "\\/");
557
-		$reservedNames = ['*'];
558
-		if (in_array($fileName, $reservedNames)) {
559
-			throw new ReservedWordException();
560
-		}
561
-	}
562
-
563
-	/**
564
-	 * @param string $fileName
565
-	 * @param string $invalidChars
566
-	 * @throws InvalidPathException
567
-	 */
568
-	private function scanForInvalidCharacters($fileName, $invalidChars) {
569
-		foreach (str_split($invalidChars) as $char) {
570
-			if (strpos($fileName, $char) !== false) {
571
-				throw new InvalidCharacterInPathException();
572
-			}
573
-		}
574
-
575
-		$sanitizedFileName = filter_var($fileName, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW);
576
-		if ($sanitizedFileName !== $fileName) {
577
-			throw new InvalidCharacterInPathException();
578
-		}
579
-	}
580
-
581
-	/**
582
-	 * @param array $options
583
-	 */
584
-	public function setMountOptions(array $options) {
585
-		$this->mountOptions = $options;
586
-	}
587
-
588
-	/**
589
-	 * @param string $name
590
-	 * @param mixed $default
591
-	 * @return mixed
592
-	 */
593
-	public function getMountOption($name, $default = null) {
594
-		return isset($this->mountOptions[$name]) ? $this->mountOptions[$name] : $default;
595
-	}
596
-
597
-	/**
598
-	 * @param IStorage $sourceStorage
599
-	 * @param string $sourceInternalPath
600
-	 * @param string $targetInternalPath
601
-	 * @param bool $preserveMtime
602
-	 * @return bool
603
-	 */
604
-	public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime = false) {
605
-		if ($sourceStorage === $this) {
606
-			return $this->copy($sourceInternalPath, $targetInternalPath);
607
-		}
608
-
609
-		if ($sourceStorage->is_dir($sourceInternalPath)) {
610
-			$dh = $sourceStorage->opendir($sourceInternalPath);
611
-			$result = $this->mkdir($targetInternalPath);
612
-			if (is_resource($dh)) {
613
-				while ($result and ($file = readdir($dh)) !== false) {
614
-					if (!Filesystem::isIgnoredDir($file)) {
615
-						$result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file);
616
-					}
617
-				}
618
-			}
619
-		} else {
620
-			$source = $sourceStorage->fopen($sourceInternalPath, 'r');
621
-			// TODO: call fopen in a way that we execute again all storage wrappers
622
-			// to avoid that we bypass storage wrappers which perform important actions
623
-			// for this operation. Same is true for all other operations which
624
-			// are not the same as the original one.Once this is fixed we also
625
-			// need to adjust the encryption wrapper.
626
-			$target = $this->fopen($targetInternalPath, 'w');
627
-			list(, $result) = \OC_Helper::streamCopy($source, $target);
628
-			if ($result and $preserveMtime) {
629
-				$this->touch($targetInternalPath, $sourceStorage->filemtime($sourceInternalPath));
630
-			}
631
-			fclose($source);
632
-			fclose($target);
633
-
634
-			if (!$result) {
635
-				// delete partially written target file
636
-				$this->unlink($targetInternalPath);
637
-				// delete cache entry that was created by fopen
638
-				$this->getCache()->remove($targetInternalPath);
639
-			}
640
-		}
641
-		return (bool)$result;
642
-	}
643
-
644
-	/**
645
-	 * Check if a storage is the same as the current one, including wrapped storages
646
-	 *
647
-	 * @param IStorage $storage
648
-	 * @return bool
649
-	 */
650
-	private function isSameStorage(IStorage $storage): bool {
651
-		while ($storage->instanceOfStorage(Wrapper::class)) {
652
-			/**
653
-			 * @var Wrapper $sourceStorage
654
-			 */
655
-			$storage = $storage->getWrapperStorage();
656
-		}
657
-
658
-		return $storage === $this;
659
-	}
660
-
661
-	/**
662
-	 * @param IStorage $sourceStorage
663
-	 * @param string $sourceInternalPath
664
-	 * @param string $targetInternalPath
665
-	 * @return bool
666
-	 */
667
-	public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
668
-		if ($this->isSameStorage($sourceStorage)) {
669
-			// resolve any jailed paths
670
-			while ($sourceStorage->instanceOfStorage(Jail::class)) {
671
-				/**
672
-				 * @var Jail $sourceStorage
673
-				 */
674
-				$sourceInternalPath = $sourceStorage->getUnjailedPath($sourceInternalPath);
675
-				$sourceStorage = $sourceStorage->getUnjailedStorage();
676
-			}
677
-
678
-			return $this->rename($sourceInternalPath, $targetInternalPath);
679
-		}
680
-
681
-		if (!$sourceStorage->isDeletable($sourceInternalPath)) {
682
-			return false;
683
-		}
684
-
685
-		$result = $this->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath, true);
686
-		if ($result) {
687
-			if ($sourceStorage->is_dir($sourceInternalPath)) {
688
-				$result &= $sourceStorage->rmdir($sourceInternalPath);
689
-			} else {
690
-				$result &= $sourceStorage->unlink($sourceInternalPath);
691
-			}
692
-		}
693
-		return $result;
694
-	}
695
-
696
-	/**
697
-	 * @inheritdoc
698
-	 */
699
-	public function getMetaData($path) {
700
-		$permissions = $this->getPermissions($path);
701
-		if (!$permissions & \OCP\Constants::PERMISSION_READ) {
702
-			//can't read, nothing we can do
703
-			return null;
704
-		}
705
-
706
-		$data = [];
707
-		$data['mimetype'] = $this->getMimeType($path);
708
-		$data['mtime'] = $this->filemtime($path);
709
-		if ($data['mtime'] === false) {
710
-			$data['mtime'] = time();
711
-		}
712
-		if ($data['mimetype'] == 'httpd/unix-directory') {
713
-			$data['size'] = -1; //unknown
714
-		} else {
715
-			$data['size'] = $this->filesize($path);
716
-		}
717
-		$data['etag'] = $this->getETag($path);
718
-		$data['storage_mtime'] = $data['mtime'];
719
-		$data['permissions'] = $permissions;
720
-
721
-		return $data;
722
-	}
723
-
724
-	/**
725
-	 * @param string $path
726
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
727
-	 * @param \OCP\Lock\ILockingProvider $provider
728
-	 * @throws \OCP\Lock\LockedException
729
-	 */
730
-	public function acquireLock($path, $type, ILockingProvider $provider) {
731
-		$logger = $this->getLockLogger();
732
-		if ($logger) {
733
-			$typeString = ($type === ILockingProvider::LOCK_SHARED) ? 'shared' : 'exclusive';
734
-			$logger->info(
735
-				sprintf(
736
-					'acquire %s lock on "%s" on storage "%s"',
737
-					$typeString,
738
-					$path,
739
-					$this->getId()
740
-				),
741
-				[
742
-					'app' => 'locking',
743
-				]
744
-			);
745
-		}
746
-		try {
747
-			$provider->acquireLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
748
-		} catch (LockedException $e) {
749
-			if ($logger) {
750
-				$logger->logException($e, ['level' => ILogger::INFO]);
751
-			}
752
-			throw $e;
753
-		}
754
-	}
755
-
756
-	/**
757
-	 * @param string $path
758
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
759
-	 * @param \OCP\Lock\ILockingProvider $provider
760
-	 * @throws \OCP\Lock\LockedException
761
-	 */
762
-	public function releaseLock($path, $type, ILockingProvider $provider) {
763
-		$logger = $this->getLockLogger();
764
-		if ($logger) {
765
-			$typeString = ($type === ILockingProvider::LOCK_SHARED) ? 'shared' : 'exclusive';
766
-			$logger->info(
767
-				sprintf(
768
-					'release %s lock on "%s" on storage "%s"',
769
-					$typeString,
770
-					$path,
771
-					$this->getId()
772
-				),
773
-				[
774
-					'app' => 'locking',
775
-				]
776
-			);
777
-		}
778
-		try {
779
-			$provider->releaseLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
780
-		} catch (LockedException $e) {
781
-			if ($logger) {
782
-				$logger->logException($e, ['level' => ILogger::INFO]);
783
-			}
784
-			throw $e;
785
-		}
786
-	}
787
-
788
-	/**
789
-	 * @param string $path
790
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
791
-	 * @param \OCP\Lock\ILockingProvider $provider
792
-	 * @throws \OCP\Lock\LockedException
793
-	 */
794
-	public function changeLock($path, $type, ILockingProvider $provider) {
795
-		$logger = $this->getLockLogger();
796
-		if ($logger) {
797
-			$typeString = ($type === ILockingProvider::LOCK_SHARED) ? 'shared' : 'exclusive';
798
-			$logger->info(
799
-				sprintf(
800
-					'change lock on "%s" to %s on storage "%s"',
801
-					$path,
802
-					$typeString,
803
-					$this->getId()
804
-				),
805
-				[
806
-					'app' => 'locking',
807
-				]
808
-			);
809
-		}
810
-		try {
811
-			$provider->changeLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
812
-		} catch (LockedException $e) {
813
-			\OC::$server->getLogger()->logException($e, ['level' => ILogger::INFO]);
814
-			throw $e;
815
-		}
816
-	}
817
-
818
-	private function getLockLogger() {
819
-		if (is_null($this->shouldLogLocks)) {
820
-			$this->shouldLogLocks = \OC::$server->getConfig()->getSystemValue('filelocking.debug', false);
821
-			$this->logger = $this->shouldLogLocks ? \OC::$server->getLogger() : null;
822
-		}
823
-		return $this->logger;
824
-	}
825
-
826
-	/**
827
-	 * @return array [ available, last_checked ]
828
-	 */
829
-	public function getAvailability() {
830
-		return $this->getStorageCache()->getAvailability();
831
-	}
832
-
833
-	/**
834
-	 * @param bool $isAvailable
835
-	 */
836
-	public function setAvailability($isAvailable) {
837
-		$this->getStorageCache()->setAvailability($isAvailable);
838
-	}
839
-
840
-	/**
841
-	 * @return bool
842
-	 */
843
-	public function needsPartFile() {
844
-		return true;
845
-	}
846
-
847
-	/**
848
-	 * fallback implementation
849
-	 *
850
-	 * @param string $path
851
-	 * @param resource $stream
852
-	 * @param int $size
853
-	 * @return int
854
-	 */
855
-	public function writeStream(string $path, $stream, int $size = null): int {
856
-		$target = $this->fopen($path, 'w');
857
-		if (!$target) {
858
-			return 0;
859
-		}
860
-		list($count, $result) = \OC_Helper::streamCopy($stream, $target);
861
-		fclose($stream);
862
-		fclose($target);
863
-		return $count;
864
-	}
536
+                throw new InvalidCharacterInPathException();
537
+            }
538
+        }
539
+
540
+        // 255 characters is the limit on common file systems (ext/xfs)
541
+        // oc_filecache has a 250 char length limit for the filename
542
+        if (isset($fileName[250])) {
543
+            throw new FileNameTooLongException();
544
+        }
545
+
546
+        // NOTE: $path will remain unverified for now
547
+        $this->verifyPosixPath($fileName);
548
+    }
549
+
550
+    /**
551
+     * @param string $fileName
552
+     * @throws InvalidPathException
553
+     */
554
+    protected function verifyPosixPath($fileName) {
555
+        $fileName = trim($fileName);
556
+        $this->scanForInvalidCharacters($fileName, "\\/");
557
+        $reservedNames = ['*'];
558
+        if (in_array($fileName, $reservedNames)) {
559
+            throw new ReservedWordException();
560
+        }
561
+    }
562
+
563
+    /**
564
+     * @param string $fileName
565
+     * @param string $invalidChars
566
+     * @throws InvalidPathException
567
+     */
568
+    private function scanForInvalidCharacters($fileName, $invalidChars) {
569
+        foreach (str_split($invalidChars) as $char) {
570
+            if (strpos($fileName, $char) !== false) {
571
+                throw new InvalidCharacterInPathException();
572
+            }
573
+        }
574
+
575
+        $sanitizedFileName = filter_var($fileName, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW);
576
+        if ($sanitizedFileName !== $fileName) {
577
+            throw new InvalidCharacterInPathException();
578
+        }
579
+    }
580
+
581
+    /**
582
+     * @param array $options
583
+     */
584
+    public function setMountOptions(array $options) {
585
+        $this->mountOptions = $options;
586
+    }
587
+
588
+    /**
589
+     * @param string $name
590
+     * @param mixed $default
591
+     * @return mixed
592
+     */
593
+    public function getMountOption($name, $default = null) {
594
+        return isset($this->mountOptions[$name]) ? $this->mountOptions[$name] : $default;
595
+    }
596
+
597
+    /**
598
+     * @param IStorage $sourceStorage
599
+     * @param string $sourceInternalPath
600
+     * @param string $targetInternalPath
601
+     * @param bool $preserveMtime
602
+     * @return bool
603
+     */
604
+    public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime = false) {
605
+        if ($sourceStorage === $this) {
606
+            return $this->copy($sourceInternalPath, $targetInternalPath);
607
+        }
608
+
609
+        if ($sourceStorage->is_dir($sourceInternalPath)) {
610
+            $dh = $sourceStorage->opendir($sourceInternalPath);
611
+            $result = $this->mkdir($targetInternalPath);
612
+            if (is_resource($dh)) {
613
+                while ($result and ($file = readdir($dh)) !== false) {
614
+                    if (!Filesystem::isIgnoredDir($file)) {
615
+                        $result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file);
616
+                    }
617
+                }
618
+            }
619
+        } else {
620
+            $source = $sourceStorage->fopen($sourceInternalPath, 'r');
621
+            // TODO: call fopen in a way that we execute again all storage wrappers
622
+            // to avoid that we bypass storage wrappers which perform important actions
623
+            // for this operation. Same is true for all other operations which
624
+            // are not the same as the original one.Once this is fixed we also
625
+            // need to adjust the encryption wrapper.
626
+            $target = $this->fopen($targetInternalPath, 'w');
627
+            list(, $result) = \OC_Helper::streamCopy($source, $target);
628
+            if ($result and $preserveMtime) {
629
+                $this->touch($targetInternalPath, $sourceStorage->filemtime($sourceInternalPath));
630
+            }
631
+            fclose($source);
632
+            fclose($target);
633
+
634
+            if (!$result) {
635
+                // delete partially written target file
636
+                $this->unlink($targetInternalPath);
637
+                // delete cache entry that was created by fopen
638
+                $this->getCache()->remove($targetInternalPath);
639
+            }
640
+        }
641
+        return (bool)$result;
642
+    }
643
+
644
+    /**
645
+     * Check if a storage is the same as the current one, including wrapped storages
646
+     *
647
+     * @param IStorage $storage
648
+     * @return bool
649
+     */
650
+    private function isSameStorage(IStorage $storage): bool {
651
+        while ($storage->instanceOfStorage(Wrapper::class)) {
652
+            /**
653
+             * @var Wrapper $sourceStorage
654
+             */
655
+            $storage = $storage->getWrapperStorage();
656
+        }
657
+
658
+        return $storage === $this;
659
+    }
660
+
661
+    /**
662
+     * @param IStorage $sourceStorage
663
+     * @param string $sourceInternalPath
664
+     * @param string $targetInternalPath
665
+     * @return bool
666
+     */
667
+    public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
668
+        if ($this->isSameStorage($sourceStorage)) {
669
+            // resolve any jailed paths
670
+            while ($sourceStorage->instanceOfStorage(Jail::class)) {
671
+                /**
672
+                 * @var Jail $sourceStorage
673
+                 */
674
+                $sourceInternalPath = $sourceStorage->getUnjailedPath($sourceInternalPath);
675
+                $sourceStorage = $sourceStorage->getUnjailedStorage();
676
+            }
677
+
678
+            return $this->rename($sourceInternalPath, $targetInternalPath);
679
+        }
680
+
681
+        if (!$sourceStorage->isDeletable($sourceInternalPath)) {
682
+            return false;
683
+        }
684
+
685
+        $result = $this->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath, true);
686
+        if ($result) {
687
+            if ($sourceStorage->is_dir($sourceInternalPath)) {
688
+                $result &= $sourceStorage->rmdir($sourceInternalPath);
689
+            } else {
690
+                $result &= $sourceStorage->unlink($sourceInternalPath);
691
+            }
692
+        }
693
+        return $result;
694
+    }
695
+
696
+    /**
697
+     * @inheritdoc
698
+     */
699
+    public function getMetaData($path) {
700
+        $permissions = $this->getPermissions($path);
701
+        if (!$permissions & \OCP\Constants::PERMISSION_READ) {
702
+            //can't read, nothing we can do
703
+            return null;
704
+        }
705
+
706
+        $data = [];
707
+        $data['mimetype'] = $this->getMimeType($path);
708
+        $data['mtime'] = $this->filemtime($path);
709
+        if ($data['mtime'] === false) {
710
+            $data['mtime'] = time();
711
+        }
712
+        if ($data['mimetype'] == 'httpd/unix-directory') {
713
+            $data['size'] = -1; //unknown
714
+        } else {
715
+            $data['size'] = $this->filesize($path);
716
+        }
717
+        $data['etag'] = $this->getETag($path);
718
+        $data['storage_mtime'] = $data['mtime'];
719
+        $data['permissions'] = $permissions;
720
+
721
+        return $data;
722
+    }
723
+
724
+    /**
725
+     * @param string $path
726
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
727
+     * @param \OCP\Lock\ILockingProvider $provider
728
+     * @throws \OCP\Lock\LockedException
729
+     */
730
+    public function acquireLock($path, $type, ILockingProvider $provider) {
731
+        $logger = $this->getLockLogger();
732
+        if ($logger) {
733
+            $typeString = ($type === ILockingProvider::LOCK_SHARED) ? 'shared' : 'exclusive';
734
+            $logger->info(
735
+                sprintf(
736
+                    'acquire %s lock on "%s" on storage "%s"',
737
+                    $typeString,
738
+                    $path,
739
+                    $this->getId()
740
+                ),
741
+                [
742
+                    'app' => 'locking',
743
+                ]
744
+            );
745
+        }
746
+        try {
747
+            $provider->acquireLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
748
+        } catch (LockedException $e) {
749
+            if ($logger) {
750
+                $logger->logException($e, ['level' => ILogger::INFO]);
751
+            }
752
+            throw $e;
753
+        }
754
+    }
755
+
756
+    /**
757
+     * @param string $path
758
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
759
+     * @param \OCP\Lock\ILockingProvider $provider
760
+     * @throws \OCP\Lock\LockedException
761
+     */
762
+    public function releaseLock($path, $type, ILockingProvider $provider) {
763
+        $logger = $this->getLockLogger();
764
+        if ($logger) {
765
+            $typeString = ($type === ILockingProvider::LOCK_SHARED) ? 'shared' : 'exclusive';
766
+            $logger->info(
767
+                sprintf(
768
+                    'release %s lock on "%s" on storage "%s"',
769
+                    $typeString,
770
+                    $path,
771
+                    $this->getId()
772
+                ),
773
+                [
774
+                    'app' => 'locking',
775
+                ]
776
+            );
777
+        }
778
+        try {
779
+            $provider->releaseLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
780
+        } catch (LockedException $e) {
781
+            if ($logger) {
782
+                $logger->logException($e, ['level' => ILogger::INFO]);
783
+            }
784
+            throw $e;
785
+        }
786
+    }
787
+
788
+    /**
789
+     * @param string $path
790
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
791
+     * @param \OCP\Lock\ILockingProvider $provider
792
+     * @throws \OCP\Lock\LockedException
793
+     */
794
+    public function changeLock($path, $type, ILockingProvider $provider) {
795
+        $logger = $this->getLockLogger();
796
+        if ($logger) {
797
+            $typeString = ($type === ILockingProvider::LOCK_SHARED) ? 'shared' : 'exclusive';
798
+            $logger->info(
799
+                sprintf(
800
+                    'change lock on "%s" to %s on storage "%s"',
801
+                    $path,
802
+                    $typeString,
803
+                    $this->getId()
804
+                ),
805
+                [
806
+                    'app' => 'locking',
807
+                ]
808
+            );
809
+        }
810
+        try {
811
+            $provider->changeLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
812
+        } catch (LockedException $e) {
813
+            \OC::$server->getLogger()->logException($e, ['level' => ILogger::INFO]);
814
+            throw $e;
815
+        }
816
+    }
817
+
818
+    private function getLockLogger() {
819
+        if (is_null($this->shouldLogLocks)) {
820
+            $this->shouldLogLocks = \OC::$server->getConfig()->getSystemValue('filelocking.debug', false);
821
+            $this->logger = $this->shouldLogLocks ? \OC::$server->getLogger() : null;
822
+        }
823
+        return $this->logger;
824
+    }
825
+
826
+    /**
827
+     * @return array [ available, last_checked ]
828
+     */
829
+    public function getAvailability() {
830
+        return $this->getStorageCache()->getAvailability();
831
+    }
832
+
833
+    /**
834
+     * @param bool $isAvailable
835
+     */
836
+    public function setAvailability($isAvailable) {
837
+        $this->getStorageCache()->setAvailability($isAvailable);
838
+    }
839
+
840
+    /**
841
+     * @return bool
842
+     */
843
+    public function needsPartFile() {
844
+        return true;
845
+    }
846
+
847
+    /**
848
+     * fallback implementation
849
+     *
850
+     * @param string $path
851
+     * @param resource $stream
852
+     * @param int $size
853
+     * @return int
854
+     */
855
+    public function writeStream(string $path, $stream, int $size = null): int {
856
+        $target = $this->fopen($path, 'w');
857
+        if (!$target) {
858
+            return 0;
859
+        }
860
+        list($count, $result) = \OC_Helper::streamCopy($stream, $target);
861
+        fclose($stream);
862
+        fclose($target);
863
+        return $count;
864
+    }
865 865
 }
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
 			$this->mkdir($path2);
225 225
 			while ($file = readdir($dir)) {
226 226
 				if (!Filesystem::isIgnoredDir($file)) {
227
-					if (!$this->copy($path1 . '/' . $file, $path2 . '/' . $file)) {
227
+					if (!$this->copy($path1.'/'.$file, $path2.'/'.$file)) {
228 228
 						return false;
229 229
 					}
230 230
 				}
@@ -278,12 +278,12 @@  discard block
 block discarded – undo
278 278
 		if (is_resource($dh)) {
279 279
 			while (($file = readdir($dh)) !== false) {
280 280
 				if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
281
-					if ($this->is_dir($path . '/' . $file)) {
282
-						mkdir($target . '/' . $file);
283
-						$this->addLocalFolder($path . '/' . $file, $target . '/' . $file);
281
+					if ($this->is_dir($path.'/'.$file)) {
282
+						mkdir($target.'/'.$file);
283
+						$this->addLocalFolder($path.'/'.$file, $target.'/'.$file);
284 284
 					} else {
285
-						$tmp = $this->toTmpFile($path . '/' . $file);
286
-						rename($tmp, $target . '/' . $file);
285
+						$tmp = $this->toTmpFile($path.'/'.$file);
286
+						rename($tmp, $target.'/'.$file);
287 287
 					}
288 288
 				}
289 289
 			}
@@ -302,10 +302,10 @@  discard block
 block discarded – undo
302 302
 			while (($item = readdir($dh)) !== false) {
303 303
 				if (\OC\Files\Filesystem::isIgnoredDir($item)) continue;
304 304
 				if (strstr(strtolower($item), strtolower($query)) !== false) {
305
-					$files[] = $dir . '/' . $item;
305
+					$files[] = $dir.'/'.$item;
306 306
 				}
307
-				if ($this->is_dir($dir . '/' . $item)) {
308
-					$files = array_merge($files, $this->searchInDir($query, $dir . '/' . $item));
307
+				if ($this->is_dir($dir.'/'.$item)) {
308
+					$files = array_merge($files, $this->searchInDir($query, $dir.'/'.$item));
309 309
 				}
310 310
 			}
311 311
 		}
@@ -356,7 +356,7 @@  discard block
 block discarded – undo
356 356
 		if (!isset($this->watcher)) {
357 357
 			$this->watcher = new Watcher($storage);
358 358
 			$globalPolicy = \OC::$server->getConfig()->getSystemValue('filesystem_check_changes', Watcher::CHECK_NEVER);
359
-			$this->watcher->setPolicy((int)$this->getMountOption('filesystem_check_changes', $globalPolicy));
359
+			$this->watcher->setPolicy((int) $this->getMountOption('filesystem_check_changes', $globalPolicy));
360 360
 		}
361 361
 		return $this->watcher;
362 362
 	}
@@ -373,7 +373,7 @@  discard block
 block discarded – undo
373 373
 		}
374 374
 		if (!isset($storage->propagator)) {
375 375
 			$config = \OC::$server->getSystemConfig();
376
-			$storage->propagator = new Propagator($storage, \OC::$server->getDatabaseConnection(), ['appdata_' . $config->getValue('instanceid')]);
376
+			$storage->propagator = new Propagator($storage, \OC::$server->getDatabaseConnection(), ['appdata_'.$config->getValue('instanceid')]);
377 377
 		}
378 378
 		return $storage->propagator;
379 379
 	}
@@ -431,7 +431,7 @@  discard block
 block discarded – undo
431 431
 	 */
432 432
 	public function cleanPath($path) {
433 433
 		if (strlen($path) == 0 or $path[0] != '/') {
434
-			$path = '/' . $path;
434
+			$path = '/'.$path;
435 435
 		}
436 436
 
437 437
 		$output = [];
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
 			\OC::$server->getLogger()->info("External storage not available: stat() failed");
460 460
 			return false;
461 461
 		} catch (\Exception $e) {
462
-			\OC::$server->getLogger()->info("External storage not available: " . $e->getMessage());
462
+			\OC::$server->getLogger()->info("External storage not available: ".$e->getMessage());
463 463
 			\OC::$server->getLogger()->logException($e, ['level' => ILogger::DEBUG]);
464 464
 			return false;
465 465
 		}
@@ -612,7 +612,7 @@  discard block
 block discarded – undo
612 612
 			if (is_resource($dh)) {
613 613
 				while ($result and ($file = readdir($dh)) !== false) {
614 614
 					if (!Filesystem::isIgnoredDir($file)) {
615
-						$result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file);
615
+						$result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath.'/'.$file, $targetInternalPath.'/'.$file);
616 616
 					}
617 617
 				}
618 618
 			}
@@ -638,7 +638,7 @@  discard block
 block discarded – undo
638 638
 				$this->getCache()->remove($targetInternalPath);
639 639
 			}
640 640
 		}
641
-		return (bool)$result;
641
+		return (bool) $result;
642 642
 	}
643 643
 
644 644
 	/**
@@ -744,7 +744,7 @@  discard block
 block discarded – undo
744 744
 			);
745 745
 		}
746 746
 		try {
747
-			$provider->acquireLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
747
+			$provider->acquireLock('files/'.md5($this->getId().'::'.trim($path, '/')), $type);
748 748
 		} catch (LockedException $e) {
749 749
 			if ($logger) {
750 750
 				$logger->logException($e, ['level' => ILogger::INFO]);
@@ -776,7 +776,7 @@  discard block
 block discarded – undo
776 776
 			);
777 777
 		}
778 778
 		try {
779
-			$provider->releaseLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
779
+			$provider->releaseLock('files/'.md5($this->getId().'::'.trim($path, '/')), $type);
780 780
 		} catch (LockedException $e) {
781 781
 			if ($logger) {
782 782
 				$logger->logException($e, ['level' => ILogger::INFO]);
@@ -808,7 +808,7 @@  discard block
 block discarded – undo
808 808
 			);
809 809
 		}
810 810
 		try {
811
-			$provider->changeLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
811
+			$provider->changeLock('files/'.md5($this->getId().'::'.trim($path, '/')), $type);
812 812
 		} catch (LockedException $e) {
813 813
 			\OC::$server->getLogger()->logException($e, ['level' => ILogger::INFO]);
814 814
 			throw $e;
Please login to merge, or discard this patch.
lib/private/Files/Storage/StorageFactory.php 2 patches
Indentation   +70 added lines, -70 removed lines patch added patch discarded remove patch
@@ -29,80 +29,80 @@
 block discarded – undo
29 29
 use OCP\Files\Storage\IStorageFactory;
30 30
 
31 31
 class StorageFactory implements IStorageFactory {
32
-	/**
33
-	 * @var array[] [$name=>['priority'=>$priority, 'wrapper'=>$callable] $storageWrappers
34
-	 */
35
-	private $storageWrappers = [];
32
+    /**
33
+     * @var array[] [$name=>['priority'=>$priority, 'wrapper'=>$callable] $storageWrappers
34
+     */
35
+    private $storageWrappers = [];
36 36
 
37
-	/**
38
-	 * allow modifier storage behaviour by adding wrappers around storages
39
-	 *
40
-	 * $callback should be a function of type (string $mountPoint, Storage $storage) => Storage
41
-	 *
42
-	 * @param string $wrapperName name of the wrapper
43
-	 * @param callable $callback callback
44
-	 * @param int $priority wrappers with the lower priority are applied last (meaning they get called first)
45
-	 * @param \OCP\Files\Mount\IMountPoint[] $existingMounts existing mount points to apply the wrapper to
46
-	 * @return bool true if the wrapper was added, false if there was already a wrapper with this
47
-	 * name registered
48
-	 */
49
-	public function addStorageWrapper($wrapperName, $callback, $priority = 50, $existingMounts = []) {
50
-		if (isset($this->storageWrappers[$wrapperName])) {
51
-			return false;
52
-		}
37
+    /**
38
+     * allow modifier storage behaviour by adding wrappers around storages
39
+     *
40
+     * $callback should be a function of type (string $mountPoint, Storage $storage) => Storage
41
+     *
42
+     * @param string $wrapperName name of the wrapper
43
+     * @param callable $callback callback
44
+     * @param int $priority wrappers with the lower priority are applied last (meaning they get called first)
45
+     * @param \OCP\Files\Mount\IMountPoint[] $existingMounts existing mount points to apply the wrapper to
46
+     * @return bool true if the wrapper was added, false if there was already a wrapper with this
47
+     * name registered
48
+     */
49
+    public function addStorageWrapper($wrapperName, $callback, $priority = 50, $existingMounts = []) {
50
+        if (isset($this->storageWrappers[$wrapperName])) {
51
+            return false;
52
+        }
53 53
 
54
-		// apply to existing mounts before registering it to prevent applying it double in MountPoint::createStorage
55
-		foreach ($existingMounts as $mount) {
56
-			$mount->wrapStorage($callback);
57
-		}
54
+        // apply to existing mounts before registering it to prevent applying it double in MountPoint::createStorage
55
+        foreach ($existingMounts as $mount) {
56
+            $mount->wrapStorage($callback);
57
+        }
58 58
 
59
-		$this->storageWrappers[$wrapperName] = ['wrapper' => $callback, 'priority' => $priority];
60
-		return true;
61
-	}
59
+        $this->storageWrappers[$wrapperName] = ['wrapper' => $callback, 'priority' => $priority];
60
+        return true;
61
+    }
62 62
 
63
-	/**
64
-	 * Remove a storage wrapper by name.
65
-	 * Note: internal method only to be used for cleanup
66
-	 *
67
-	 * @param string $wrapperName name of the wrapper
68
-	 * @internal
69
-	 */
70
-	public function removeStorageWrapper($wrapperName) {
71
-		unset($this->storageWrappers[$wrapperName]);
72
-	}
63
+    /**
64
+     * Remove a storage wrapper by name.
65
+     * Note: internal method only to be used for cleanup
66
+     *
67
+     * @param string $wrapperName name of the wrapper
68
+     * @internal
69
+     */
70
+    public function removeStorageWrapper($wrapperName) {
71
+        unset($this->storageWrappers[$wrapperName]);
72
+    }
73 73
 
74
-	/**
75
-	 * Create an instance of a storage and apply the registered storage wrappers
76
-	 *
77
-	 * @param \OCP\Files\Mount\IMountPoint $mountPoint
78
-	 * @param string $class
79
-	 * @param array $arguments
80
-	 * @return \OCP\Files\Storage
81
-	 */
82
-	public function getInstance(IMountPoint $mountPoint, $class, $arguments) {
83
-		return $this->wrap($mountPoint, new $class($arguments));
84
-	}
74
+    /**
75
+     * Create an instance of a storage and apply the registered storage wrappers
76
+     *
77
+     * @param \OCP\Files\Mount\IMountPoint $mountPoint
78
+     * @param string $class
79
+     * @param array $arguments
80
+     * @return \OCP\Files\Storage
81
+     */
82
+    public function getInstance(IMountPoint $mountPoint, $class, $arguments) {
83
+        return $this->wrap($mountPoint, new $class($arguments));
84
+    }
85 85
 
86
-	/**
87
-	 * @param \OCP\Files\Mount\IMountPoint $mountPoint
88
-	 * @param \OCP\Files\Storage $storage
89
-	 * @return \OCP\Files\Storage
90
-	 */
91
-	public function wrap(IMountPoint $mountPoint, $storage) {
92
-		$wrappers = array_values($this->storageWrappers);
93
-		usort($wrappers, function ($a, $b) {
94
-			return $b['priority'] - $a['priority'];
95
-		});
96
-		/** @var callable[] $wrappers */
97
-		$wrappers = array_map(function ($wrapper) {
98
-			return $wrapper['wrapper'];
99
-		}, $wrappers);
100
-		foreach ($wrappers as $wrapper) {
101
-			$storage = $wrapper($mountPoint->getMountPoint(), $storage, $mountPoint);
102
-			if (!($storage instanceof \OCP\Files\Storage)) {
103
-				throw new \Exception('Invalid result from storage wrapper');
104
-			}
105
-		}
106
-		return $storage;
107
-	}
86
+    /**
87
+     * @param \OCP\Files\Mount\IMountPoint $mountPoint
88
+     * @param \OCP\Files\Storage $storage
89
+     * @return \OCP\Files\Storage
90
+     */
91
+    public function wrap(IMountPoint $mountPoint, $storage) {
92
+        $wrappers = array_values($this->storageWrappers);
93
+        usort($wrappers, function ($a, $b) {
94
+            return $b['priority'] - $a['priority'];
95
+        });
96
+        /** @var callable[] $wrappers */
97
+        $wrappers = array_map(function ($wrapper) {
98
+            return $wrapper['wrapper'];
99
+        }, $wrappers);
100
+        foreach ($wrappers as $wrapper) {
101
+            $storage = $wrapper($mountPoint->getMountPoint(), $storage, $mountPoint);
102
+            if (!($storage instanceof \OCP\Files\Storage)) {
103
+                throw new \Exception('Invalid result from storage wrapper');
104
+            }
105
+        }
106
+        return $storage;
107
+    }
108 108
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -90,11 +90,11 @@
 block discarded – undo
90 90
 	 */
91 91
 	public function wrap(IMountPoint $mountPoint, $storage) {
92 92
 		$wrappers = array_values($this->storageWrappers);
93
-		usort($wrappers, function ($a, $b) {
93
+		usort($wrappers, function($a, $b) {
94 94
 			return $b['priority'] - $a['priority'];
95 95
 		});
96 96
 		/** @var callable[] $wrappers */
97
-		$wrappers = array_map(function ($wrapper) {
97
+		$wrappers = array_map(function($wrapper) {
98 98
 			return $wrapper['wrapper'];
99 99
 		}, $wrappers);
100 100
 		foreach ($wrappers as $wrapper) {
Please login to merge, or discard this patch.
lib/private/Files/Storage/PolyFill/CopyDirectory.php 2 patches
Indentation   +71 added lines, -71 removed lines patch added patch discarded remove patch
@@ -25,81 +25,81 @@
 block discarded – undo
25 25
 namespace OC\Files\Storage\PolyFill;
26 26
 
27 27
 trait CopyDirectory {
28
-	/**
29
-	 * Check if a path is a directory
30
-	 *
31
-	 * @param string $path
32
-	 * @return bool
33
-	 */
34
-	abstract public function is_dir($path);
28
+    /**
29
+     * Check if a path is a directory
30
+     *
31
+     * @param string $path
32
+     * @return bool
33
+     */
34
+    abstract public function is_dir($path);
35 35
 
36
-	/**
37
-	 * Check if a file or folder exists
38
-	 *
39
-	 * @param string $path
40
-	 * @return bool
41
-	 */
42
-	abstract public function file_exists($path);
36
+    /**
37
+     * Check if a file or folder exists
38
+     *
39
+     * @param string $path
40
+     * @return bool
41
+     */
42
+    abstract public function file_exists($path);
43 43
 
44
-	/**
45
-	 * Delete a file or folder
46
-	 *
47
-	 * @param string $path
48
-	 * @return bool
49
-	 */
50
-	abstract public function unlink($path);
44
+    /**
45
+     * Delete a file or folder
46
+     *
47
+     * @param string $path
48
+     * @return bool
49
+     */
50
+    abstract public function unlink($path);
51 51
 
52
-	/**
53
-	 * Open a directory handle for a folder
54
-	 *
55
-	 * @param string $path
56
-	 * @return resource | bool
57
-	 */
58
-	abstract public function opendir($path);
52
+    /**
53
+     * Open a directory handle for a folder
54
+     *
55
+     * @param string $path
56
+     * @return resource | bool
57
+     */
58
+    abstract public function opendir($path);
59 59
 
60
-	/**
61
-	 * Create a new folder
62
-	 *
63
-	 * @param string $path
64
-	 * @return bool
65
-	 */
66
-	abstract public function mkdir($path);
60
+    /**
61
+     * Create a new folder
62
+     *
63
+     * @param string $path
64
+     * @return bool
65
+     */
66
+    abstract public function mkdir($path);
67 67
 
68
-	public function copy($source, $target) {
69
-		if ($this->is_dir($source)) {
70
-			if ($this->file_exists($target)) {
71
-				$this->unlink($target);
72
-			}
73
-			$this->mkdir($target);
74
-			return $this->copyRecursive($source, $target);
75
-		} else {
76
-			return parent::copy($source, $target);
77
-		}
78
-	}
68
+    public function copy($source, $target) {
69
+        if ($this->is_dir($source)) {
70
+            if ($this->file_exists($target)) {
71
+                $this->unlink($target);
72
+            }
73
+            $this->mkdir($target);
74
+            return $this->copyRecursive($source, $target);
75
+        } else {
76
+            return parent::copy($source, $target);
77
+        }
78
+    }
79 79
 
80
-	/**
81
-	 * For adapters that don't support copying folders natively
82
-	 *
83
-	 * @param $source
84
-	 * @param $target
85
-	 * @return bool
86
-	 */
87
-	protected function copyRecursive($source, $target) {
88
-		$dh = $this->opendir($source);
89
-		$result = true;
90
-		while ($file = readdir($dh)) {
91
-			if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
92
-				if ($this->is_dir($source . '/' . $file)) {
93
-					$this->mkdir($target . '/' . $file);
94
-					$result = $this->copyRecursive($source . '/' . $file, $target . '/' . $file);
95
-				} else {
96
-					$result = parent::copy($source . '/' . $file, $target . '/' . $file);
97
-				}
98
-				if (!$result) {
99
-					break;
100
-				}
101
-			}
102
-		}
103
-		return $result;
104
-	}
80
+    /**
81
+     * For adapters that don't support copying folders natively
82
+     *
83
+     * @param $source
84
+     * @param $target
85
+     * @return bool
86
+     */
87
+    protected function copyRecursive($source, $target) {
88
+        $dh = $this->opendir($source);
89
+        $result = true;
90
+        while ($file = readdir($dh)) {
91
+            if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
92
+                if ($this->is_dir($source . '/' . $file)) {
93
+                    $this->mkdir($target . '/' . $file);
94
+                    $result = $this->copyRecursive($source . '/' . $file, $target . '/' . $file);
95
+                } else {
96
+                    $result = parent::copy($source . '/' . $file, $target . '/' . $file);
97
+                }
98
+                if (!$result) {
99
+                    break;
100
+                }
101
+            }
102
+        }
103
+        return $result;
104
+    }
105 105
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -89,11 +89,11 @@
 block discarded – undo
89 89
 		$result = true;
90 90
 		while ($file = readdir($dh)) {
91 91
 			if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
92
-				if ($this->is_dir($source . '/' . $file)) {
93
-					$this->mkdir($target . '/' . $file);
94
-					$result = $this->copyRecursive($source . '/' . $file, $target . '/' . $file);
92
+				if ($this->is_dir($source.'/'.$file)) {
93
+					$this->mkdir($target.'/'.$file);
94
+					$result = $this->copyRecursive($source.'/'.$file, $target.'/'.$file);
95 95
 				} else {
96
-					$result = parent::copy($source . '/' . $file, $target . '/' . $file);
96
+					$result = parent::copy($source.'/'.$file, $target.'/'.$file);
97 97
 				}
98 98
 				if (!$result) {
99 99
 					break;
Please login to merge, or discard this patch.
lib/private/Files/Storage/CommonTest.php 2 patches
Indentation   +47 added lines, -47 removed lines patch added patch discarded remove patch
@@ -33,53 +33,53 @@
 block discarded – undo
33 33
 namespace OC\Files\Storage;
34 34
 
35 35
 class CommonTest extends \OC\Files\Storage\Common{
36
-	/**
37
-	 * underlying local storage used for missing functions
38
-	 * @var \OC\Files\Storage\Local
39
-	 */
40
-	private $storage;
36
+    /**
37
+     * underlying local storage used for missing functions
38
+     * @var \OC\Files\Storage\Local
39
+     */
40
+    private $storage;
41 41
 
42
-	public function __construct($params) {
43
-		$this->storage=new \OC\Files\Storage\Local($params);
44
-	}
42
+    public function __construct($params) {
43
+        $this->storage=new \OC\Files\Storage\Local($params);
44
+    }
45 45
 
46
-	public function getId(){
47
-		return 'test::'.$this->storage->getId();
48
-	}
49
-	public function mkdir($path) {
50
-		return $this->storage->mkdir($path);
51
-	}
52
-	public function rmdir($path) {
53
-		return $this->storage->rmdir($path);
54
-	}
55
-	public function opendir($path) {
56
-		return $this->storage->opendir($path);
57
-	}
58
-	public function stat($path) {
59
-		return $this->storage->stat($path);
60
-	}
61
-	public function filetype($path) {
62
-		return @$this->storage->filetype($path);
63
-	}
64
-	public function isReadable($path) {
65
-		return $this->storage->isReadable($path);
66
-	}
67
-	public function isUpdatable($path) {
68
-		return $this->storage->isUpdatable($path);
69
-	}
70
-	public function file_exists($path) {
71
-		return $this->storage->file_exists($path);
72
-	}
73
-	public function unlink($path) {
74
-		return $this->storage->unlink($path);
75
-	}
76
-	public function fopen($path, $mode) {
77
-		return $this->storage->fopen($path, $mode);
78
-	}
79
-	public function free_space($path) {
80
-		return $this->storage->free_space($path);
81
-	}
82
-	public function touch($path, $mtime=null) {
83
-		return $this->storage->touch($path, $mtime);
84
-	}
46
+    public function getId(){
47
+        return 'test::'.$this->storage->getId();
48
+    }
49
+    public function mkdir($path) {
50
+        return $this->storage->mkdir($path);
51
+    }
52
+    public function rmdir($path) {
53
+        return $this->storage->rmdir($path);
54
+    }
55
+    public function opendir($path) {
56
+        return $this->storage->opendir($path);
57
+    }
58
+    public function stat($path) {
59
+        return $this->storage->stat($path);
60
+    }
61
+    public function filetype($path) {
62
+        return @$this->storage->filetype($path);
63
+    }
64
+    public function isReadable($path) {
65
+        return $this->storage->isReadable($path);
66
+    }
67
+    public function isUpdatable($path) {
68
+        return $this->storage->isUpdatable($path);
69
+    }
70
+    public function file_exists($path) {
71
+        return $this->storage->file_exists($path);
72
+    }
73
+    public function unlink($path) {
74
+        return $this->storage->unlink($path);
75
+    }
76
+    public function fopen($path, $mode) {
77
+        return $this->storage->fopen($path, $mode);
78
+    }
79
+    public function free_space($path) {
80
+        return $this->storage->free_space($path);
81
+    }
82
+    public function touch($path, $mtime=null) {
83
+        return $this->storage->touch($path, $mtime);
84
+    }
85 85
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -32,7 +32,7 @@  discard block
 block discarded – undo
32 32
 
33 33
 namespace OC\Files\Storage;
34 34
 
35
-class CommonTest extends \OC\Files\Storage\Common{
35
+class CommonTest extends \OC\Files\Storage\Common {
36 36
 	/**
37 37
 	 * underlying local storage used for missing functions
38 38
 	 * @var \OC\Files\Storage\Local
@@ -40,10 +40,10 @@  discard block
 block discarded – undo
40 40
 	private $storage;
41 41
 
42 42
 	public function __construct($params) {
43
-		$this->storage=new \OC\Files\Storage\Local($params);
43
+		$this->storage = new \OC\Files\Storage\Local($params);
44 44
 	}
45 45
 
46
-	public function getId(){
46
+	public function getId() {
47 47
 		return 'test::'.$this->storage->getId();
48 48
 	}
49 49
 	public function mkdir($path) {
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
 	public function free_space($path) {
80 80
 		return $this->storage->free_space($path);
81 81
 	}
82
-	public function touch($path, $mtime=null) {
82
+	public function touch($path, $mtime = null) {
83 83
 		return $this->storage->touch($path, $mtime);
84 84
 	}
85 85
 }
Please login to merge, or discard this patch.
lib/private/Files/Notify/RenameChange.php 1 patch
Indentation   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -26,27 +26,27 @@
 block discarded – undo
26 26
 use OCP\Files\Notify\IRenameChange;
27 27
 
28 28
 class RenameChange extends Change implements IRenameChange {
29
-	/** @var string */
30
-	private $targetPath;
29
+    /** @var string */
30
+    private $targetPath;
31 31
 
32
-	/**
33
-	 * Change constructor.
34
-	 *
35
-	 * @param int $type
36
-	 * @param string $path
37
-	 * @param string $targetPath
38
-	 */
39
-	public function __construct($type, $path, $targetPath) {
40
-		parent::__construct($type, $path);
41
-		$this->targetPath = $targetPath;
42
-	}
32
+    /**
33
+     * Change constructor.
34
+     *
35
+     * @param int $type
36
+     * @param string $path
37
+     * @param string $targetPath
38
+     */
39
+    public function __construct($type, $path, $targetPath) {
40
+        parent::__construct($type, $path);
41
+        $this->targetPath = $targetPath;
42
+    }
43 43
 
44
-	/**
45
-	 * Get the new path of the renamed file relative to the storage root
46
-	 *
47
-	 * @return string
48
-	 */
49
-	public function getTargetPath() {
50
-		return $this->targetPath;
51
-	}
44
+    /**
45
+     * Get the new path of the renamed file relative to the storage root
46
+     *
47
+     * @return string
48
+     */
49
+    public function getTargetPath() {
50
+        return $this->targetPath;
51
+    }
52 52
 }
Please login to merge, or discard this patch.