Passed
Push — master ( d144a8...c9639f )
by Morris
39:08 queued 27:16
created
apps/files_sharing/lib/SharedStorage.php 1 patch
Indentation   +464 added lines, -464 removed lines patch added patch discarded remove patch
@@ -50,468 +50,468 @@
 block discarded – undo
50 50
  */
51 51
 class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage, IDisableEncryptionStorage {
52 52
 
53
-	/** @var \OCP\Share\IShare */
54
-	private $superShare;
55
-
56
-	/** @var \OCP\Share\IShare[] */
57
-	private $groupedShares;
58
-
59
-	/**
60
-	 * @var \OC\Files\View
61
-	 */
62
-	private $ownerView;
63
-
64
-	private $initialized = false;
65
-
66
-	/**
67
-	 * @var ICacheEntry
68
-	 */
69
-	private $sourceRootInfo;
70
-
71
-	/** @var string */
72
-	private $user;
73
-
74
-	/**
75
-	 * @var \OCP\ILogger
76
-	 */
77
-	private $logger;
78
-
79
-	/** @var  IStorage */
80
-	private $nonMaskedStorage;
81
-
82
-	private $options;
83
-
84
-	/** @var boolean */
85
-	private $sharingDisabledForUser;
86
-
87
-	public function __construct($arguments) {
88
-		$this->ownerView = $arguments['ownerView'];
89
-		$this->logger = \OC::$server->getLogger();
90
-
91
-		$this->superShare = $arguments['superShare'];
92
-		$this->groupedShares = $arguments['groupedShares'];
93
-
94
-		$this->user = $arguments['user'];
95
-		if (isset($arguments['sharingDisabledForUser'])) {
96
-			$this->sharingDisabledForUser = $arguments['sharingDisabledForUser'];
97
-		} else {
98
-			$this->sharingDisabledForUser = false;
99
-		}
100
-
101
-		parent::__construct([
102
-			'storage' => null,
103
-			'root' => null,
104
-		]);
105
-	}
106
-
107
-	/**
108
-	 * @return ICacheEntry
109
-	 */
110
-	private function getSourceRootInfo() {
111
-		if (is_null($this->sourceRootInfo)) {
112
-			if (is_null($this->superShare->getNodeCacheEntry())) {
113
-				$this->init();
114
-				$this->sourceRootInfo = $this->nonMaskedStorage->getCache()->get($this->rootPath);
115
-			} else {
116
-				$this->sourceRootInfo = $this->superShare->getNodeCacheEntry();
117
-			}
118
-		}
119
-		return $this->sourceRootInfo;
120
-	}
121
-
122
-	private function init() {
123
-		if ($this->initialized) {
124
-			return;
125
-		}
126
-		$this->initialized = true;
127
-		try {
128
-			Filesystem::initMountPoints($this->superShare->getShareOwner());
129
-			$storageId = $this->superShare->getNodeCacheEntry() ? $this->superShare->getNodeCacheEntry()->getStorageId() : null;
130
-			$sourcePath = $this->ownerView->getPath($this->superShare->getNodeId(), $storageId);
131
-			[$this->nonMaskedStorage, $this->rootPath] = $this->ownerView->resolvePath($sourcePath);
132
-			$this->storage = new PermissionsMask([
133
-				'storage' => $this->nonMaskedStorage,
134
-				'mask' => $this->superShare->getPermissions(),
135
-			]);
136
-		} catch (NotFoundException $e) {
137
-			// original file not accessible or deleted, set FailedStorage
138
-			$this->storage = new FailedStorage(['exception' => $e]);
139
-			$this->cache = new FailedCache();
140
-			$this->rootPath = '';
141
-		} catch (NoUserException $e) {
142
-			// sharer user deleted, set FailedStorage
143
-			$this->storage = new FailedStorage(['exception' => $e]);
144
-			$this->cache = new FailedCache();
145
-			$this->rootPath = '';
146
-		} catch (\Exception $e) {
147
-			$this->storage = new FailedStorage(['exception' => $e]);
148
-			$this->cache = new FailedCache();
149
-			$this->rootPath = '';
150
-			$this->logger->logException($e);
151
-		}
152
-
153
-		if (!$this->nonMaskedStorage) {
154
-			$this->nonMaskedStorage = $this->storage;
155
-		}
156
-	}
157
-
158
-	/**
159
-	 * @inheritdoc
160
-	 */
161
-	public function instanceOfStorage($class) {
162
-		if ($class === '\OC\Files\Storage\Common') {
163
-			return true;
164
-		}
165
-		if (in_array($class, ['\OC\Files\Storage\Home', '\OC\Files\ObjectStore\HomeObjectStoreStorage', '\OCP\Files\IHomeStorage'])) {
166
-			return false;
167
-		}
168
-		return parent::instanceOfStorage($class);
169
-	}
170
-
171
-	/**
172
-	 * @return string
173
-	 */
174
-	public function getShareId() {
175
-		return $this->superShare->getId();
176
-	}
177
-
178
-	private function isValid() {
179
-		return $this->getSourceRootInfo() && ($this->getSourceRootInfo()->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE;
180
-	}
181
-
182
-	/**
183
-	 * get id of the mount point
184
-	 *
185
-	 * @return string
186
-	 */
187
-	public function getId() {
188
-		return 'shared::' . $this->getMountPoint();
189
-	}
190
-
191
-	/**
192
-	 * Get the permissions granted for a shared file
193
-	 *
194
-	 * @param string $target Shared target file path
195
-	 * @return int CRUDS permissions granted
196
-	 */
197
-	public function getPermissions($target = '') {
198
-		if (!$this->isValid()) {
199
-			return 0;
200
-		}
201
-		$permissions = parent::getPermissions($target) & $this->superShare->getPermissions();
202
-
203
-		// part files and the mount point always have delete permissions
204
-		if ($target === '' || pathinfo($target, PATHINFO_EXTENSION) === 'part') {
205
-			$permissions |= \OCP\Constants::PERMISSION_DELETE;
206
-		}
207
-
208
-		if ($this->sharingDisabledForUser) {
209
-			$permissions &= ~\OCP\Constants::PERMISSION_SHARE;
210
-		}
211
-
212
-		return $permissions;
213
-	}
214
-
215
-	public function isCreatable($path) {
216
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_CREATE);
217
-	}
218
-
219
-	public function isReadable($path) {
220
-		if (!$this->isValid()) {
221
-			return false;
222
-		}
223
-		if (!$this->file_exists($path)) {
224
-			return false;
225
-		}
226
-		/** @var IStorage $storage */
227
-		/** @var string $internalPath */
228
-		[$storage, $internalPath] = $this->resolvePath($path);
229
-		return $storage->isReadable($internalPath);
230
-	}
231
-
232
-	public function isUpdatable($path) {
233
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_UPDATE);
234
-	}
235
-
236
-	public function isDeletable($path) {
237
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_DELETE);
238
-	}
239
-
240
-	public function isSharable($path) {
241
-		if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
242
-			return false;
243
-		}
244
-		return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE);
245
-	}
246
-
247
-	public function fopen($path, $mode) {
248
-		$source = $this->getUnjailedPath($path);
249
-		switch ($mode) {
250
-			case 'r+':
251
-			case 'rb+':
252
-			case 'w+':
253
-			case 'wb+':
254
-			case 'x+':
255
-			case 'xb+':
256
-			case 'a+':
257
-			case 'ab+':
258
-			case 'w':
259
-			case 'wb':
260
-			case 'x':
261
-			case 'xb':
262
-			case 'a':
263
-			case 'ab':
264
-				$creatable = $this->isCreatable(dirname($path));
265
-				$updatable = $this->isUpdatable($path);
266
-				// if neither permissions given, no need to continue
267
-				if (!$creatable && !$updatable) {
268
-					if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
269
-						$updatable = $this->isUpdatable(dirname($path));
270
-					}
271
-
272
-					if (!$updatable) {
273
-						return false;
274
-					}
275
-				}
276
-
277
-				$exists = $this->file_exists($path);
278
-				// if a file exists, updatable permissions are required
279
-				if ($exists && !$updatable) {
280
-					return false;
281
-				}
282
-
283
-				// part file is allowed if !$creatable but the final file is $updatable
284
-				if (pathinfo($path, PATHINFO_EXTENSION) !== 'part') {
285
-					if (!$exists && !$creatable) {
286
-						return false;
287
-					}
288
-				}
289
-		}
290
-		$info = [
291
-			'target' => $this->getMountPoint() . '/' . $path,
292
-			'source' => $source,
293
-			'mode' => $mode,
294
-		];
295
-		\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info);
296
-		return $this->nonMaskedStorage->fopen($this->getUnjailedPath($path), $mode);
297
-	}
298
-
299
-	/**
300
-	 * see http://php.net/manual/en/function.rename.php
301
-	 *
302
-	 * @param string $path1
303
-	 * @param string $path2
304
-	 * @return bool
305
-	 */
306
-	public function rename($path1, $path2) {
307
-		$this->init();
308
-		$isPartFile = pathinfo($path1, PATHINFO_EXTENSION) === 'part';
309
-		$targetExists = $this->file_exists($path2);
310
-		$sameFolder = dirname($path1) === dirname($path2);
311
-
312
-		if ($targetExists || ($sameFolder && !$isPartFile)) {
313
-			if (!$this->isUpdatable('')) {
314
-				return false;
315
-			}
316
-		} else {
317
-			if (!$this->isCreatable('')) {
318
-				return false;
319
-			}
320
-		}
321
-
322
-		return $this->nonMaskedStorage->rename($this->getUnjailedPath($path1), $this->getUnjailedPath($path2));
323
-	}
324
-
325
-	/**
326
-	 * return mount point of share, relative to data/user/files
327
-	 *
328
-	 * @return string
329
-	 */
330
-	public function getMountPoint() {
331
-		return $this->superShare->getTarget();
332
-	}
333
-
334
-	/**
335
-	 * @param string $path
336
-	 */
337
-	public function setMountPoint($path) {
338
-		$this->superShare->setTarget($path);
339
-
340
-		foreach ($this->groupedShares as $share) {
341
-			$share->setTarget($path);
342
-		}
343
-	}
344
-
345
-	/**
346
-	 * get the user who shared the file
347
-	 *
348
-	 * @return string
349
-	 */
350
-	public function getSharedFrom() {
351
-		return $this->superShare->getShareOwner();
352
-	}
353
-
354
-	/**
355
-	 * @return \OCP\Share\IShare
356
-	 */
357
-	public function getShare() {
358
-		return $this->superShare;
359
-	}
360
-
361
-	/**
362
-	 * return share type, can be "file" or "folder"
363
-	 *
364
-	 * @return string
365
-	 */
366
-	public function getItemType() {
367
-		return $this->superShare->getNodeType();
368
-	}
369
-
370
-	/**
371
-	 * @param string $path
372
-	 * @param null $storage
373
-	 * @return Cache
374
-	 */
375
-	public function getCache($path = '', $storage = null) {
376
-		if ($this->cache) {
377
-			return $this->cache;
378
-		}
379
-		if (!$storage) {
380
-			$storage = $this;
381
-		}
382
-		$sourceRoot = $this->getSourceRootInfo();
383
-		if ($this->storage instanceof FailedStorage) {
384
-			return new FailedCache();
385
-		}
386
-
387
-		$this->cache = new \OCA\Files_Sharing\Cache($storage, $sourceRoot, $this->superShare);
388
-		return $this->cache;
389
-	}
390
-
391
-	public function getScanner($path = '', $storage = null) {
392
-		if (!$storage) {
393
-			$storage = $this;
394
-		}
395
-		return new \OCA\Files_Sharing\Scanner($storage);
396
-	}
397
-
398
-	public function getOwner($path) {
399
-		return $this->superShare->getShareOwner();
400
-	}
401
-
402
-	public function getWatcher($path = '', $storage = null) {
403
-		// cache updating is handled by the share source
404
-		return new NullWatcher();
405
-	}
406
-
407
-	/**
408
-	 * unshare complete storage, also the grouped shares
409
-	 *
410
-	 * @return bool
411
-	 */
412
-	public function unshareStorage() {
413
-		foreach ($this->groupedShares as $share) {
414
-			\OC::$server->getShareManager()->deleteFromSelf($share, $this->user);
415
-		}
416
-		return true;
417
-	}
418
-
419
-	/**
420
-	 * @param string $path
421
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
422
-	 * @param \OCP\Lock\ILockingProvider $provider
423
-	 * @throws \OCP\Lock\LockedException
424
-	 */
425
-	public function acquireLock($path, $type, ILockingProvider $provider) {
426
-		/** @var \OCP\Files\Storage $targetStorage */
427
-		[$targetStorage, $targetInternalPath] = $this->resolvePath($path);
428
-		$targetStorage->acquireLock($targetInternalPath, $type, $provider);
429
-		// lock the parent folders of the owner when locking the share as recipient
430
-		if ($path === '') {
431
-			$sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
432
-			$this->ownerView->lockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
433
-		}
434
-	}
435
-
436
-	/**
437
-	 * @param string $path
438
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
439
-	 * @param \OCP\Lock\ILockingProvider $provider
440
-	 */
441
-	public function releaseLock($path, $type, ILockingProvider $provider) {
442
-		/** @var \OCP\Files\Storage $targetStorage */
443
-		[$targetStorage, $targetInternalPath] = $this->resolvePath($path);
444
-		$targetStorage->releaseLock($targetInternalPath, $type, $provider);
445
-		// unlock the parent folders of the owner when unlocking the share as recipient
446
-		if ($path === '') {
447
-			$sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
448
-			$this->ownerView->unlockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
449
-		}
450
-	}
451
-
452
-	/**
453
-	 * @param string $path
454
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
455
-	 * @param \OCP\Lock\ILockingProvider $provider
456
-	 */
457
-	public function changeLock($path, $type, ILockingProvider $provider) {
458
-		/** @var \OCP\Files\Storage $targetStorage */
459
-		[$targetStorage, $targetInternalPath] = $this->resolvePath($path);
460
-		$targetStorage->changeLock($targetInternalPath, $type, $provider);
461
-	}
462
-
463
-	/**
464
-	 * @return array [ available, last_checked ]
465
-	 */
466
-	public function getAvailability() {
467
-		// shares do not participate in availability logic
468
-		return [
469
-			'available' => true,
470
-			'last_checked' => 0,
471
-		];
472
-	}
473
-
474
-	/**
475
-	 * @param bool $available
476
-	 */
477
-	public function setAvailability($available) {
478
-		// shares do not participate in availability logic
479
-	}
480
-
481
-	public function getSourceStorage() {
482
-		$this->init();
483
-		return $this->nonMaskedStorage;
484
-	}
485
-
486
-	public function getWrapperStorage() {
487
-		$this->init();
488
-		return $this->storage;
489
-	}
490
-
491
-	public function file_get_contents($path) {
492
-		$info = [
493
-			'target' => $this->getMountPoint() . '/' . $path,
494
-			'source' => $this->getUnjailedPath($path),
495
-		];
496
-		\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
497
-		return parent::file_get_contents($path);
498
-	}
499
-
500
-	public function file_put_contents($path, $data) {
501
-		$info = [
502
-			'target' => $this->getMountPoint() . '/' . $path,
503
-			'source' => $this->getUnjailedPath($path),
504
-		];
505
-		\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
506
-		return parent::file_put_contents($path, $data);
507
-	}
508
-
509
-	public function setMountOptions(array $options) {
510
-		$this->mountOptions = $options;
511
-	}
512
-
513
-	public function getUnjailedPath($path) {
514
-		$this->init();
515
-		return parent::getUnjailedPath($path);
516
-	}
53
+    /** @var \OCP\Share\IShare */
54
+    private $superShare;
55
+
56
+    /** @var \OCP\Share\IShare[] */
57
+    private $groupedShares;
58
+
59
+    /**
60
+     * @var \OC\Files\View
61
+     */
62
+    private $ownerView;
63
+
64
+    private $initialized = false;
65
+
66
+    /**
67
+     * @var ICacheEntry
68
+     */
69
+    private $sourceRootInfo;
70
+
71
+    /** @var string */
72
+    private $user;
73
+
74
+    /**
75
+     * @var \OCP\ILogger
76
+     */
77
+    private $logger;
78
+
79
+    /** @var  IStorage */
80
+    private $nonMaskedStorage;
81
+
82
+    private $options;
83
+
84
+    /** @var boolean */
85
+    private $sharingDisabledForUser;
86
+
87
+    public function __construct($arguments) {
88
+        $this->ownerView = $arguments['ownerView'];
89
+        $this->logger = \OC::$server->getLogger();
90
+
91
+        $this->superShare = $arguments['superShare'];
92
+        $this->groupedShares = $arguments['groupedShares'];
93
+
94
+        $this->user = $arguments['user'];
95
+        if (isset($arguments['sharingDisabledForUser'])) {
96
+            $this->sharingDisabledForUser = $arguments['sharingDisabledForUser'];
97
+        } else {
98
+            $this->sharingDisabledForUser = false;
99
+        }
100
+
101
+        parent::__construct([
102
+            'storage' => null,
103
+            'root' => null,
104
+        ]);
105
+    }
106
+
107
+    /**
108
+     * @return ICacheEntry
109
+     */
110
+    private function getSourceRootInfo() {
111
+        if (is_null($this->sourceRootInfo)) {
112
+            if (is_null($this->superShare->getNodeCacheEntry())) {
113
+                $this->init();
114
+                $this->sourceRootInfo = $this->nonMaskedStorage->getCache()->get($this->rootPath);
115
+            } else {
116
+                $this->sourceRootInfo = $this->superShare->getNodeCacheEntry();
117
+            }
118
+        }
119
+        return $this->sourceRootInfo;
120
+    }
121
+
122
+    private function init() {
123
+        if ($this->initialized) {
124
+            return;
125
+        }
126
+        $this->initialized = true;
127
+        try {
128
+            Filesystem::initMountPoints($this->superShare->getShareOwner());
129
+            $storageId = $this->superShare->getNodeCacheEntry() ? $this->superShare->getNodeCacheEntry()->getStorageId() : null;
130
+            $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId(), $storageId);
131
+            [$this->nonMaskedStorage, $this->rootPath] = $this->ownerView->resolvePath($sourcePath);
132
+            $this->storage = new PermissionsMask([
133
+                'storage' => $this->nonMaskedStorage,
134
+                'mask' => $this->superShare->getPermissions(),
135
+            ]);
136
+        } catch (NotFoundException $e) {
137
+            // original file not accessible or deleted, set FailedStorage
138
+            $this->storage = new FailedStorage(['exception' => $e]);
139
+            $this->cache = new FailedCache();
140
+            $this->rootPath = '';
141
+        } catch (NoUserException $e) {
142
+            // sharer user deleted, set FailedStorage
143
+            $this->storage = new FailedStorage(['exception' => $e]);
144
+            $this->cache = new FailedCache();
145
+            $this->rootPath = '';
146
+        } catch (\Exception $e) {
147
+            $this->storage = new FailedStorage(['exception' => $e]);
148
+            $this->cache = new FailedCache();
149
+            $this->rootPath = '';
150
+            $this->logger->logException($e);
151
+        }
152
+
153
+        if (!$this->nonMaskedStorage) {
154
+            $this->nonMaskedStorage = $this->storage;
155
+        }
156
+    }
157
+
158
+    /**
159
+     * @inheritdoc
160
+     */
161
+    public function instanceOfStorage($class) {
162
+        if ($class === '\OC\Files\Storage\Common') {
163
+            return true;
164
+        }
165
+        if (in_array($class, ['\OC\Files\Storage\Home', '\OC\Files\ObjectStore\HomeObjectStoreStorage', '\OCP\Files\IHomeStorage'])) {
166
+            return false;
167
+        }
168
+        return parent::instanceOfStorage($class);
169
+    }
170
+
171
+    /**
172
+     * @return string
173
+     */
174
+    public function getShareId() {
175
+        return $this->superShare->getId();
176
+    }
177
+
178
+    private function isValid() {
179
+        return $this->getSourceRootInfo() && ($this->getSourceRootInfo()->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE;
180
+    }
181
+
182
+    /**
183
+     * get id of the mount point
184
+     *
185
+     * @return string
186
+     */
187
+    public function getId() {
188
+        return 'shared::' . $this->getMountPoint();
189
+    }
190
+
191
+    /**
192
+     * Get the permissions granted for a shared file
193
+     *
194
+     * @param string $target Shared target file path
195
+     * @return int CRUDS permissions granted
196
+     */
197
+    public function getPermissions($target = '') {
198
+        if (!$this->isValid()) {
199
+            return 0;
200
+        }
201
+        $permissions = parent::getPermissions($target) & $this->superShare->getPermissions();
202
+
203
+        // part files and the mount point always have delete permissions
204
+        if ($target === '' || pathinfo($target, PATHINFO_EXTENSION) === 'part') {
205
+            $permissions |= \OCP\Constants::PERMISSION_DELETE;
206
+        }
207
+
208
+        if ($this->sharingDisabledForUser) {
209
+            $permissions &= ~\OCP\Constants::PERMISSION_SHARE;
210
+        }
211
+
212
+        return $permissions;
213
+    }
214
+
215
+    public function isCreatable($path) {
216
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_CREATE);
217
+    }
218
+
219
+    public function isReadable($path) {
220
+        if (!$this->isValid()) {
221
+            return false;
222
+        }
223
+        if (!$this->file_exists($path)) {
224
+            return false;
225
+        }
226
+        /** @var IStorage $storage */
227
+        /** @var string $internalPath */
228
+        [$storage, $internalPath] = $this->resolvePath($path);
229
+        return $storage->isReadable($internalPath);
230
+    }
231
+
232
+    public function isUpdatable($path) {
233
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_UPDATE);
234
+    }
235
+
236
+    public function isDeletable($path) {
237
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_DELETE);
238
+    }
239
+
240
+    public function isSharable($path) {
241
+        if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
242
+            return false;
243
+        }
244
+        return ($this->getPermissions($path) & \OCP\Constants::PERMISSION_SHARE);
245
+    }
246
+
247
+    public function fopen($path, $mode) {
248
+        $source = $this->getUnjailedPath($path);
249
+        switch ($mode) {
250
+            case 'r+':
251
+            case 'rb+':
252
+            case 'w+':
253
+            case 'wb+':
254
+            case 'x+':
255
+            case 'xb+':
256
+            case 'a+':
257
+            case 'ab+':
258
+            case 'w':
259
+            case 'wb':
260
+            case 'x':
261
+            case 'xb':
262
+            case 'a':
263
+            case 'ab':
264
+                $creatable = $this->isCreatable(dirname($path));
265
+                $updatable = $this->isUpdatable($path);
266
+                // if neither permissions given, no need to continue
267
+                if (!$creatable && !$updatable) {
268
+                    if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
269
+                        $updatable = $this->isUpdatable(dirname($path));
270
+                    }
271
+
272
+                    if (!$updatable) {
273
+                        return false;
274
+                    }
275
+                }
276
+
277
+                $exists = $this->file_exists($path);
278
+                // if a file exists, updatable permissions are required
279
+                if ($exists && !$updatable) {
280
+                    return false;
281
+                }
282
+
283
+                // part file is allowed if !$creatable but the final file is $updatable
284
+                if (pathinfo($path, PATHINFO_EXTENSION) !== 'part') {
285
+                    if (!$exists && !$creatable) {
286
+                        return false;
287
+                    }
288
+                }
289
+        }
290
+        $info = [
291
+            'target' => $this->getMountPoint() . '/' . $path,
292
+            'source' => $source,
293
+            'mode' => $mode,
294
+        ];
295
+        \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info);
296
+        return $this->nonMaskedStorage->fopen($this->getUnjailedPath($path), $mode);
297
+    }
298
+
299
+    /**
300
+     * see http://php.net/manual/en/function.rename.php
301
+     *
302
+     * @param string $path1
303
+     * @param string $path2
304
+     * @return bool
305
+     */
306
+    public function rename($path1, $path2) {
307
+        $this->init();
308
+        $isPartFile = pathinfo($path1, PATHINFO_EXTENSION) === 'part';
309
+        $targetExists = $this->file_exists($path2);
310
+        $sameFolder = dirname($path1) === dirname($path2);
311
+
312
+        if ($targetExists || ($sameFolder && !$isPartFile)) {
313
+            if (!$this->isUpdatable('')) {
314
+                return false;
315
+            }
316
+        } else {
317
+            if (!$this->isCreatable('')) {
318
+                return false;
319
+            }
320
+        }
321
+
322
+        return $this->nonMaskedStorage->rename($this->getUnjailedPath($path1), $this->getUnjailedPath($path2));
323
+    }
324
+
325
+    /**
326
+     * return mount point of share, relative to data/user/files
327
+     *
328
+     * @return string
329
+     */
330
+    public function getMountPoint() {
331
+        return $this->superShare->getTarget();
332
+    }
333
+
334
+    /**
335
+     * @param string $path
336
+     */
337
+    public function setMountPoint($path) {
338
+        $this->superShare->setTarget($path);
339
+
340
+        foreach ($this->groupedShares as $share) {
341
+            $share->setTarget($path);
342
+        }
343
+    }
344
+
345
+    /**
346
+     * get the user who shared the file
347
+     *
348
+     * @return string
349
+     */
350
+    public function getSharedFrom() {
351
+        return $this->superShare->getShareOwner();
352
+    }
353
+
354
+    /**
355
+     * @return \OCP\Share\IShare
356
+     */
357
+    public function getShare() {
358
+        return $this->superShare;
359
+    }
360
+
361
+    /**
362
+     * return share type, can be "file" or "folder"
363
+     *
364
+     * @return string
365
+     */
366
+    public function getItemType() {
367
+        return $this->superShare->getNodeType();
368
+    }
369
+
370
+    /**
371
+     * @param string $path
372
+     * @param null $storage
373
+     * @return Cache
374
+     */
375
+    public function getCache($path = '', $storage = null) {
376
+        if ($this->cache) {
377
+            return $this->cache;
378
+        }
379
+        if (!$storage) {
380
+            $storage = $this;
381
+        }
382
+        $sourceRoot = $this->getSourceRootInfo();
383
+        if ($this->storage instanceof FailedStorage) {
384
+            return new FailedCache();
385
+        }
386
+
387
+        $this->cache = new \OCA\Files_Sharing\Cache($storage, $sourceRoot, $this->superShare);
388
+        return $this->cache;
389
+    }
390
+
391
+    public function getScanner($path = '', $storage = null) {
392
+        if (!$storage) {
393
+            $storage = $this;
394
+        }
395
+        return new \OCA\Files_Sharing\Scanner($storage);
396
+    }
397
+
398
+    public function getOwner($path) {
399
+        return $this->superShare->getShareOwner();
400
+    }
401
+
402
+    public function getWatcher($path = '', $storage = null) {
403
+        // cache updating is handled by the share source
404
+        return new NullWatcher();
405
+    }
406
+
407
+    /**
408
+     * unshare complete storage, also the grouped shares
409
+     *
410
+     * @return bool
411
+     */
412
+    public function unshareStorage() {
413
+        foreach ($this->groupedShares as $share) {
414
+            \OC::$server->getShareManager()->deleteFromSelf($share, $this->user);
415
+        }
416
+        return true;
417
+    }
418
+
419
+    /**
420
+     * @param string $path
421
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
422
+     * @param \OCP\Lock\ILockingProvider $provider
423
+     * @throws \OCP\Lock\LockedException
424
+     */
425
+    public function acquireLock($path, $type, ILockingProvider $provider) {
426
+        /** @var \OCP\Files\Storage $targetStorage */
427
+        [$targetStorage, $targetInternalPath] = $this->resolvePath($path);
428
+        $targetStorage->acquireLock($targetInternalPath, $type, $provider);
429
+        // lock the parent folders of the owner when locking the share as recipient
430
+        if ($path === '') {
431
+            $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
432
+            $this->ownerView->lockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
433
+        }
434
+    }
435
+
436
+    /**
437
+     * @param string $path
438
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
439
+     * @param \OCP\Lock\ILockingProvider $provider
440
+     */
441
+    public function releaseLock($path, $type, ILockingProvider $provider) {
442
+        /** @var \OCP\Files\Storage $targetStorage */
443
+        [$targetStorage, $targetInternalPath] = $this->resolvePath($path);
444
+        $targetStorage->releaseLock($targetInternalPath, $type, $provider);
445
+        // unlock the parent folders of the owner when unlocking the share as recipient
446
+        if ($path === '') {
447
+            $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
448
+            $this->ownerView->unlockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
449
+        }
450
+    }
451
+
452
+    /**
453
+     * @param string $path
454
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
455
+     * @param \OCP\Lock\ILockingProvider $provider
456
+     */
457
+    public function changeLock($path, $type, ILockingProvider $provider) {
458
+        /** @var \OCP\Files\Storage $targetStorage */
459
+        [$targetStorage, $targetInternalPath] = $this->resolvePath($path);
460
+        $targetStorage->changeLock($targetInternalPath, $type, $provider);
461
+    }
462
+
463
+    /**
464
+     * @return array [ available, last_checked ]
465
+     */
466
+    public function getAvailability() {
467
+        // shares do not participate in availability logic
468
+        return [
469
+            'available' => true,
470
+            'last_checked' => 0,
471
+        ];
472
+    }
473
+
474
+    /**
475
+     * @param bool $available
476
+     */
477
+    public function setAvailability($available) {
478
+        // shares do not participate in availability logic
479
+    }
480
+
481
+    public function getSourceStorage() {
482
+        $this->init();
483
+        return $this->nonMaskedStorage;
484
+    }
485
+
486
+    public function getWrapperStorage() {
487
+        $this->init();
488
+        return $this->storage;
489
+    }
490
+
491
+    public function file_get_contents($path) {
492
+        $info = [
493
+            'target' => $this->getMountPoint() . '/' . $path,
494
+            'source' => $this->getUnjailedPath($path),
495
+        ];
496
+        \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
497
+        return parent::file_get_contents($path);
498
+    }
499
+
500
+    public function file_put_contents($path, $data) {
501
+        $info = [
502
+            'target' => $this->getMountPoint() . '/' . $path,
503
+            'source' => $this->getUnjailedPath($path),
504
+        ];
505
+        \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
506
+        return parent::file_put_contents($path, $data);
507
+    }
508
+
509
+    public function setMountOptions(array $options) {
510
+        $this->mountOptions = $options;
511
+    }
512
+
513
+    public function getUnjailedPath($path) {
514
+        $this->init();
515
+        return parent::getUnjailedPath($path);
516
+    }
517 517
 }
Please login to merge, or discard this patch.
apps/files_trashbin/lib/Storage.php 2 patches
Indentation   +174 added lines, -174 removed lines patch added patch discarded remove patch
@@ -42,178 +42,178 @@
 block discarded – undo
42 42
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
43 43
 
44 44
 class Storage extends Wrapper {
45
-	/** @var IMountPoint */
46
-	private $mountPoint;
47
-
48
-	/** @var  IUserManager */
49
-	private $userManager;
50
-
51
-	/** @var ILogger */
52
-	private $logger;
53
-
54
-	/** @var EventDispatcherInterface */
55
-	private $eventDispatcher;
56
-
57
-	/** @var IRootFolder */
58
-	private $rootFolder;
59
-
60
-	/** @var ITrashManager */
61
-	private $trashManager;
62
-
63
-	/**
64
-	 * Storage constructor.
65
-	 *
66
-	 * @param array $parameters
67
-	 * @param ITrashManager $trashManager
68
-	 * @param IUserManager|null $userManager
69
-	 * @param ILogger|null $logger
70
-	 * @param EventDispatcherInterface|null $eventDispatcher
71
-	 * @param IRootFolder|null $rootFolder
72
-	 */
73
-	public function __construct(
74
-		$parameters,
75
-		ITrashManager $trashManager = null,
76
-		IUserManager $userManager = null,
77
-		ILogger $logger = null,
78
-		EventDispatcherInterface $eventDispatcher = null,
79
-		IRootFolder $rootFolder = null
80
-	) {
81
-		$this->mountPoint = $parameters['mountPoint'];
82
-		$this->trashManager = $trashManager;
83
-		$this->userManager = $userManager;
84
-		$this->logger = $logger;
85
-		$this->eventDispatcher = $eventDispatcher;
86
-		$this->rootFolder = $rootFolder;
87
-		parent::__construct($parameters);
88
-	}
89
-
90
-	/**
91
-	 * Deletes the given file by moving it into the trashbin.
92
-	 *
93
-	 * @param string $path path of file or folder to delete
94
-	 *
95
-	 * @return bool true if the operation succeeded, false otherwise
96
-	 */
97
-	public function unlink($path) {
98
-		try {
99
-			return $this->doDelete($path, 'unlink');
100
-		} catch (GenericEncryptionException $e) {
101
-			// in case of a encryption exception we delete the file right away
102
-			$this->logger->info(
103
-				"Can't move file " . $path .
104
-				" to the trash bin, therefore it was deleted right away");
105
-
106
-			return $this->storage->unlink($path);
107
-		}
108
-	}
109
-
110
-	/**
111
-	 * Deletes the given folder by moving it into the trashbin.
112
-	 *
113
-	 * @param string $path path of folder to delete
114
-	 *
115
-	 * @return bool true if the operation succeeded, false otherwise
116
-	 */
117
-	public function rmdir($path) {
118
-		return $this->doDelete($path, 'rmdir');
119
-	}
120
-
121
-	/**
122
-	 * check if it is a file located in data/user/files only files in the
123
-	 * 'files' directory should be moved to the trash
124
-	 *
125
-	 * @param $path
126
-	 * @return bool
127
-	 */
128
-	protected function shouldMoveToTrash($path) {
129
-		$normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path);
130
-		$parts = explode('/', $normalized);
131
-		if (count($parts) < 4) {
132
-			return false;
133
-		}
134
-
135
-		// check if there is a app which want to disable the trash bin for this file
136
-		$fileId = $this->storage->getCache()->getId($path);
137
-		$owner = $this->storage->getOwner($path);
138
-		if ($owner === false) {
139
-			$nodes = $this->rootFolder->getById($fileId);
140
-		} else {
141
-			$nodes = $this->rootFolder->getUserFolder($owner)->getById($fileId);
142
-		}
143
-
144
-		foreach ($nodes as $node) {
145
-			$event = $this->createMoveToTrashEvent($node);
146
-			$this->eventDispatcher->dispatch('OCA\Files_Trashbin::moveToTrash', $event);
147
-			if ($event->shouldMoveToTrashBin() === false) {
148
-				return false;
149
-			}
150
-		}
151
-
152
-		if ($parts[2] === 'files' && $this->userManager->userExists($parts[1])) {
153
-			return true;
154
-		}
155
-
156
-		return false;
157
-	}
158
-
159
-	/**
160
-	 * get move to trash event
161
-	 *
162
-	 * @param Node $node
163
-	 * @return MoveToTrashEvent
164
-	 */
165
-	protected function createMoveToTrashEvent(Node $node) {
166
-		return new MoveToTrashEvent($node);
167
-	}
168
-
169
-	/**
170
-	 * Run the delete operation with the given method
171
-	 *
172
-	 * @param string $path path of file or folder to delete
173
-	 * @param string $method either "unlink" or "rmdir"
174
-	 *
175
-	 * @return bool true if the operation succeeded, false otherwise
176
-	 */
177
-	private function doDelete($path, $method) {
178
-		if (
179
-			!\OC::$server->getAppManager()->isEnabledForUser('files_trashbin')
180
-			|| (pathinfo($path, PATHINFO_EXTENSION) === 'part')
181
-			|| $this->shouldMoveToTrash($path) === false
182
-		) {
183
-			return call_user_func([$this->storage, $method], $path);
184
-		}
185
-
186
-		// check permissions before we continue, this is especially important for
187
-		// shared files
188
-		if (!$this->isDeletable($path)) {
189
-			return false;
190
-		}
191
-
192
-		$isMovedToTrash = $this->trashManager->moveToTrash($this, $path);
193
-		if (!$isMovedToTrash) {
194
-			return call_user_func([$this->storage, $method], $path);
195
-		} else {
196
-			return true;
197
-		}
198
-	}
199
-
200
-	/**
201
-	 * Setup the storate wrapper callback
202
-	 */
203
-	public static function setupStorage() {
204
-		\OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function ($mountPoint, $storage) {
205
-			return new \OCA\Files_Trashbin\Storage(
206
-				['storage' => $storage, 'mountPoint' => $mountPoint],
207
-				\OC::$server->query(ITrashManager::class),
208
-				\OC::$server->getUserManager(),
209
-				\OC::$server->getLogger(),
210
-				\OC::$server->getEventDispatcher(),
211
-				\OC::$server->getLazyRootFolder()
212
-			);
213
-		}, 1);
214
-	}
215
-
216
-	public function getMountPoint() {
217
-		return $this->mountPoint;
218
-	}
45
+    /** @var IMountPoint */
46
+    private $mountPoint;
47
+
48
+    /** @var  IUserManager */
49
+    private $userManager;
50
+
51
+    /** @var ILogger */
52
+    private $logger;
53
+
54
+    /** @var EventDispatcherInterface */
55
+    private $eventDispatcher;
56
+
57
+    /** @var IRootFolder */
58
+    private $rootFolder;
59
+
60
+    /** @var ITrashManager */
61
+    private $trashManager;
62
+
63
+    /**
64
+     * Storage constructor.
65
+     *
66
+     * @param array $parameters
67
+     * @param ITrashManager $trashManager
68
+     * @param IUserManager|null $userManager
69
+     * @param ILogger|null $logger
70
+     * @param EventDispatcherInterface|null $eventDispatcher
71
+     * @param IRootFolder|null $rootFolder
72
+     */
73
+    public function __construct(
74
+        $parameters,
75
+        ITrashManager $trashManager = null,
76
+        IUserManager $userManager = null,
77
+        ILogger $logger = null,
78
+        EventDispatcherInterface $eventDispatcher = null,
79
+        IRootFolder $rootFolder = null
80
+    ) {
81
+        $this->mountPoint = $parameters['mountPoint'];
82
+        $this->trashManager = $trashManager;
83
+        $this->userManager = $userManager;
84
+        $this->logger = $logger;
85
+        $this->eventDispatcher = $eventDispatcher;
86
+        $this->rootFolder = $rootFolder;
87
+        parent::__construct($parameters);
88
+    }
89
+
90
+    /**
91
+     * Deletes the given file by moving it into the trashbin.
92
+     *
93
+     * @param string $path path of file or folder to delete
94
+     *
95
+     * @return bool true if the operation succeeded, false otherwise
96
+     */
97
+    public function unlink($path) {
98
+        try {
99
+            return $this->doDelete($path, 'unlink');
100
+        } catch (GenericEncryptionException $e) {
101
+            // in case of a encryption exception we delete the file right away
102
+            $this->logger->info(
103
+                "Can't move file " . $path .
104
+                " to the trash bin, therefore it was deleted right away");
105
+
106
+            return $this->storage->unlink($path);
107
+        }
108
+    }
109
+
110
+    /**
111
+     * Deletes the given folder by moving it into the trashbin.
112
+     *
113
+     * @param string $path path of folder to delete
114
+     *
115
+     * @return bool true if the operation succeeded, false otherwise
116
+     */
117
+    public function rmdir($path) {
118
+        return $this->doDelete($path, 'rmdir');
119
+    }
120
+
121
+    /**
122
+     * check if it is a file located in data/user/files only files in the
123
+     * 'files' directory should be moved to the trash
124
+     *
125
+     * @param $path
126
+     * @return bool
127
+     */
128
+    protected function shouldMoveToTrash($path) {
129
+        $normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path);
130
+        $parts = explode('/', $normalized);
131
+        if (count($parts) < 4) {
132
+            return false;
133
+        }
134
+
135
+        // check if there is a app which want to disable the trash bin for this file
136
+        $fileId = $this->storage->getCache()->getId($path);
137
+        $owner = $this->storage->getOwner($path);
138
+        if ($owner === false) {
139
+            $nodes = $this->rootFolder->getById($fileId);
140
+        } else {
141
+            $nodes = $this->rootFolder->getUserFolder($owner)->getById($fileId);
142
+        }
143
+
144
+        foreach ($nodes as $node) {
145
+            $event = $this->createMoveToTrashEvent($node);
146
+            $this->eventDispatcher->dispatch('OCA\Files_Trashbin::moveToTrash', $event);
147
+            if ($event->shouldMoveToTrashBin() === false) {
148
+                return false;
149
+            }
150
+        }
151
+
152
+        if ($parts[2] === 'files' && $this->userManager->userExists($parts[1])) {
153
+            return true;
154
+        }
155
+
156
+        return false;
157
+    }
158
+
159
+    /**
160
+     * get move to trash event
161
+     *
162
+     * @param Node $node
163
+     * @return MoveToTrashEvent
164
+     */
165
+    protected function createMoveToTrashEvent(Node $node) {
166
+        return new MoveToTrashEvent($node);
167
+    }
168
+
169
+    /**
170
+     * Run the delete operation with the given method
171
+     *
172
+     * @param string $path path of file or folder to delete
173
+     * @param string $method either "unlink" or "rmdir"
174
+     *
175
+     * @return bool true if the operation succeeded, false otherwise
176
+     */
177
+    private function doDelete($path, $method) {
178
+        if (
179
+            !\OC::$server->getAppManager()->isEnabledForUser('files_trashbin')
180
+            || (pathinfo($path, PATHINFO_EXTENSION) === 'part')
181
+            || $this->shouldMoveToTrash($path) === false
182
+        ) {
183
+            return call_user_func([$this->storage, $method], $path);
184
+        }
185
+
186
+        // check permissions before we continue, this is especially important for
187
+        // shared files
188
+        if (!$this->isDeletable($path)) {
189
+            return false;
190
+        }
191
+
192
+        $isMovedToTrash = $this->trashManager->moveToTrash($this, $path);
193
+        if (!$isMovedToTrash) {
194
+            return call_user_func([$this->storage, $method], $path);
195
+        } else {
196
+            return true;
197
+        }
198
+    }
199
+
200
+    /**
201
+     * Setup the storate wrapper callback
202
+     */
203
+    public static function setupStorage() {
204
+        \OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function ($mountPoint, $storage) {
205
+            return new \OCA\Files_Trashbin\Storage(
206
+                ['storage' => $storage, 'mountPoint' => $mountPoint],
207
+                \OC::$server->query(ITrashManager::class),
208
+                \OC::$server->getUserManager(),
209
+                \OC::$server->getLogger(),
210
+                \OC::$server->getEventDispatcher(),
211
+                \OC::$server->getLazyRootFolder()
212
+            );
213
+        }, 1);
214
+    }
215
+
216
+    public function getMountPoint() {
217
+        return $this->mountPoint;
218
+    }
219 219
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -100,7 +100,7 @@  discard block
 block discarded – undo
100 100
 		} catch (GenericEncryptionException $e) {
101 101
 			// in case of a encryption exception we delete the file right away
102 102
 			$this->logger->info(
103
-				"Can't move file " . $path .
103
+				"Can't move file ".$path.
104 104
 				" to the trash bin, therefore it was deleted right away");
105 105
 
106 106
 			return $this->storage->unlink($path);
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
 	 * @return bool
127 127
 	 */
128 128
 	protected function shouldMoveToTrash($path) {
129
-		$normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path);
129
+		$normalized = Filesystem::normalizePath($this->mountPoint.'/'.$path);
130 130
 		$parts = explode('/', $normalized);
131 131
 		if (count($parts) < 4) {
132 132
 			return false;
@@ -201,7 +201,7 @@  discard block
 block discarded – undo
201 201
 	 * Setup the storate wrapper callback
202 202
 	 */
203 203
 	public static function setupStorage() {
204
-		\OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function ($mountPoint, $storage) {
204
+		\OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function($mountPoint, $storage) {
205 205
 			return new \OCA\Files_Trashbin\Storage(
206 206
 				['storage' => $storage, 'mountPoint' => $mountPoint],
207 207
 				\OC::$server->query(ITrashManager::class),
Please login to merge, or discard this patch.