Completed
Push — master ( 07630e...c158d3 )
by Julius
27s queued 11s
created

StorageWrapper   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 631
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 52.17%

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 2
dl 0
loc 631
ccs 48
cts 92
cp 0.5217
rs 9.969
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A checkFileAccess() 0 3 1
A mkdir() 0 4 1
A rmdir() 0 4 1
A isCreatable() 0 8 2
A isReadable() 0 8 2
A isUpdatable() 0 8 2
A isDeletable() 0 8 2
A getPermissions() 0 8 2
A file_get_contents() 0 4 1
A file_put_contents() 0 4 1
A unlink() 0 4 1
A rename() 0 5 1
A copy() 0 5 1
A fopen() 0 4 1
A touch() 0 4 1
A getCache() 0 7 2
A getDirectDownload() 0 4 1
A copyFromStorage() 0 8 2
A moveFromStorage() 0 8 2
A writeStream() 0 13 2
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Morris Jobke <[email protected]>
4
 *
5
 * @license GNU AGPL version 3 or any later version
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Affero General Public License as
9
 * published by the Free Software Foundation, either version 3 of the
10
 * License, or (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 */
21
22
namespace OCA\FilesAccessControl;
23
24
use OC\Files\Storage\Wrapper\Wrapper;
25
use OCP\Constants;
26
use OCP\Files\ForbiddenException;
27
use OCP\Files\Storage\IStorage;
28
use OCP\Files\Storage\IWriteStreamStorage;
29
30
class StorageWrapper extends Wrapper implements IWriteStreamStorage {
31
32
	/** @var Operation */
33
	protected $operation;
34
35
	/** @var string */
36
	public $mountPoint;
37
	/** @var int */
38
	protected $mask;
39
40
	/**
41
	 * @param array $parameters
42
	 */
43 38
	public function __construct($parameters) {
44 38
		parent::__construct($parameters);
45 38
		$this->operation = $parameters['operation'];
46 38
		$this->mountPoint = $parameters['mountPoint'];
47
48 38
		$this->mask = Constants::PERMISSION_ALL;
49 38
		$this->mask &= ~Constants::PERMISSION_READ;
50 38
		$this->mask &= ~Constants::PERMISSION_CREATE;
51 38
		$this->mask &= ~Constants::PERMISSION_UPDATE;
52 38
		$this->mask &= ~Constants::PERMISSION_DELETE;
53 38
	}
54
55
	/**
56
	 * @param string $path
57
	 * @param bool $isDir
58
	 */
59 2
	protected function checkFileAccess(string $path, bool $isDir = false): void {
60 2
		$this->operation->checkFileAccess($this, $path, $isDir);
61 2
	}
62
63
	/*
64
	 * Storage wrapper methods
65
	 */
66
67
	/**
68
	 * see http://php.net/manual/en/function.mkdir.php
69
	 *
70
	 * @param string $path
71
	 * @return bool
72
	 */
73 4
	public function mkdir($path) {
74 4
		$this->checkFileAccess($path, true);
75 2
		return $this->storage->mkdir($path);
76
	}
77
78
	/**
79
	 * see http://php.net/manual/en/function.rmdir.php
80
	 *
81
	 * @param string $path
82
	 * @return bool
83
	 */
84 4
	public function rmdir($path) {
85 4
		$this->checkFileAccess($path, true);
86 2
		return $this->storage->rmdir($path);
87
	}
88
89
//	/**
90
//	 * see http://php.net/manual/en/function.opendir.php
91
//	 *
92
//	 * @param string $path
93
//	 * @return resource
94
//	 */
95
//	public function opendir($path) {
96
//		return $this->storage->opendir($path);
97
//	}
98
//
99
//	/**
100
//	 * see http://php.net/manual/en/function.is_dir.php
101
//	 *
102
//	 * @param string $path
103
//	 * @return bool
104
//	 */
105
//	public function is_dir($path) {
106
//		return $this->storage->is_dir($path);
107
//	}
108
//
109
//	/**
110
//	 * see http://php.net/manual/en/function.is_file.php
111
//	 *
112
//	 * @param string $path
113
//	 * @return bool
114
//	 */
115
//	public function is_file($path) {
116
//		return $this->storage->is_file($path);
117
//	}
118
//
119
//	/**
120
//	 * see http://php.net/manual/en/function.stat.php
121
//	 * only the following keys are required in the result: size and mtime
122
//	 *
123
//	 * @param string $path
124
//	 * @return array
125
//	 */
126
//	public function stat($path) {
127
//		return $this->storage->stat($path);
128
//	}
129
//
130
//	/**
131
//	 * see http://php.net/manual/en/function.filetype.php
132
//	 *
133
//	 * @param string $path
134
//	 * @return bool
135
//	 */
136
//	public function filetype($path) {
137
//		return $this->storage->filetype($path);
138
//	}
139
//
140
//	/**
141
//	 * see http://php.net/manual/en/function.filesize.php
142
//	 * The result for filesize when called on a folder is required to be 0
143
//	 *
144
//	 * @param string $path
145
//	 * @return int
146
//	 */
147
//	public function filesize($path) {
148
//		return $this->storage->filesize($path);
149
//	}
150
151
	/**
152
	 * check if a file can be created in $path
153
	 *
154
	 * @param string $path
155
	 * @return bool
156
	 */
157 4
	public function isCreatable($path) {
158
		try {
159 4
			$this->checkFileAccess($path);
160 2
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
161 2
			return false;
162
		}
163 2
		return $this->storage->isCreatable($path);
164
	}
165
166
	/**
167
	 * check if a file can be read
168
	 *
169
	 * @param string $path
170
	 * @return bool
171
	 */
172 4
	public function isReadable($path) {
173
		try {
174 4
			$this->checkFileAccess($path);
175 2
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
176 2
			return false;
177
		}
178 2
		return $this->storage->isReadable($path);
179
	}
180
181
	/**
182
	 * check if a file can be written to
183
	 *
184
	 * @param string $path
185
	 * @return bool
186
	 */
187 4
	public function isUpdatable($path) {
188
		try {
189 4
			$this->checkFileAccess($path);
190 2
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
191 2
			return false;
192
		}
193 2
		return $this->storage->isUpdatable($path);
194
	}
195
196
	/**
197
	 * check if a file can be deleted
198
	 *
199
	 * @param string $path
200
	 * @return bool
201
	 */
202 4
	public function isDeletable($path) {
203
		try {
204 4
			$this->checkFileAccess($path);
205 2
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
206 2
			return false;
207
		}
208 2
		return $this->storage->isDeletable($path);
209
	}
210
211
//	/**
212
//	 * check if a file can be shared
213
//	 *
214
//	 * @param string $path
215
//	 * @return bool
216
//	 */
217
//	public function isSharable($path) {
218
//		return $this->storage->isSharable($path);
219
//	}
220
//
221
//	/**
222
//	 * get the full permissions of a path.
223
//	 * Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php
224
//	 *
225
//	 * @param string $path
226
//	 * @return int
227
//	 */
228
	public function getPermissions($path) {
229
		try {
230
			$this->checkFileAccess($path);
231
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
232
			return $this->mask;
233
		}
234
		return $this->storage->getPermissions($path);
235
	}
236
//
237
//	/**
238
//	 * see http://php.net/manual/en/function.file_exists.php
239
//	 *
240
//	 * @param string $path
241
//	 * @return bool
242
//	 */
243
//	public function file_exists($path) {
244
//		return $this->storage->file_exists($path);
245
//	}
246
//
247
//	/**
248
//	 * see http://php.net/manual/en/function.filemtime.php
249
//	 *
250
//	 * @param string $path
251
//	 * @return int
252
//	 */
253
//	public function filemtime($path) {
254
//		return $this->storage->filemtime($path);
255
//	}
256
257
	/**
258
	 * see http://php.net/manual/en/function.file_get_contents.php
259
	 *
260
	 * @param string $path
261
	 * @return string
262
	 */
263 4
	public function file_get_contents($path) {
264 4
		$this->checkFileAccess($path);
265 2
		return $this->storage->file_get_contents($path);
266
	}
267
268
	/**
269
	 * see http://php.net/manual/en/function.file_put_contents.php
270
	 *
271
	 * @param string $path
272
	 * @param string $data
273
	 * @return bool
274
	 */
275
	public function file_put_contents($path, $data) {
276
		$this->checkFileAccess($path);
277
		return $this->storage->file_put_contents($path, $data);
278
	}
279
280
	/**
281
	 * see http://php.net/manual/en/function.unlink.php
282
	 *
283
	 * @param string $path
284
	 * @return bool
285
	 */
286 4
	public function unlink($path) {
287 4
		$this->checkFileAccess($path);
288 2
		return $this->storage->unlink($path);
289
	}
290
291
	/**
292
	 * see http://php.net/manual/en/function.rename.php
293
	 *
294
	 * @param string $path1
295
	 * @param string $path2
296
	 * @return bool
297
	 */
298
	public function rename($path1, $path2) {
299
		$this->checkFileAccess($path1);
300
		$this->checkFileAccess($path2);
301
		return $this->storage->rename($path1, $path2);
302
	}
303
304
	/**
305
	 * see http://php.net/manual/en/function.copy.php
306
	 *
307
	 * @param string $path1
308
	 * @param string $path2
309
	 * @return bool
310
	 */
311
	public function copy($path1, $path2) {
312
		$this->checkFileAccess($path1);
313
		$this->checkFileAccess($path2);
314
		return $this->storage->copy($path1, $path2);
315
	}
316
317
	/**
318
	 * see http://php.net/manual/en/function.fopen.php
319
	 *
320
	 * @param string $path
321
	 * @param string $mode
322
	 * @return resource
323
	 */
324
	public function fopen($path, $mode) {
325
		$this->checkFileAccess($path);
326
		return $this->storage->fopen($path, $mode);
327
	}
328
329
//	/**
330
//	 * get the mimetype for a file or folder
331
//	 * The mimetype for a folder is required to be "httpd/unix-directory"
332
//	 *
333
//	 * @param string $path
334
//	 * @return string
335
//	 */
336
//	public function getMimeType($path) {
337
//		return $this->storage->getMimeType($path);
338
//	}
339
//
340
//	/**
341
//	 * see http://php.net/manual/en/function.hash.php
342
//	 *
343
//	 * @param string $type
344
//	 * @param string $path
345
//	 * @param bool $raw
346
//	 * @return string
347
//	 */
348
//	public function hash($type, $path, $raw = false) {
349
//		return $this->storage->hash($type, $path, $raw);
350
//	}
351
//
352
//	/**
353
//	 * see http://php.net/manual/en/function.free_space.php
354
//	 *
355
//	 * @param string $path
356
//	 * @return int
357
//	 */
358
//	public function free_space($path) {
359
//		return $this->storage->free_space($path);
360
//	}
361
//
362
//	/**
363
//	 * search for occurrences of $query in file names
364
//	 *
365
//	 * @param string $query
366
//	 * @return array
367
//	 */
368
//	public function search($query) {
369
//		return $this->storage->search($query);
370
//	}
371
372
	/**
373
	 * see http://php.net/manual/en/function.touch.php
374
	 * If the backend does not support the operation, false should be returned
375
	 *
376
	 * @param string $path
377
	 * @param int $mtime
378
	 * @return bool
379
	 */
380
	public function touch($path, $mtime = null) {
381
		$this->checkFileAccess($path);
382
		return $this->storage->touch($path, $mtime);
383
	}
384
385
//	/**
386
//	 * get the path to a local version of the file.
387
//	 * The local version of the file can be temporary and doesn't have to be persistent across requests
388
//	 *
389
//	 * @param string $path
390
//	 * @return string
391
//	 */
392
//	public function getLocalFile($path) {
393
//		return $this->storage->getLocalFile($path);
394
//	}
395
//
396
//	/**
397
//	 * check if a file or folder has been updated since $time
398
//	 *
399
//	 * @param string $path
400
//	 * @param int $time
401
//	 * @return bool
402
//	 *
403
//	 * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed.
404
//	 * returning true for other changes in the folder is optional
405
//	 */
406
//	public function hasUpdated($path, $time) {
407
//		return $this->storage->hasUpdated($path, $time);
408
//	}
409
410
	/**
411
	 * get a cache instance for the storage
412
	 *
413
	 * @param string $path
414
	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache
415
	 * @return \OC\Files\Cache\Cache
416
	 */
417
	public function getCache($path = '', $storage = null) {
418
		if (!$storage) {
419
			$storage = $this;
420
		}
421
		$cache = $this->storage->getCache($path, $storage);
422
		return new CacheWrapper($cache, $storage, $this->operation);
423
	}
424
425
//	/**
426
//	 * get a scanner instance for the storage
427
//	 *
428
//	 * @param string $path
429
//	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
430
//	 * @return \OC\Files\Cache\Scanner
431
//	 */
432
//	public function getScanner($path = '', $storage = null) {
433
//		if (!$storage) {
434
//			$storage = $this;
435
//		}
436
//		return $this->storage->getScanner($path, $storage);
437
//	}
438
//
439
//
440
//	/**
441
//	 * get the user id of the owner of a file or folder
442
//	 *
443
//	 * @param string $path
444
//	 * @return string
445
//	 */
446
//	public function getOwner($path) {
447
//		return $this->storage->getOwner($path);
448
//	}
449
//
450
//	/**
451
//	 * get a watcher instance for the cache
452
//	 *
453
//	 * @param string $path
454
//	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher
455
//	 * @return \OC\Files\Cache\Watcher
456
//	 */
457
//	public function getWatcher($path = '', $storage = null) {
458
//		if (!$storage) {
459
//			$storage = $this;
460
//		}
461
//		return $this->storage->getWatcher($path, $storage);
462
//	}
463
//
464
//	public function getPropagator($storage = null) {
465
//		if (!$storage) {
466
//			$storage = $this;
467
//		}
468
//		return $this->storage->getPropagator($storage);
469
//	}
470
//
471
//	public function getUpdater($storage = null) {
472
//		if (!$storage) {
473
//			$storage = $this;
474
//		}
475
//		return $this->storage->getUpdater($storage);
476
//	}
477
//
478
//	/**
479
//	 * @return \OC\Files\Cache\Storage
480
//	 */
481
//	public function getStorageCache() {
482
//		return $this->storage->getStorageCache();
483
//	}
484
//
485
//	/**
486
//	 * get the ETag for a file or folder
487
//	 *
488
//	 * @param string $path
489
//	 * @return string
490
//	 */
491
//	public function getETag($path) {
492
//		return $this->storage->getETag($path);
493
//	}
494
//
495
//	/**
496
//	 * Returns true
497
//	 *
498
//	 * @return true
499
//	 */
500
//	public function test() {
501
//		return $this->storage->test();
502
//	}
503
//
504
//	/**
505
//	 * Returns the wrapped storage's value for isLocal()
506
//	 *
507
//	 * @return bool wrapped storage's isLocal() value
508
//	 */
509
//	public function isLocal() {
510
//		return $this->storage->isLocal();
511
//	}
512
//
513
//	/**
514
//	 * Check if the storage is an instance of $class or is a wrapper for a storage that is an instance of $class
515
//	 *
516
//	 * @param string $class
517
//	 * @return bool
518
//	 */
519
//	public function instanceOfStorage($class) {
520
//		return is_a($this, $class) or $this->storage->instanceOfStorage($class);
521
//	}
522
//
523
//	/**
524
//	 * Pass any methods custom to specific storage implementations to the wrapped storage
525
//	 *
526
//	 * @param string $method
527
//	 * @param array $args
528
//	 * @return mixed
529
//	 */
530
//	public function __call($method, $args) {
531
//		return call_user_func_array(array($this->storage, $method), $args);
532
//	}
533
534
	/**
535
	 * A custom storage implementation can return an url for direct download of a give file.
536
	 *
537
	 * For now the returned array can hold the parameter url - in future more attributes might follow.
538
	 *
539
	 * @param string $path
540
	 * @return array
541
	 */
542 4
	public function getDirectDownload($path) {
543 4
		$this->checkFileAccess($path);
544 2
		return $this->storage->getDirectDownload($path);
545
	}
546
547
//	/**
548
//	 * Get availability of the storage
549
//	 *
550
//	 * @return array [ available, last_checked ]
551
//	 */
552
//	public function getAvailability() {
553
//		return $this->storage->getAvailability();
554
//	}
555
//
556
//	/**
557
//	 * Set availability of the storage
558
//	 *
559
//	 * @param bool $isAvailable
560
//	 */
561
//	public function setAvailability($isAvailable) {
562
//		$this->storage->setAvailability($isAvailable);
563
//	}
564
//
565
//	/**
566
//	 * @param string $path the path of the target folder
567
//	 * @param string $fileName the name of the file itself
568
//	 * @return void
569
//	 * @throws InvalidPathException
570
//	 */
571
//	public function verifyPath($path, $fileName) {
572
//		$this->storage->verifyPath($path, $fileName);
573
//	}
574
575
	/**
576
	 * @param IStorage $sourceStorage
577
	 * @param string $sourceInternalPath
578
	 * @param string $targetInternalPath
579
	 * @return bool
580
	 */
581
	public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
582
		if ($sourceStorage === $this) {
583
			return $this->copy($sourceInternalPath, $targetInternalPath);
584
		}
585
586
		$this->checkFileAccess($targetInternalPath);
587
		return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
588
	}
589
590
	/**
591
	 * @param IStorage $sourceStorage
592
	 * @param string $sourceInternalPath
593
	 * @param string $targetInternalPath
594
	 * @return bool
595
	 */
596
	public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
597
		if ($sourceStorage === $this) {
598
			return $this->rename($sourceInternalPath, $targetInternalPath);
599
		}
600
601
		$this->checkFileAccess($targetInternalPath);
602
		return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
603
	}
604
605
//	/**
606
//	 * @param string $path
607
//	 * @return array
608
//	 */
609
//	public function getMetaData($path) {
610
//		return $this->storage->getMetaData($path);
611
//	}
612
//
613
//	/**
614
//	 * @param string $path
615
//	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
616
//	 * @param \OCP\Lock\ILockingProvider $provider
617
//	 * @throws \OCP\Lock\LockedException
618
//	 */
619
//	public function acquireLock($path, $type, ILockingProvider $provider) {
620
//		if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
621
//			$this->storage->acquireLock($path, $type, $provider);
622
//		}
623
//	}
624
//
625
//	/**
626
//	 * @param string $path
627
//	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
628
//	 * @param \OCP\Lock\ILockingProvider $provider
629
//	 */
630
//	public function releaseLock($path, $type, ILockingProvider $provider) {
631
//		if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
632
//			$this->storage->releaseLock($path, $type, $provider);
633
//		}
634
//	}
635
//
636
//	/**
637
//	 * @param string $path
638
//	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
639
//	 * @param \OCP\Lock\ILockingProvider $provider
640
//	 */
641
//	public function changeLock($path, $type, ILockingProvider $provider) {
642
//		if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
643
//			$this->storage->changeLock($path, $type, $provider);
644
//		}
645
//	}
646
647
	public function writeStream(string $path, $stream, int $size = null): int {
648
		// Required for object storage since  part file is not in the storage so we cannot check it before moving it to the storage
649
		// As an alternative we might be able to check on the cache update/insert/delete though the Cache wrapper
650
		$result = $this->storage->writeStream($path, $stream, $size);
651
		try {
652
			$this->checkFileAccess($path);
653
		} catch (\Exception $e) {
654
			$this->storage->unlink($path);
655
			throw $e;
656
		}
657
		return $result;
658
659
	}
660
}
661