Completed
Push — stable9 ( 485cb1...e094cf )
by Lukas
26:41 queued 26:23
created

apps/files_sharing/lib/sharedstorage.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Bart Visscher <[email protected]>
6
 * @author Björn Schießle <[email protected]>
7
 * @author Joas Schilling <[email protected]>
8
 * @author Michael Gapczynski <[email protected]>
9
 * @author Morris Jobke <[email protected]>
10
 * @author Robin Appelman <[email protected]>
11
 * @author Robin McCorkell <[email protected]>
12
 * @author Roeland Jago Douma <[email protected]>
13
 * @author scambra <[email protected]>
14
 * @author Vincent Petry <[email protected]>
15
 *
16
 * @license AGPL-3.0
17
 *
18
 * This code is free software: you can redistribute it and/or modify
19
 * it under the terms of the GNU Affero General Public License, version 3,
20
 * as published by the Free Software Foundation.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
 * GNU Affero General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU Affero General Public License, version 3,
28
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
29
 *
30
 */
31
32
namespace OC\Files\Storage;
33
34
use OC\Files\Filesystem;
35
use OC\Files\Cache\FailedCache;
36
use OCA\Files_Sharing\ISharedStorage;
37
use OCP\Constants;
38
use OCP\Files\Cache\ICacheEntry;
39
use OCP\Files\Storage\IStorage;
40
use OCP\Lock\ILockingProvider;
41
42
/**
43
 * Convert target path to source path and pass the function call to the correct storage provider
44
 */
45
class Shared extends \OC\Files\Storage\Common implements ISharedStorage {
46
47
	private $share;   // the shared resource
48
	private $files = array();
49
50
	/**
51
	 * @var \OC\Files\View
52
	 */
53
	private $ownerView;
54
55
	/**
56
	 * @var string
57
	 */
58
	private $user;
59
60
	private $initialized = false;
61
62
	/**
63
	 * @var ICacheEntry
64
	 */
65
	private $sourceRootInfo;
66
67
	/**
68
	 * @var IStorage
69
	 */
70
	private $sourceStorage;
71
72
	/**
73
	 * @var \OCP\ILogger
74
	 */
75
	private $logger;
76
77
	public function __construct($arguments) {
78
		$this->share = $arguments['share'];
79
		$this->ownerView = $arguments['ownerView'];
80
		$this->user = $arguments['user'];
81
		$this->logger = \OC::$server->getLogger();
82
	}
83
84
	private function init() {
85
		if ($this->initialized) {
86
			return;
87
		}
88
		$this->initialized = true;
89
		try {
90
			Filesystem::initMountPoints($this->share['uid_owner']);
91
			$sourcePath = $this->ownerView->getPath($this->share['file_source']);
92
			list($this->sourceStorage, $sourceInternalPath) = $this->ownerView->resolvePath($sourcePath);
93
			$this->sourceRootInfo = $this->sourceStorage->getCache()->get($sourceInternalPath);
94
		} catch (\Exception $e) {
95
			$this->logger->logException($e);
96
		}
97
	}
98
99
	private function isValid() {
100
		$this->init();
101
		return $this->sourceRootInfo && ($this->sourceRootInfo->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE;
102
	}
103
104
	/**
105
	 * get id of the mount point
106
	 *
107
	 * @return string
108
	 */
109
	public function getId() {
110
		return 'shared::' . $this->getMountPoint();
111
	}
112
113
	/**
114
	 * get file cache of the shared item source
115
	 *
116
	 * @return int
117
	 */
118
	public function getSourceId() {
119
		return (int)$this->share['file_source'];
120
	}
121
122
	/**
123
	 * Get the source file path, permissions, and owner for a shared file
124
	 *
125
	 * @param string $target Shared target file path
126
	 * @return array Returns array with the keys path, permissions, and owner or false if not found
127
	 */
128
	public function getFile($target) {
129
		$this->init();
130
		if (!isset($this->files[$target])) {
131
			// Check for partial files
132
			if (pathinfo($target, PATHINFO_EXTENSION) === 'part') {
133
				$source = \OC_Share_Backend_File::getSource(substr($target, 0, -5), $this->getShare());
134
				if ($source) {
135
					$source['path'] .= '.part';
136
					// All partial files have delete permission
137
					$source['permissions'] |= \OCP\Constants::PERMISSION_DELETE;
138
				}
139
			} else {
140
				$source = \OC_Share_Backend_File::getSource($target, $this->getShare());
141
			}
142
			$this->files[$target] = $source;
143
		}
144
		return $this->files[$target];
145
	}
146
147
	/**
148
	 * Get the source file path for a shared file
149
	 *
150
	 * @param string $target Shared target file path
151
	 * @return string|false source file path or false if not found
152
	 */
153
	public function getSourcePath($target) {
154
		if (!$this->isValid()){
155
			return false;
156
		}
157
		$source = $this->getFile($target);
158
		if ($source) {
159
			if (!isset($source['fullPath'])) {
160
				\OC\Files\Filesystem::initMountPoints($source['fileOwner']);
161
				$mount = \OC\Files\Filesystem::getMountByNumericId($source['storage']);
162
				if (is_array($mount) && !empty($mount)) {
163
					$this->files[$target]['fullPath'] = $mount[key($mount)]->getMountPoint() . $source['path'];
164
				} else {
165
					$this->files[$target]['fullPath'] = false;
166
					\OCP\Util::writeLog('files_sharing', "Unable to get mount for shared storage '" . $source['storage'] . "' user '" . $source['fileOwner'] . "'", \OCP\Util::ERROR);
167
				}
168
			}
169
			return $this->files[$target]['fullPath'];
170
		}
171
		return false;
172
	}
173
174
	/**
175
	 * Get the permissions granted for a shared file
176
	 *
177
	 * @param string $target Shared target file path
178
	 * @return int CRUDS permissions granted
179
	 */
180
	public function getPermissions($target = '') {
181
		if (!$this->isValid()) {
182
			return 0;
183
		}
184
		$permissions = $this->share['permissions'];
185
		// part files and the mount point always have delete permissions
186
		if ($target === '' || pathinfo($target, PATHINFO_EXTENSION) === 'part') {
187
			$permissions |= \OCP\Constants::PERMISSION_DELETE;
188
		}
189
190
		if (\OCP\Util::isSharingDisabledForUser()) {
191
			$permissions &= ~\OCP\Constants::PERMISSION_SHARE;
192
		}
193
194
		return $permissions;
195
	}
196
197
	public function mkdir($path) {
198
		if ($path == '' || $path == '/' || !$this->isCreatable(dirname($path))) {
199
			return false;
200
		} else if ($source = $this->getSourcePath($path)) {
201
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
202
			return $storage->mkdir($internalPath);
203
		}
204
		return false;
205
	}
206
207
	/**
208
	 * Delete the directory if DELETE permission is granted
209
	 *
210
	 * @param string $path
211
	 * @return boolean
212
	 */
213 View Code Duplication
	public function rmdir($path) {
214
215
		// never delete a share mount point
216
		if (empty($path)) {
217
			return false;
218
		}
219
220
		if (($source = $this->getSourcePath($path)) && $this->isDeletable($path)) {
221
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
222
			return $storage->rmdir($internalPath);
223
		}
224
		return false;
225
	}
226
227
	public function opendir($path) {
228
		$source = $this->getSourcePath($path);
229
		list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
230
		return $storage->opendir($internalPath);
231
	}
232
233
	public function is_dir($path) {
234
		$source = $this->getSourcePath($path);
235
		list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
236
		return $storage->is_dir($internalPath);
237
	}
238
239 View Code Duplication
	public function is_file($path) {
240
		if ($source = $this->getSourcePath($path)) {
241
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
242
			return $storage->is_file($internalPath);
243
		}
244
		return false;
245
	}
246
247
	public function stat($path) {
248
		if ($path == '' || $path == '/') {
249
			$stat['size'] = $this->filesize($path);
250
			$stat['mtime'] = $this->filemtime($path);
251
			return $stat;
252
		} else if ($source = $this->getSourcePath($path)) {
253
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
254
			return $storage->stat($internalPath);
255
		}
256
		return false;
257
	}
258
259 View Code Duplication
	public function filetype($path) {
260
		if ($path == '' || $path == '/') {
261
			return 'dir';
262
		} else if ($source = $this->getSourcePath($path)) {
263
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
264
			return $storage->filetype($internalPath);
265
		}
266
		return false;
267
	}
268
269
	public function filesize($path) {
270
		$source = $this->getSourcePath($path);
271
		list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
272
		return $storage->filesize($internalPath);
273
	}
274
275
	public function isCreatable($path) {
276
		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_CREATE);
277
	}
278
279
	public function isReadable($path) {
280
		if (!$this->isValid()) {
281
			return false;
282
		}
283
		if (!$this->file_exists($path)) {
284
			return false;
285
		}
286
		list($storage, $internalPath) = $this->resolvePath($path);
287
		return $storage->isReadable($internalPath);
288
	}
289
290
	public function isUpdatable($path) {
291
		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_UPDATE);
292
	}
293
294
	public function isDeletable($path) {
295
		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_DELETE);
296
	}
297
298
	public function isSharable($path) {
299
		if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
300
			return false;
301
		}
302
		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE);
303
	}
304
305 View Code Duplication
	public function file_exists($path) {
306
		if ($path == '' || $path == '/') {
307
			return true;
308
		} else if ($source = $this->getSourcePath($path)) {
309
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
310
			return $storage->file_exists($internalPath);
311
		}
312
		return false;
313
	}
314
315
	public function filemtime($path) {
316
		$source = $this->getSourcePath($path);
317
		list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
318
		return $storage->filemtime($internalPath);
319
	}
320
321
	public function file_get_contents($path) {
322
		$source = $this->getSourcePath($path);
323
		if ($source) {
324
			$info = array(
325
				'target' => $this->getMountPoint() . '/' . $path,
326
				'source' => $source,
327
			);
328
			\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
329
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
330
			return $storage->file_get_contents($internalPath);
331
		}
332
	}
333
334
	public function file_put_contents($path, $data) {
335
		if ($source = $this->getSourcePath($path)) {
336
			// Check if permission is granted
337
			if (($this->file_exists($path) && !$this->isUpdatable($path))
338
				|| ($this->is_dir($path) && !$this->isCreatable($path))
339
			) {
340
				return false;
341
			}
342
			$info = array(
343
				'target' => $this->getMountPoint() . '/' . $path,
344
				'source' => $source,
345
			);
346
			\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
347
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
348
			$result = $storage->file_put_contents($internalPath, $data);
349
			return $result;
350
		}
351
		return false;
352
	}
353
354
	/**
355
	 * Delete the file if DELETE permission is granted
356
	 *
357
	 * @param string $path
358
	 * @return boolean
359
	 */
360 View Code Duplication
	public function unlink($path) {
361
362
		// never delete a share mount point
363
		if (empty($path)) {
364
			return false;
365
		}
366
		if ($source = $this->getSourcePath($path)) {
367
			if ($this->isDeletable($path)) {
368
				list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
369
				return $storage->unlink($internalPath);
370
			}
371
		}
372
		return false;
373
	}
374
375
	public function rename($path1, $path2) {
376
		$this->init();
377
		// we need the paths relative to data/user/files
378
		$relPath1 = $this->getMountPoint() . '/' . $path1;
379
		$relPath2 = $this->getMountPoint() . '/' . $path2;
380
		$pathinfo = pathinfo($relPath1);
381
382
		$isPartFile = (isset($pathinfo['extension']) && $pathinfo['extension'] === 'part');
383
		$targetExists = $this->file_exists($path2);
384
		$sameFolder = (dirname($relPath1) === dirname($relPath2));
385
		if ($targetExists || ($sameFolder && !$isPartFile)) {
386
			// note that renaming a share mount point is always allowed
387
			if (!$this->isUpdatable('')) {
388
				return false;
389
			}
390
		} else {
391
			if (!$this->isCreatable('')) {
392
				return false;
393
			}
394
		}
395
396
397
		/**
398
		 * @var \OC\Files\Storage\Storage $sourceStorage
399
		 */
400
		list($sourceStorage, $sourceInternalPath) = $this->resolvePath($path1);
401
		/**
402
		 * @var \OC\Files\Storage\Storage $targetStorage
403
		 */
404
		list($targetStorage, $targetInternalPath) = $this->resolvePath($path2);
405
406
		return $targetStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
407
	}
408
409
	public function copy($path1, $path2) {
410
		// Copy the file if CREATE permission is granted
411
		if ($this->isCreatable(dirname($path2))) {
412
			/**
413
			 * @var \OC\Files\Storage\Storage $sourceStorage
414
			 */
415
			list($sourceStorage, $sourceInternalPath) = $this->resolvePath($path1);
416
			/**
417
			 * @var \OC\Files\Storage\Storage $targetStorage
418
			 */
419
			list($targetStorage, $targetInternalPath) = $this->resolvePath($path2);
420
421
			return $targetStorage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
422
		}
423
		return false;
424
	}
425
426
	public function fopen($path, $mode) {
427
		if ($source = $this->getSourcePath($path)) {
428
			switch ($mode) {
429
				case 'r+':
430
				case 'rb+':
431
				case 'w+':
432
				case 'wb+':
433
				case 'x+':
434
				case 'xb+':
435
				case 'a+':
436
				case 'ab+':
437
				case 'w':
438
				case 'wb':
439
				case 'x':
440
				case 'xb':
441
				case 'a':
442
				case 'ab':
443
					$creatable = $this->isCreatable($path);
444
					$updatable = $this->isUpdatable($path);
445
					// if neither permissions given, no need to continue
446
					if (!$creatable && !$updatable) {
447
						return false;
448
					}
449
450
					$exists = $this->file_exists($path);
451
					// if a file exists, updatable permissions are required
452
					if ($exists && !$updatable) {
453
						return false;
454
					}
455
456
					// part file is allowed if !$creatable but the final file is $updatable
457
					if (pathinfo($path, PATHINFO_EXTENSION) !== 'part') {
458
						if (!$exists && !$creatable) {
459
							return false;
460
						}
461
					}
462
			}
463
			$info = array(
464
				'target' => $this->getMountPoint() . '/' . $path,
465
				'source' => $source,
466
				'mode' => $mode,
467
			);
468
			\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info);
469
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
470
			return $storage->fopen($internalPath, $mode);
471
		}
472
		return false;
473
	}
474
475 View Code Duplication
	public function getMimeType($path) {
476
		if ($source = $this->getSourcePath($path)) {
477
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
478
			return $storage->getMimeType($internalPath);
479
		}
480
		return false;
481
	}
482
483
	public function free_space($path) {
484
		$source = $this->getSourcePath($path);
485
		if ($source) {
486
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
487
			return $storage->free_space($internalPath);
488
		}
489
		return \OCP\Files\FileInfo::SPACE_UNKNOWN;
490
	}
491
492 View Code Duplication
	public function getLocalFile($path) {
493
		if ($source = $this->getSourcePath($path)) {
494
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
495
			return $storage->getLocalFile($internalPath);
496
		}
497
		return false;
498
	}
499
500 View Code Duplication
	public function touch($path, $mtime = null) {
501
		if ($source = $this->getSourcePath($path)) {
502
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
503
			return $storage->touch($internalPath, $mtime);
504
		}
505
		return false;
506
	}
507
508
	/**
509
	 * return mount point of share, relative to data/user/files
510
	 *
511
	 * @return string
512
	 */
513
	public function getMountPoint() {
514
		return $this->share['file_target'];
515
	}
516
517
	public function setMountPoint($path) {
518
		$this->share['file_target'] = $path;
519
	}
520
521
	public function getShareType() {
522
		return $this->share['share_type'];
523
	}
524
525
	/**
526
	 * does the group share already has a user specific unique name
527
	 *
528
	 * @return bool
529
	 */
530
	public function uniqueNameSet() {
531
		return (isset($this->share['unique_name']) && $this->share['unique_name']);
532
	}
533
534
	/**
535
	 * the share now uses a unique name of this user
536
	 *
537
	 * @brief the share now uses a unique name of this user
538
	 */
539
	public function setUniqueName() {
540
		$this->share['unique_name'] = true;
541
	}
542
543
	/**
544
	 * get share ID
545
	 *
546
	 * @return integer unique share ID
547
	 */
548
	public function getShareId() {
549
		return $this->share['id'];
550
	}
551
552
	/**
553
	 * get the user who shared the file
554
	 *
555
	 * @return string
556
	 */
557
	public function getSharedFrom() {
558
		return $this->share['uid_owner'];
559
	}
560
561
	/**
562
	 * @return array
563
	 */
564
	public function getShare() {
565
		return $this->share;
566
	}
567
568
	/**
569
	 * return share type, can be "file" or "folder"
570
	 *
571
	 * @return string
572
	 */
573
	public function getItemType() {
574
		return $this->share['item_type'];
575
	}
576
577
	public function hasUpdated($path, $time) {
578
		return $this->filemtime($path) > $time;
579
	}
580
581
	public function getCache($path = '', $storage = null) {
582
		$this->init();
583
		if (is_null($this->sourceStorage)) {
584
			return new FailedCache(false);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \OC\Files\Cache\FailedCache(false); (OC\Files\Cache\FailedCache) is incompatible with the return type declared by the interface OC\Files\Storage\Storage::getCache of type OC\Files\Cache\Cache.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
585
		}
586
		if (!$storage) {
587
			$storage = $this;
588
		}
589
		return new \OC\Files\Cache\Shared_Cache($storage, $this->sourceStorage, $this->sourceRootInfo);
590
	}
591
592
	public function getScanner($path = '', $storage = null) {
593
		if (!$storage) {
594
			$storage = $this;
595
		}
596
		return new \OC\Files\Cache\SharedScanner($storage);
597
	}
598
599
	public function getPropagator($storage = null) {
600
		if (!$storage) {
601
			$storage = $this;
602
		}
603
		return new \OCA\Files_Sharing\SharedPropagator($storage);
604
	}
605
606
	public function getOwner($path) {
607
		if ($path == '') {
608
			$path = $this->getMountPoint();
609
		}
610
		$source = $this->getFile($path);
611
		if ($source) {
612
			return $source['fileOwner'];
613
		}
614
		return false;
615
	}
616
617 View Code Duplication
	public function getETag($path) {
618
		if ($source = $this->getSourcePath($path)) {
619
			list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
620
			return $storage->getETag($internalPath);
621
		}
622
		return null;
623
	}
624
625
	/**
626
	 * unshare complete storage, also the grouped shares
627
	 *
628
	 * @return bool
629
	 */
630
	public function unshareStorage() {
631
		$result = true;
632
		if (!empty($this->share['grouped'])) {
633
			foreach ($this->share['grouped'] as $share) {
634
				$result = $result && \OCP\Share::unshareFromSelf($share['item_type'], $share['file_target']);
635
			}
636
		}
637
		$result = $result && \OCP\Share::unshareFromSelf($this->getItemType(), $this->getMountPoint());
638
639
		return $result;
640
	}
641
642
	/**
643
	 * Resolve the path for the source of the share
644
	 *
645
	 * @param string $path
646
	 * @return array
647
	 */
648
	public function resolvePath($path) {
649
		$source = $this->getSourcePath($path);
650
		return \OC\Files\Filesystem::resolvePath($source);
651
	}
652
653
	/**
654
	 * @param \OCP\Files\Storage $sourceStorage
655
	 * @param string $sourceInternalPath
656
	 * @param string $targetInternalPath
657
	 * @return bool
658
	 */
659
	public function copyFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
660
		/** @var \OCP\Files\Storage $targetStorage */
661
		list($targetStorage, $targetInternalPath) = $this->resolvePath($targetInternalPath);
662
		return $targetStorage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
663
	}
664
665
	/**
666
	 * @param \OCP\Files\Storage $sourceStorage
667
	 * @param string $sourceInternalPath
668
	 * @param string $targetInternalPath
669
	 * @return bool
670
	 */
671
	public function moveFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
672
		/** @var \OCP\Files\Storage $targetStorage */
673
		list($targetStorage, $targetInternalPath) = $this->resolvePath($targetInternalPath);
674
		return $targetStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
675
	}
676
677
	/**
678
	 * @param string $path
679
	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
680
	 * @param \OCP\Lock\ILockingProvider $provider
681
	 * @throws \OCP\Lock\LockedException
682
	 */
683 View Code Duplication
	public function acquireLock($path, $type, ILockingProvider $provider) {
684
		/** @var \OCP\Files\Storage $targetStorage */
685
		list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
686
		$targetStorage->acquireLock($targetInternalPath, $type, $provider);
687
		// lock the parent folders of the owner when locking the share as recipient
688
		if ($path === '') {
689
			$sourcePath = $this->ownerView->getPath($this->share['file_source']);
690
			$this->ownerView->lockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
691
		}
692
	}
693
694
	/**
695
	 * @param string $path
696
	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
697
	 * @param \OCP\Lock\ILockingProvider $provider
698
	 */
699 View Code Duplication
	public function releaseLock($path, $type, ILockingProvider $provider) {
700
		/** @var \OCP\Files\Storage $targetStorage */
701
		list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
702
		$targetStorage->releaseLock($targetInternalPath, $type, $provider);
703
		// unlock the parent folders of the owner when unlocking the share as recipient
704
		if ($path === '') {
705
			$sourcePath = $this->ownerView->getPath($this->share['file_source']);
706
			$this->ownerView->unlockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
707
		}
708
	}
709
710
	/**
711
	 * @param string $path
712
	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
713
	 * @param \OCP\Lock\ILockingProvider $provider
714
	 */
715
	public function changeLock($path, $type, ILockingProvider $provider) {
716
		/** @var \OCP\Files\Storage $targetStorage */
717
		list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
718
		$targetStorage->changeLock($targetInternalPath, $type, $provider);
719
	}
720
721
	/**
722
	 * @return array [ available, last_checked ]
723
	 */
724
	public function getAvailability() {
725
		// shares do not participate in availability logic
726
		return [
727
			'available' => true,
728
			'last_checked' => 0
729
		];
730
	}
731
732
	/**
733
	 * @param bool $available
734
	 */
735
	public function setAvailability($available) {
736
		// shares do not participate in availability logic
737
	}
738
739
	public function isLocal() {
740
		$this->init();
741
		return $this->sourceStorage->isLocal();
742
	}
743
744
	public function getSourceStorage() {
745
		return $this->sourceStorage;
746
	}
747
}
748