Passed
Push — master ( a52894...c5c14d )
by Morris
10:12 queued 10s
created
lib/private/Share20/Manager.php 1 patch
Indentation   +1575 added lines, -1575 removed lines patch added patch discarded remove patch
@@ -72,1603 +72,1603 @@
 block discarded – undo
72 72
  */
73 73
 class Manager implements IManager {
74 74
 
75
-	/** @var IProviderFactory */
76
-	private $factory;
77
-	/** @var ILogger */
78
-	private $logger;
79
-	/** @var IConfig */
80
-	private $config;
81
-	/** @var ISecureRandom */
82
-	private $secureRandom;
83
-	/** @var IHasher */
84
-	private $hasher;
85
-	/** @var IMountManager */
86
-	private $mountManager;
87
-	/** @var IGroupManager */
88
-	private $groupManager;
89
-	/** @var IL10N */
90
-	private $l;
91
-	/** @var IFactory */
92
-	private $l10nFactory;
93
-	/** @var IUserManager */
94
-	private $userManager;
95
-	/** @var IRootFolder */
96
-	private $rootFolder;
97
-	/** @var CappedMemoryCache */
98
-	private $sharingDisabledForUsersCache;
99
-	/** @var EventDispatcherInterface */
100
-	private $eventDispatcher;
101
-	/** @var LegacyHooks */
102
-	private $legacyHooks;
103
-	/** @var IMailer */
104
-	private $mailer;
105
-	/** @var IURLGenerator */
106
-	private $urlGenerator;
107
-	/** @var \OC_Defaults */
108
-	private $defaults;
109
-
110
-
111
-	/**
112
-	 * Manager constructor.
113
-	 *
114
-	 * @param ILogger $logger
115
-	 * @param IConfig $config
116
-	 * @param ISecureRandom $secureRandom
117
-	 * @param IHasher $hasher
118
-	 * @param IMountManager $mountManager
119
-	 * @param IGroupManager $groupManager
120
-	 * @param IL10N $l
121
-	 * @param IFactory $l10nFactory
122
-	 * @param IProviderFactory $factory
123
-	 * @param IUserManager $userManager
124
-	 * @param IRootFolder $rootFolder
125
-	 * @param EventDispatcherInterface $eventDispatcher
126
-	 * @param IMailer $mailer
127
-	 * @param IURLGenerator $urlGenerator
128
-	 * @param \OC_Defaults $defaults
129
-	 */
130
-	public function __construct(
131
-			ILogger $logger,
132
-			IConfig $config,
133
-			ISecureRandom $secureRandom,
134
-			IHasher $hasher,
135
-			IMountManager $mountManager,
136
-			IGroupManager $groupManager,
137
-			IL10N $l,
138
-			IFactory $l10nFactory,
139
-			IProviderFactory $factory,
140
-			IUserManager $userManager,
141
-			IRootFolder $rootFolder,
142
-			EventDispatcherInterface $eventDispatcher,
143
-			IMailer $mailer,
144
-			IURLGenerator $urlGenerator,
145
-			\OC_Defaults $defaults
146
-	) {
147
-		$this->logger = $logger;
148
-		$this->config = $config;
149
-		$this->secureRandom = $secureRandom;
150
-		$this->hasher = $hasher;
151
-		$this->mountManager = $mountManager;
152
-		$this->groupManager = $groupManager;
153
-		$this->l = $l;
154
-		$this->l10nFactory = $l10nFactory;
155
-		$this->factory = $factory;
156
-		$this->userManager = $userManager;
157
-		$this->rootFolder = $rootFolder;
158
-		$this->eventDispatcher = $eventDispatcher;
159
-		$this->sharingDisabledForUsersCache = new CappedMemoryCache();
160
-		$this->legacyHooks = new LegacyHooks($this->eventDispatcher);
161
-		$this->mailer = $mailer;
162
-		$this->urlGenerator = $urlGenerator;
163
-		$this->defaults = $defaults;
164
-	}
165
-
166
-	/**
167
-	 * Convert from a full share id to a tuple (providerId, shareId)
168
-	 *
169
-	 * @param string $id
170
-	 * @return string[]
171
-	 */
172
-	private function splitFullId($id) {
173
-		return explode(':', $id, 2);
174
-	}
175
-
176
-	/**
177
-	 * Verify if a password meets all requirements
178
-	 *
179
-	 * @param string $password
180
-	 * @throws \Exception
181
-	 */
182
-	protected function verifyPassword($password) {
183
-		if ($password === null) {
184
-			// No password is set, check if this is allowed.
185
-			if ($this->shareApiLinkEnforcePassword()) {
186
-				throw new \InvalidArgumentException('Passwords are enforced for link shares');
187
-			}
188
-
189
-			return;
190
-		}
191
-
192
-		// Let others verify the password
193
-		try {
194
-			$event = new GenericEvent($password);
195
-			$this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event);
196
-		} catch (HintException $e) {
197
-			throw new \Exception($e->getHint());
198
-		}
199
-	}
200
-
201
-	/**
202
-	 * Check for generic requirements before creating a share
203
-	 *
204
-	 * @param \OCP\Share\IShare $share
205
-	 * @throws \InvalidArgumentException
206
-	 * @throws GenericShareException
207
-	 *
208
-	 * @suppress PhanUndeclaredClassMethod
209
-	 */
210
-	protected function generalCreateChecks(\OCP\Share\IShare $share) {
211
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
212
-			// We expect a valid user as sharedWith for user shares
213
-			if (!$this->userManager->userExists($share->getSharedWith())) {
214
-				throw new \InvalidArgumentException('SharedWith is not a valid user');
215
-			}
216
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
217
-			// We expect a valid group as sharedWith for group shares
218
-			if (!$this->groupManager->groupExists($share->getSharedWith())) {
219
-				throw new \InvalidArgumentException('SharedWith is not a valid group');
220
-			}
221
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
222
-			if ($share->getSharedWith() !== null) {
223
-				throw new \InvalidArgumentException('SharedWith should be empty');
224
-			}
225
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
226
-			if ($share->getSharedWith() === null) {
227
-				throw new \InvalidArgumentException('SharedWith should not be empty');
228
-			}
229
-		}  else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
230
-			if ($share->getSharedWith() === null) {
231
-				throw new \InvalidArgumentException('SharedWith should not be empty');
232
-			}
233
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
234
-			if ($share->getSharedWith() === null) {
235
-				throw new \InvalidArgumentException('SharedWith should not be empty');
236
-			}
237
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) {
238
-			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($share->getSharedWith());
239
-			if ($circle === null) {
240
-				throw new \InvalidArgumentException('SharedWith is not a valid circle');
241
-			}
242
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM) {
243
-		} else {
244
-			// We can't handle other types yet
245
-			throw new \InvalidArgumentException('unknown share type');
246
-		}
247
-
248
-		// Verify the initiator of the share is set
249
-		if ($share->getSharedBy() === null) {
250
-			throw new \InvalidArgumentException('SharedBy should be set');
251
-		}
252
-
253
-		// Cannot share with yourself
254
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
255
-			$share->getSharedWith() === $share->getSharedBy()) {
256
-			throw new \InvalidArgumentException('Can’t share with yourself');
257
-		}
258
-
259
-		// The path should be set
260
-		if ($share->getNode() === null) {
261
-			throw new \InvalidArgumentException('Path should be set');
262
-		}
263
-
264
-		// And it should be a file or a folder
265
-		if (!($share->getNode() instanceof \OCP\Files\File) &&
266
-				!($share->getNode() instanceof \OCP\Files\Folder)) {
267
-			throw new \InvalidArgumentException('Path should be either a file or a folder');
268
-		}
269
-
270
-		// And you can't share your rootfolder
271
-		if ($this->userManager->userExists($share->getSharedBy())) {
272
-			$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
273
-			$userFolderPath = $userFolder->getPath();
274
-		} else {
275
-			$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
276
-			$userFolderPath = $userFolder->getPath();
277
-		}
278
-		if ($userFolderPath === $share->getNode()->getPath()) {
279
-			throw new \InvalidArgumentException('You can’t share your root folder');
280
-		}
281
-
282
-		// Check if we actually have share permissions
283
-		if (!$share->getNode()->isShareable()) {
284
-			$message_t = $this->l->t('You are not allowed to share %s', [$share->getNode()->getPath()]);
285
-			throw new GenericShareException($message_t, $message_t, 404);
286
-		}
287
-
288
-		// Permissions should be set
289
-		if ($share->getPermissions() === null) {
290
-			throw new \InvalidArgumentException('A share requires permissions');
291
-		}
292
-
293
-		$mount = $share->getNode()->getMountPoint();
294
-		if ($share->getNode()->getOwner()->getUID() !== $share->getSharedBy()) {
295
-			// When it's a reshare use the parent share permissions as maximum
296
-			$userMountPointId = $mount->getStorageRootId();
297
-			$userMountPoints = $userFolder->getById($userMountPointId);
298
-			$userMountPoint = array_shift($userMountPoints);
299
-
300
-			/* Check if this is an incoming share */
301
-			$incomingShares = $this->getSharedWith($share->getSharedBy(), Share::SHARE_TYPE_USER, $userMountPoint, -1, 0);
302
-			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), Share::SHARE_TYPE_GROUP, $userMountPoint, -1, 0));
303
-			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), Share::SHARE_TYPE_ROOM, $userMountPoint, -1, 0));
304
-
305
-			/** @var \OCP\Share\IShare[] $incomingShares */
306
-			if (!empty($incomingShares)) {
307
-				$permissions = 0;
308
-				foreach ($incomingShares as $incomingShare) {
309
-					$permissions |= $incomingShare->getPermissions();
310
-				}
311
-			}
312
-		} else {
313
-			/*
75
+    /** @var IProviderFactory */
76
+    private $factory;
77
+    /** @var ILogger */
78
+    private $logger;
79
+    /** @var IConfig */
80
+    private $config;
81
+    /** @var ISecureRandom */
82
+    private $secureRandom;
83
+    /** @var IHasher */
84
+    private $hasher;
85
+    /** @var IMountManager */
86
+    private $mountManager;
87
+    /** @var IGroupManager */
88
+    private $groupManager;
89
+    /** @var IL10N */
90
+    private $l;
91
+    /** @var IFactory */
92
+    private $l10nFactory;
93
+    /** @var IUserManager */
94
+    private $userManager;
95
+    /** @var IRootFolder */
96
+    private $rootFolder;
97
+    /** @var CappedMemoryCache */
98
+    private $sharingDisabledForUsersCache;
99
+    /** @var EventDispatcherInterface */
100
+    private $eventDispatcher;
101
+    /** @var LegacyHooks */
102
+    private $legacyHooks;
103
+    /** @var IMailer */
104
+    private $mailer;
105
+    /** @var IURLGenerator */
106
+    private $urlGenerator;
107
+    /** @var \OC_Defaults */
108
+    private $defaults;
109
+
110
+
111
+    /**
112
+     * Manager constructor.
113
+     *
114
+     * @param ILogger $logger
115
+     * @param IConfig $config
116
+     * @param ISecureRandom $secureRandom
117
+     * @param IHasher $hasher
118
+     * @param IMountManager $mountManager
119
+     * @param IGroupManager $groupManager
120
+     * @param IL10N $l
121
+     * @param IFactory $l10nFactory
122
+     * @param IProviderFactory $factory
123
+     * @param IUserManager $userManager
124
+     * @param IRootFolder $rootFolder
125
+     * @param EventDispatcherInterface $eventDispatcher
126
+     * @param IMailer $mailer
127
+     * @param IURLGenerator $urlGenerator
128
+     * @param \OC_Defaults $defaults
129
+     */
130
+    public function __construct(
131
+            ILogger $logger,
132
+            IConfig $config,
133
+            ISecureRandom $secureRandom,
134
+            IHasher $hasher,
135
+            IMountManager $mountManager,
136
+            IGroupManager $groupManager,
137
+            IL10N $l,
138
+            IFactory $l10nFactory,
139
+            IProviderFactory $factory,
140
+            IUserManager $userManager,
141
+            IRootFolder $rootFolder,
142
+            EventDispatcherInterface $eventDispatcher,
143
+            IMailer $mailer,
144
+            IURLGenerator $urlGenerator,
145
+            \OC_Defaults $defaults
146
+    ) {
147
+        $this->logger = $logger;
148
+        $this->config = $config;
149
+        $this->secureRandom = $secureRandom;
150
+        $this->hasher = $hasher;
151
+        $this->mountManager = $mountManager;
152
+        $this->groupManager = $groupManager;
153
+        $this->l = $l;
154
+        $this->l10nFactory = $l10nFactory;
155
+        $this->factory = $factory;
156
+        $this->userManager = $userManager;
157
+        $this->rootFolder = $rootFolder;
158
+        $this->eventDispatcher = $eventDispatcher;
159
+        $this->sharingDisabledForUsersCache = new CappedMemoryCache();
160
+        $this->legacyHooks = new LegacyHooks($this->eventDispatcher);
161
+        $this->mailer = $mailer;
162
+        $this->urlGenerator = $urlGenerator;
163
+        $this->defaults = $defaults;
164
+    }
165
+
166
+    /**
167
+     * Convert from a full share id to a tuple (providerId, shareId)
168
+     *
169
+     * @param string $id
170
+     * @return string[]
171
+     */
172
+    private function splitFullId($id) {
173
+        return explode(':', $id, 2);
174
+    }
175
+
176
+    /**
177
+     * Verify if a password meets all requirements
178
+     *
179
+     * @param string $password
180
+     * @throws \Exception
181
+     */
182
+    protected function verifyPassword($password) {
183
+        if ($password === null) {
184
+            // No password is set, check if this is allowed.
185
+            if ($this->shareApiLinkEnforcePassword()) {
186
+                throw new \InvalidArgumentException('Passwords are enforced for link shares');
187
+            }
188
+
189
+            return;
190
+        }
191
+
192
+        // Let others verify the password
193
+        try {
194
+            $event = new GenericEvent($password);
195
+            $this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event);
196
+        } catch (HintException $e) {
197
+            throw new \Exception($e->getHint());
198
+        }
199
+    }
200
+
201
+    /**
202
+     * Check for generic requirements before creating a share
203
+     *
204
+     * @param \OCP\Share\IShare $share
205
+     * @throws \InvalidArgumentException
206
+     * @throws GenericShareException
207
+     *
208
+     * @suppress PhanUndeclaredClassMethod
209
+     */
210
+    protected function generalCreateChecks(\OCP\Share\IShare $share) {
211
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
212
+            // We expect a valid user as sharedWith for user shares
213
+            if (!$this->userManager->userExists($share->getSharedWith())) {
214
+                throw new \InvalidArgumentException('SharedWith is not a valid user');
215
+            }
216
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
217
+            // We expect a valid group as sharedWith for group shares
218
+            if (!$this->groupManager->groupExists($share->getSharedWith())) {
219
+                throw new \InvalidArgumentException('SharedWith is not a valid group');
220
+            }
221
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
222
+            if ($share->getSharedWith() !== null) {
223
+                throw new \InvalidArgumentException('SharedWith should be empty');
224
+            }
225
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
226
+            if ($share->getSharedWith() === null) {
227
+                throw new \InvalidArgumentException('SharedWith should not be empty');
228
+            }
229
+        }  else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
230
+            if ($share->getSharedWith() === null) {
231
+                throw new \InvalidArgumentException('SharedWith should not be empty');
232
+            }
233
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
234
+            if ($share->getSharedWith() === null) {
235
+                throw new \InvalidArgumentException('SharedWith should not be empty');
236
+            }
237
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) {
238
+            $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($share->getSharedWith());
239
+            if ($circle === null) {
240
+                throw new \InvalidArgumentException('SharedWith is not a valid circle');
241
+            }
242
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM) {
243
+        } else {
244
+            // We can't handle other types yet
245
+            throw new \InvalidArgumentException('unknown share type');
246
+        }
247
+
248
+        // Verify the initiator of the share is set
249
+        if ($share->getSharedBy() === null) {
250
+            throw new \InvalidArgumentException('SharedBy should be set');
251
+        }
252
+
253
+        // Cannot share with yourself
254
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
255
+            $share->getSharedWith() === $share->getSharedBy()) {
256
+            throw new \InvalidArgumentException('Can’t share with yourself');
257
+        }
258
+
259
+        // The path should be set
260
+        if ($share->getNode() === null) {
261
+            throw new \InvalidArgumentException('Path should be set');
262
+        }
263
+
264
+        // And it should be a file or a folder
265
+        if (!($share->getNode() instanceof \OCP\Files\File) &&
266
+                !($share->getNode() instanceof \OCP\Files\Folder)) {
267
+            throw new \InvalidArgumentException('Path should be either a file or a folder');
268
+        }
269
+
270
+        // And you can't share your rootfolder
271
+        if ($this->userManager->userExists($share->getSharedBy())) {
272
+            $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
273
+            $userFolderPath = $userFolder->getPath();
274
+        } else {
275
+            $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
276
+            $userFolderPath = $userFolder->getPath();
277
+        }
278
+        if ($userFolderPath === $share->getNode()->getPath()) {
279
+            throw new \InvalidArgumentException('You can’t share your root folder');
280
+        }
281
+
282
+        // Check if we actually have share permissions
283
+        if (!$share->getNode()->isShareable()) {
284
+            $message_t = $this->l->t('You are not allowed to share %s', [$share->getNode()->getPath()]);
285
+            throw new GenericShareException($message_t, $message_t, 404);
286
+        }
287
+
288
+        // Permissions should be set
289
+        if ($share->getPermissions() === null) {
290
+            throw new \InvalidArgumentException('A share requires permissions');
291
+        }
292
+
293
+        $mount = $share->getNode()->getMountPoint();
294
+        if ($share->getNode()->getOwner()->getUID() !== $share->getSharedBy()) {
295
+            // When it's a reshare use the parent share permissions as maximum
296
+            $userMountPointId = $mount->getStorageRootId();
297
+            $userMountPoints = $userFolder->getById($userMountPointId);
298
+            $userMountPoint = array_shift($userMountPoints);
299
+
300
+            /* Check if this is an incoming share */
301
+            $incomingShares = $this->getSharedWith($share->getSharedBy(), Share::SHARE_TYPE_USER, $userMountPoint, -1, 0);
302
+            $incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), Share::SHARE_TYPE_GROUP, $userMountPoint, -1, 0));
303
+            $incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), Share::SHARE_TYPE_ROOM, $userMountPoint, -1, 0));
304
+
305
+            /** @var \OCP\Share\IShare[] $incomingShares */
306
+            if (!empty($incomingShares)) {
307
+                $permissions = 0;
308
+                foreach ($incomingShares as $incomingShare) {
309
+                    $permissions |= $incomingShare->getPermissions();
310
+                }
311
+            }
312
+        } else {
313
+            /*
314 314
 			 * Quick fix for #23536
315 315
 			 * Non moveable mount points do not have update and delete permissions
316 316
 			 * while we 'most likely' do have that on the storage.
317 317
 			 */
318
-			$permissions = $share->getNode()->getPermissions();
319
-			if (!($mount instanceof MoveableMount)) {
320
-				$permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
321
-			}
322
-		}
323
-
324
-		// Check that we do not share with more permissions than we have
325
-		if ($share->getPermissions() & ~$permissions) {
326
-			$message_t = $this->l->t('Can’t increase permissions of %s', [$share->getNode()->getPath()]);
327
-			throw new GenericShareException($message_t, $message_t, 404);
328
-		}
329
-
330
-
331
-		// Check that read permissions are always set
332
-		// Link shares are allowed to have no read permissions to allow upload to hidden folders
333
-		$noReadPermissionRequired = $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK
334
-			|| $share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL;
335
-		if (!$noReadPermissionRequired &&
336
-			($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
337
-			throw new \InvalidArgumentException('Shares need at least read permissions');
338
-		}
339
-
340
-		if ($share->getNode() instanceof \OCP\Files\File) {
341
-			if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
342
-				$message_t = $this->l->t('Files can’t be shared with delete permissions');
343
-				throw new GenericShareException($message_t);
344
-			}
345
-			if ($share->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
346
-				$message_t = $this->l->t('Files can’t be shared with create permissions');
347
-				throw new GenericShareException($message_t);
348
-			}
349
-		}
350
-	}
351
-
352
-	/**
353
-	 * Validate if the expiration date fits the system settings
354
-	 *
355
-	 * @param \OCP\Share\IShare $share The share to validate the expiration date of
356
-	 * @return \OCP\Share\IShare The modified share object
357
-	 * @throws GenericShareException
358
-	 * @throws \InvalidArgumentException
359
-	 * @throws \Exception
360
-	 */
361
-	protected function validateExpirationDate(\OCP\Share\IShare $share) {
362
-
363
-		$expirationDate = $share->getExpirationDate();
364
-
365
-		if ($expirationDate !== null) {
366
-			//Make sure the expiration date is a date
367
-			$expirationDate->setTime(0, 0, 0);
368
-
369
-			$date = new \DateTime();
370
-			$date->setTime(0, 0, 0);
371
-			if ($date >= $expirationDate) {
372
-				$message = $this->l->t('Expiration date is in the past');
373
-				throw new GenericShareException($message, $message, 404);
374
-			}
375
-		}
376
-
377
-		// If expiredate is empty set a default one if there is a default
378
-		$fullId = null;
379
-		try {
380
-			$fullId = $share->getFullId();
381
-		} catch (\UnexpectedValueException $e) {
382
-			// This is a new share
383
-		}
384
-
385
-		if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
386
-			$expirationDate = new \DateTime();
387
-			$expirationDate->setTime(0,0,0);
388
-			$expirationDate->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
389
-		}
390
-
391
-		// If we enforce the expiration date check that is does not exceed
392
-		if ($this->shareApiLinkDefaultExpireDateEnforced()) {
393
-			if ($expirationDate === null) {
394
-				throw new \InvalidArgumentException('Expiration date is enforced');
395
-			}
396
-
397
-			$date = new \DateTime();
398
-			$date->setTime(0, 0, 0);
399
-			$date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
400
-			if ($date < $expirationDate) {
401
-				$message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
402
-				throw new GenericShareException($message, $message, 404);
403
-			}
404
-		}
405
-
406
-		$accepted = true;
407
-		$message = '';
408
-		\OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
409
-			'expirationDate' => &$expirationDate,
410
-			'accepted' => &$accepted,
411
-			'message' => &$message,
412
-			'passwordSet' => $share->getPassword() !== null,
413
-		]);
414
-
415
-		if (!$accepted) {
416
-			throw new \Exception($message);
417
-		}
418
-
419
-		$share->setExpirationDate($expirationDate);
420
-
421
-		return $share;
422
-	}
423
-
424
-	/**
425
-	 * Check for pre share requirements for user shares
426
-	 *
427
-	 * @param \OCP\Share\IShare $share
428
-	 * @throws \Exception
429
-	 */
430
-	protected function userCreateChecks(\OCP\Share\IShare $share) {
431
-		// Check if we can share with group members only
432
-		if ($this->shareWithGroupMembersOnly()) {
433
-			$sharedBy = $this->userManager->get($share->getSharedBy());
434
-			$sharedWith = $this->userManager->get($share->getSharedWith());
435
-			// Verify we can share with this user
436
-			$groups = array_intersect(
437
-					$this->groupManager->getUserGroupIds($sharedBy),
438
-					$this->groupManager->getUserGroupIds($sharedWith)
439
-			);
440
-			if (empty($groups)) {
441
-				throw new \Exception('Sharing is only allowed with group members');
442
-			}
443
-		}
444
-
445
-		/*
318
+            $permissions = $share->getNode()->getPermissions();
319
+            if (!($mount instanceof MoveableMount)) {
320
+                $permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
321
+            }
322
+        }
323
+
324
+        // Check that we do not share with more permissions than we have
325
+        if ($share->getPermissions() & ~$permissions) {
326
+            $message_t = $this->l->t('Can’t increase permissions of %s', [$share->getNode()->getPath()]);
327
+            throw new GenericShareException($message_t, $message_t, 404);
328
+        }
329
+
330
+
331
+        // Check that read permissions are always set
332
+        // Link shares are allowed to have no read permissions to allow upload to hidden folders
333
+        $noReadPermissionRequired = $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK
334
+            || $share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL;
335
+        if (!$noReadPermissionRequired &&
336
+            ($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
337
+            throw new \InvalidArgumentException('Shares need at least read permissions');
338
+        }
339
+
340
+        if ($share->getNode() instanceof \OCP\Files\File) {
341
+            if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
342
+                $message_t = $this->l->t('Files can’t be shared with delete permissions');
343
+                throw new GenericShareException($message_t);
344
+            }
345
+            if ($share->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
346
+                $message_t = $this->l->t('Files can’t be shared with create permissions');
347
+                throw new GenericShareException($message_t);
348
+            }
349
+        }
350
+    }
351
+
352
+    /**
353
+     * Validate if the expiration date fits the system settings
354
+     *
355
+     * @param \OCP\Share\IShare $share The share to validate the expiration date of
356
+     * @return \OCP\Share\IShare The modified share object
357
+     * @throws GenericShareException
358
+     * @throws \InvalidArgumentException
359
+     * @throws \Exception
360
+     */
361
+    protected function validateExpirationDate(\OCP\Share\IShare $share) {
362
+
363
+        $expirationDate = $share->getExpirationDate();
364
+
365
+        if ($expirationDate !== null) {
366
+            //Make sure the expiration date is a date
367
+            $expirationDate->setTime(0, 0, 0);
368
+
369
+            $date = new \DateTime();
370
+            $date->setTime(0, 0, 0);
371
+            if ($date >= $expirationDate) {
372
+                $message = $this->l->t('Expiration date is in the past');
373
+                throw new GenericShareException($message, $message, 404);
374
+            }
375
+        }
376
+
377
+        // If expiredate is empty set a default one if there is a default
378
+        $fullId = null;
379
+        try {
380
+            $fullId = $share->getFullId();
381
+        } catch (\UnexpectedValueException $e) {
382
+            // This is a new share
383
+        }
384
+
385
+        if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
386
+            $expirationDate = new \DateTime();
387
+            $expirationDate->setTime(0,0,0);
388
+            $expirationDate->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
389
+        }
390
+
391
+        // If we enforce the expiration date check that is does not exceed
392
+        if ($this->shareApiLinkDefaultExpireDateEnforced()) {
393
+            if ($expirationDate === null) {
394
+                throw new \InvalidArgumentException('Expiration date is enforced');
395
+            }
396
+
397
+            $date = new \DateTime();
398
+            $date->setTime(0, 0, 0);
399
+            $date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
400
+            if ($date < $expirationDate) {
401
+                $message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
402
+                throw new GenericShareException($message, $message, 404);
403
+            }
404
+        }
405
+
406
+        $accepted = true;
407
+        $message = '';
408
+        \OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
409
+            'expirationDate' => &$expirationDate,
410
+            'accepted' => &$accepted,
411
+            'message' => &$message,
412
+            'passwordSet' => $share->getPassword() !== null,
413
+        ]);
414
+
415
+        if (!$accepted) {
416
+            throw new \Exception($message);
417
+        }
418
+
419
+        $share->setExpirationDate($expirationDate);
420
+
421
+        return $share;
422
+    }
423
+
424
+    /**
425
+     * Check for pre share requirements for user shares
426
+     *
427
+     * @param \OCP\Share\IShare $share
428
+     * @throws \Exception
429
+     */
430
+    protected function userCreateChecks(\OCP\Share\IShare $share) {
431
+        // Check if we can share with group members only
432
+        if ($this->shareWithGroupMembersOnly()) {
433
+            $sharedBy = $this->userManager->get($share->getSharedBy());
434
+            $sharedWith = $this->userManager->get($share->getSharedWith());
435
+            // Verify we can share with this user
436
+            $groups = array_intersect(
437
+                    $this->groupManager->getUserGroupIds($sharedBy),
438
+                    $this->groupManager->getUserGroupIds($sharedWith)
439
+            );
440
+            if (empty($groups)) {
441
+                throw new \Exception('Sharing is only allowed with group members');
442
+            }
443
+        }
444
+
445
+        /*
446 446
 		 * TODO: Could be costly, fix
447 447
 		 *
448 448
 		 * Also this is not what we want in the future.. then we want to squash identical shares.
449 449
 		 */
450
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_USER);
451
-		$existingShares = $provider->getSharesByPath($share->getNode());
452
-		foreach($existingShares as $existingShare) {
453
-			// Ignore if it is the same share
454
-			try {
455
-				if ($existingShare->getFullId() === $share->getFullId()) {
456
-					continue;
457
-				}
458
-			} catch (\UnexpectedValueException $e) {
459
-				//Shares are not identical
460
-			}
461
-
462
-			// Identical share already existst
463
-			if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
464
-				throw new \Exception('Path is already shared with this user');
465
-			}
466
-
467
-			// The share is already shared with this user via a group share
468
-			if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
469
-				$group = $this->groupManager->get($existingShare->getSharedWith());
470
-				if (!is_null($group)) {
471
-					$user = $this->userManager->get($share->getSharedWith());
472
-
473
-					if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
474
-						throw new \Exception('Path is already shared with this user');
475
-					}
476
-				}
477
-			}
478
-		}
479
-	}
480
-
481
-	/**
482
-	 * Check for pre share requirements for group shares
483
-	 *
484
-	 * @param \OCP\Share\IShare $share
485
-	 * @throws \Exception
486
-	 */
487
-	protected function groupCreateChecks(\OCP\Share\IShare $share) {
488
-		// Verify group shares are allowed
489
-		if (!$this->allowGroupSharing()) {
490
-			throw new \Exception('Group sharing is now allowed');
491
-		}
492
-
493
-		// Verify if the user can share with this group
494
-		if ($this->shareWithGroupMembersOnly()) {
495
-			$sharedBy = $this->userManager->get($share->getSharedBy());
496
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
497
-			if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
498
-				throw new \Exception('Sharing is only allowed within your own groups');
499
-			}
500
-		}
501
-
502
-		/*
450
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_USER);
451
+        $existingShares = $provider->getSharesByPath($share->getNode());
452
+        foreach($existingShares as $existingShare) {
453
+            // Ignore if it is the same share
454
+            try {
455
+                if ($existingShare->getFullId() === $share->getFullId()) {
456
+                    continue;
457
+                }
458
+            } catch (\UnexpectedValueException $e) {
459
+                //Shares are not identical
460
+            }
461
+
462
+            // Identical share already existst
463
+            if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
464
+                throw new \Exception('Path is already shared with this user');
465
+            }
466
+
467
+            // The share is already shared with this user via a group share
468
+            if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
469
+                $group = $this->groupManager->get($existingShare->getSharedWith());
470
+                if (!is_null($group)) {
471
+                    $user = $this->userManager->get($share->getSharedWith());
472
+
473
+                    if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
474
+                        throw new \Exception('Path is already shared with this user');
475
+                    }
476
+                }
477
+            }
478
+        }
479
+    }
480
+
481
+    /**
482
+     * Check for pre share requirements for group shares
483
+     *
484
+     * @param \OCP\Share\IShare $share
485
+     * @throws \Exception
486
+     */
487
+    protected function groupCreateChecks(\OCP\Share\IShare $share) {
488
+        // Verify group shares are allowed
489
+        if (!$this->allowGroupSharing()) {
490
+            throw new \Exception('Group sharing is now allowed');
491
+        }
492
+
493
+        // Verify if the user can share with this group
494
+        if ($this->shareWithGroupMembersOnly()) {
495
+            $sharedBy = $this->userManager->get($share->getSharedBy());
496
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
497
+            if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
498
+                throw new \Exception('Sharing is only allowed within your own groups');
499
+            }
500
+        }
501
+
502
+        /*
503 503
 		 * TODO: Could be costly, fix
504 504
 		 *
505 505
 		 * Also this is not what we want in the future.. then we want to squash identical shares.
506 506
 		 */
507
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
508
-		$existingShares = $provider->getSharesByPath($share->getNode());
509
-		foreach($existingShares as $existingShare) {
510
-			try {
511
-				if ($existingShare->getFullId() === $share->getFullId()) {
512
-					continue;
513
-				}
514
-			} catch (\UnexpectedValueException $e) {
515
-				//It is a new share so just continue
516
-			}
517
-
518
-			if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
519
-				throw new \Exception('Path is already shared with this group');
520
-			}
521
-		}
522
-	}
523
-
524
-	/**
525
-	 * Check for pre share requirements for link shares
526
-	 *
527
-	 * @param \OCP\Share\IShare $share
528
-	 * @throws \Exception
529
-	 */
530
-	protected function linkCreateChecks(\OCP\Share\IShare $share) {
531
-		// Are link shares allowed?
532
-		if (!$this->shareApiAllowLinks()) {
533
-			throw new \Exception('Link sharing is not allowed');
534
-		}
535
-
536
-		// Link shares by definition can't have share permissions
537
-		if ($share->getPermissions() & \OCP\Constants::PERMISSION_SHARE) {
538
-			throw new \InvalidArgumentException('Link shares can’t have reshare permissions');
539
-		}
540
-
541
-		// Check if public upload is allowed
542
-		if (!$this->shareApiLinkAllowPublicUpload() &&
543
-			($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
544
-			throw new \InvalidArgumentException('Public upload is not allowed');
545
-		}
546
-	}
547
-
548
-	/**
549
-	 * To make sure we don't get invisible link shares we set the parent
550
-	 * of a link if it is a reshare. This is a quick word around
551
-	 * until we can properly display multiple link shares in the UI
552
-	 *
553
-	 * See: https://github.com/owncloud/core/issues/22295
554
-	 *
555
-	 * FIXME: Remove once multiple link shares can be properly displayed
556
-	 *
557
-	 * @param \OCP\Share\IShare $share
558
-	 */
559
-	protected function setLinkParent(\OCP\Share\IShare $share) {
560
-
561
-		// No sense in checking if the method is not there.
562
-		if (method_exists($share, 'setParent')) {
563
-			$storage = $share->getNode()->getStorage();
564
-			if ($storage->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
565
-				/** @var \OCA\Files_Sharing\SharedStorage $storage */
566
-				$share->setParent($storage->getShareId());
567
-			}
568
-		}
569
-	}
570
-
571
-	/**
572
-	 * @param File|Folder $path
573
-	 */
574
-	protected function pathCreateChecks($path) {
575
-		// Make sure that we do not share a path that contains a shared mountpoint
576
-		if ($path instanceof \OCP\Files\Folder) {
577
-			$mounts = $this->mountManager->findIn($path->getPath());
578
-			foreach($mounts as $mount) {
579
-				if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
580
-					throw new \InvalidArgumentException('Path contains files shared with you');
581
-				}
582
-			}
583
-		}
584
-	}
585
-
586
-	/**
587
-	 * Check if the user that is sharing can actually share
588
-	 *
589
-	 * @param \OCP\Share\IShare $share
590
-	 * @throws \Exception
591
-	 */
592
-	protected function canShare(\OCP\Share\IShare $share) {
593
-		if (!$this->shareApiEnabled()) {
594
-			throw new \Exception('Sharing is disabled');
595
-		}
596
-
597
-		if ($this->sharingDisabledForUser($share->getSharedBy())) {
598
-			throw new \Exception('Sharing is disabled for you');
599
-		}
600
-	}
601
-
602
-	/**
603
-	 * Share a path
604
-	 *
605
-	 * @param \OCP\Share\IShare $share
606
-	 * @return Share The share object
607
-	 * @throws \Exception
608
-	 *
609
-	 * TODO: handle link share permissions or check them
610
-	 */
611
-	public function createShare(\OCP\Share\IShare $share) {
612
-		$this->canShare($share);
613
-
614
-		$this->generalCreateChecks($share);
615
-
616
-		// Verify if there are any issues with the path
617
-		$this->pathCreateChecks($share->getNode());
618
-
619
-		/*
507
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
508
+        $existingShares = $provider->getSharesByPath($share->getNode());
509
+        foreach($existingShares as $existingShare) {
510
+            try {
511
+                if ($existingShare->getFullId() === $share->getFullId()) {
512
+                    continue;
513
+                }
514
+            } catch (\UnexpectedValueException $e) {
515
+                //It is a new share so just continue
516
+            }
517
+
518
+            if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
519
+                throw new \Exception('Path is already shared with this group');
520
+            }
521
+        }
522
+    }
523
+
524
+    /**
525
+     * Check for pre share requirements for link shares
526
+     *
527
+     * @param \OCP\Share\IShare $share
528
+     * @throws \Exception
529
+     */
530
+    protected function linkCreateChecks(\OCP\Share\IShare $share) {
531
+        // Are link shares allowed?
532
+        if (!$this->shareApiAllowLinks()) {
533
+            throw new \Exception('Link sharing is not allowed');
534
+        }
535
+
536
+        // Link shares by definition can't have share permissions
537
+        if ($share->getPermissions() & \OCP\Constants::PERMISSION_SHARE) {
538
+            throw new \InvalidArgumentException('Link shares can’t have reshare permissions');
539
+        }
540
+
541
+        // Check if public upload is allowed
542
+        if (!$this->shareApiLinkAllowPublicUpload() &&
543
+            ($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
544
+            throw new \InvalidArgumentException('Public upload is not allowed');
545
+        }
546
+    }
547
+
548
+    /**
549
+     * To make sure we don't get invisible link shares we set the parent
550
+     * of a link if it is a reshare. This is a quick word around
551
+     * until we can properly display multiple link shares in the UI
552
+     *
553
+     * See: https://github.com/owncloud/core/issues/22295
554
+     *
555
+     * FIXME: Remove once multiple link shares can be properly displayed
556
+     *
557
+     * @param \OCP\Share\IShare $share
558
+     */
559
+    protected function setLinkParent(\OCP\Share\IShare $share) {
560
+
561
+        // No sense in checking if the method is not there.
562
+        if (method_exists($share, 'setParent')) {
563
+            $storage = $share->getNode()->getStorage();
564
+            if ($storage->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
565
+                /** @var \OCA\Files_Sharing\SharedStorage $storage */
566
+                $share->setParent($storage->getShareId());
567
+            }
568
+        }
569
+    }
570
+
571
+    /**
572
+     * @param File|Folder $path
573
+     */
574
+    protected function pathCreateChecks($path) {
575
+        // Make sure that we do not share a path that contains a shared mountpoint
576
+        if ($path instanceof \OCP\Files\Folder) {
577
+            $mounts = $this->mountManager->findIn($path->getPath());
578
+            foreach($mounts as $mount) {
579
+                if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
580
+                    throw new \InvalidArgumentException('Path contains files shared with you');
581
+                }
582
+            }
583
+        }
584
+    }
585
+
586
+    /**
587
+     * Check if the user that is sharing can actually share
588
+     *
589
+     * @param \OCP\Share\IShare $share
590
+     * @throws \Exception
591
+     */
592
+    protected function canShare(\OCP\Share\IShare $share) {
593
+        if (!$this->shareApiEnabled()) {
594
+            throw new \Exception('Sharing is disabled');
595
+        }
596
+
597
+        if ($this->sharingDisabledForUser($share->getSharedBy())) {
598
+            throw new \Exception('Sharing is disabled for you');
599
+        }
600
+    }
601
+
602
+    /**
603
+     * Share a path
604
+     *
605
+     * @param \OCP\Share\IShare $share
606
+     * @return Share The share object
607
+     * @throws \Exception
608
+     *
609
+     * TODO: handle link share permissions or check them
610
+     */
611
+    public function createShare(\OCP\Share\IShare $share) {
612
+        $this->canShare($share);
613
+
614
+        $this->generalCreateChecks($share);
615
+
616
+        // Verify if there are any issues with the path
617
+        $this->pathCreateChecks($share->getNode());
618
+
619
+        /*
620 620
 		 * On creation of a share the owner is always the owner of the path
621 621
 		 * Except for mounted federated shares.
622 622
 		 */
623
-		$storage = $share->getNode()->getStorage();
624
-		if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
625
-			$parent = $share->getNode()->getParent();
626
-			while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
627
-				$parent = $parent->getParent();
628
-			}
629
-			$share->setShareOwner($parent->getOwner()->getUID());
630
-		} else {
631
-			$share->setShareOwner($share->getNode()->getOwner()->getUID());
632
-		}
633
-
634
-		//Verify share type
635
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
636
-			$this->userCreateChecks($share);
637
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
638
-			$this->groupCreateChecks($share);
639
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
640
-			$this->linkCreateChecks($share);
641
-			$this->setLinkParent($share);
642
-
643
-			/*
623
+        $storage = $share->getNode()->getStorage();
624
+        if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
625
+            $parent = $share->getNode()->getParent();
626
+            while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
627
+                $parent = $parent->getParent();
628
+            }
629
+            $share->setShareOwner($parent->getOwner()->getUID());
630
+        } else {
631
+            $share->setShareOwner($share->getNode()->getOwner()->getUID());
632
+        }
633
+
634
+        //Verify share type
635
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
636
+            $this->userCreateChecks($share);
637
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
638
+            $this->groupCreateChecks($share);
639
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
640
+            $this->linkCreateChecks($share);
641
+            $this->setLinkParent($share);
642
+
643
+            /*
644 644
 			 * For now ignore a set token.
645 645
 			 */
646
-			$share->setToken(
647
-				$this->secureRandom->generate(
648
-					\OC\Share\Constants::TOKEN_LENGTH,
649
-					\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
650
-				)
651
-			);
652
-
653
-			//Verify the expiration date
654
-			$this->validateExpirationDate($share);
655
-
656
-			//Verify the password
657
-			$this->verifyPassword($share->getPassword());
658
-
659
-			// If a password is set. Hash it!
660
-			if ($share->getPassword() !== null) {
661
-				$share->setPassword($this->hasher->hash($share->getPassword()));
662
-			}
663
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
664
-			$share->setToken(
665
-				$this->secureRandom->generate(
666
-					\OC\Share\Constants::TOKEN_LENGTH,
667
-					\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
668
-				)
669
-			);
670
-		}
671
-
672
-		// Cannot share with the owner
673
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
674
-			$share->getSharedWith() === $share->getShareOwner()) {
675
-			throw new \InvalidArgumentException('Can’t share with the share owner');
676
-		}
677
-
678
-		// Generate the target
679
-		$target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
680
-		$target = \OC\Files\Filesystem::normalizePath($target);
681
-		$share->setTarget($target);
682
-
683
-		// Pre share event
684
-		$event = new GenericEvent($share);
685
-		$this->eventDispatcher->dispatch('OCP\Share::preShare', $event);
686
-		if ($event->isPropagationStopped() && $event->hasArgument('error')) {
687
-			throw new \Exception($event->getArgument('error'));
688
-		}
689
-
690
-		$oldShare = $share;
691
-		$provider = $this->factory->getProviderForType($share->getShareType());
692
-		$share = $provider->create($share);
693
-		//reuse the node we already have
694
-		$share->setNode($oldShare->getNode());
695
-
696
-		// Post share event
697
-		$event = new GenericEvent($share);
698
-		$this->eventDispatcher->dispatch('OCP\Share::postShare', $event);
699
-
700
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
701
-			$mailSend = $share->getMailSend();
702
-			if($mailSend === true) {
703
-				$user = $this->userManager->get($share->getSharedWith());
704
-				if ($user !== null) {
705
-					$emailAddress = $user->getEMailAddress();
706
-					if ($emailAddress !== null && $emailAddress !== '') {
707
-						$userLang = $this->config->getUserValue($share->getSharedWith(), 'core', 'lang', null);
708
-						$l = $this->l10nFactory->get('lib', $userLang);
709
-						$this->sendMailNotification(
710
-							$l,
711
-							$share->getNode()->getName(),
712
-							$this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]),
713
-							$share->getSharedBy(),
714
-							$emailAddress,
715
-							$share->getExpirationDate()
716
-						);
717
-						$this->logger->debug('Sent share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
718
-					} else {
719
-						$this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
720
-					}
721
-				} else {
722
-					$this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
723
-				}
724
-			} else {
725
-				$this->logger->debug('Share notification not sent because mailsend is false.', ['app' => 'share']);
726
-			}
727
-		}
728
-
729
-		return $share;
730
-	}
731
-
732
-	/**
733
-	 * Send mail notifications
734
-	 *
735
-	 * This method will catch and log mail transmission errors
736
-	 *
737
-	 * @param IL10N $l Language of the recipient
738
-	 * @param string $filename file/folder name
739
-	 * @param string $link link to the file/folder
740
-	 * @param string $initiator user ID of share sender
741
-	 * @param string $shareWith email address of share receiver
742
-	 * @param \DateTime|null $expiration
743
-	 */
744
-	protected function sendMailNotification(IL10N $l,
745
-											$filename,
746
-											$link,
747
-											$initiator,
748
-											$shareWith,
749
-											\DateTime $expiration = null) {
750
-		$initiatorUser = $this->userManager->get($initiator);
751
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
752
-
753
-		$message = $this->mailer->createMessage();
754
-
755
-		$emailTemplate = $this->mailer->createEMailTemplate('files_sharing.RecipientNotification', [
756
-			'filename' => $filename,
757
-			'link' => $link,
758
-			'initiator' => $initiatorDisplayName,
759
-			'expiration' => $expiration,
760
-			'shareWith' => $shareWith,
761
-		]);
762
-
763
-		$emailTemplate->setSubject($l->t('%1$s shared »%2$s« with you', array($initiatorDisplayName, $filename)));
764
-		$emailTemplate->addHeader();
765
-		$emailTemplate->addHeading($l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
766
-		$text = $l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
767
-
768
-		$emailTemplate->addBodyText(
769
-			htmlspecialchars($text . ' ' . $l->t('Click the button below to open it.')),
770
-			$text
771
-		);
772
-		$emailTemplate->addBodyButton(
773
-			$l->t('Open »%s«', [$filename]),
774
-			$link
775
-		);
776
-
777
-		$message->setTo([$shareWith]);
778
-
779
-		// The "From" contains the sharers name
780
-		$instanceName = $this->defaults->getName();
781
-		$senderName = $l->t(
782
-			'%1$s via %2$s',
783
-			[
784
-				$initiatorDisplayName,
785
-				$instanceName
786
-			]
787
-		);
788
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
789
-
790
-		// The "Reply-To" is set to the sharer if an mail address is configured
791
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
792
-		$initiatorEmail = $initiatorUser->getEMailAddress();
793
-		if($initiatorEmail !== null) {
794
-			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
795
-			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
796
-		} else {
797
-			$emailTemplate->addFooter();
798
-		}
799
-
800
-		$message->useTemplate($emailTemplate);
801
-		try {
802
-			$failedRecipients = $this->mailer->send($message);
803
-			if(!empty($failedRecipients)) {
804
-				$this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
805
-				return;
806
-			}
807
-		} catch (\Exception $e) {
808
-			$this->logger->logException($e, ['message' => 'Share notification mail could not be sent']);
809
-		}
810
-	}
811
-
812
-	/**
813
-	 * Update a share
814
-	 *
815
-	 * @param \OCP\Share\IShare $share
816
-	 * @return \OCP\Share\IShare The share object
817
-	 * @throws \InvalidArgumentException
818
-	 */
819
-	public function updateShare(\OCP\Share\IShare $share) {
820
-		$expirationDateUpdated = false;
821
-
822
-		$this->canShare($share);
823
-
824
-		try {
825
-			$originalShare = $this->getShareById($share->getFullId());
826
-		} catch (\UnexpectedValueException $e) {
827
-			throw new \InvalidArgumentException('Share does not have a full id');
828
-		}
829
-
830
-		// We can't change the share type!
831
-		if ($share->getShareType() !== $originalShare->getShareType()) {
832
-			throw new \InvalidArgumentException('Can’t change share type');
833
-		}
834
-
835
-		// We can only change the recipient on user shares
836
-		if ($share->getSharedWith() !== $originalShare->getSharedWith() &&
837
-		    $share->getShareType() !== \OCP\Share::SHARE_TYPE_USER) {
838
-			throw new \InvalidArgumentException('Can only update recipient on user shares');
839
-		}
840
-
841
-		// Cannot share with the owner
842
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
843
-			$share->getSharedWith() === $share->getShareOwner()) {
844
-			throw new \InvalidArgumentException('Can’t share with the share owner');
845
-		}
846
-
847
-		$this->generalCreateChecks($share);
848
-
849
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
850
-			$this->userCreateChecks($share);
851
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
852
-			$this->groupCreateChecks($share);
853
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
854
-			$this->linkCreateChecks($share);
855
-
856
-			$this->updateSharePasswordIfNeeded($share, $originalShare);
857
-
858
-			if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
859
-				//Verify the expiration date
860
-				$this->validateExpirationDate($share);
861
-				$expirationDateUpdated = true;
862
-			}
863
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
864
-			// The new password is not set again if it is the same as the old
865
-			// one, unless when switching from sending by Talk to sending by
866
-			// mail.
867
-			$plainTextPassword = $share->getPassword();
868
-			if (!empty($plainTextPassword) && !$this->updateSharePasswordIfNeeded($share, $originalShare) &&
869
-					!($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk())) {
870
-				$plainTextPassword = null;
871
-			}
872
-			if (empty($plainTextPassword) && !$originalShare->getSendPasswordByTalk() && $share->getSendPasswordByTalk()) {
873
-				// If the same password was already sent by mail the recipient
874
-				// would already have access to the share without having to call
875
-				// the sharer to verify her identity
876
-				throw new \InvalidArgumentException('Can’t enable sending the password by Talk without setting a new password');
877
-			}
878
-		}
879
-
880
-		$this->pathCreateChecks($share->getNode());
881
-
882
-		// Now update the share!
883
-		$provider = $this->factory->getProviderForType($share->getShareType());
884
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
885
-			$share = $provider->update($share, $plainTextPassword);
886
-		} else {
887
-			$share = $provider->update($share);
888
-		}
889
-
890
-		if ($expirationDateUpdated === true) {
891
-			\OC_Hook::emit(Share::class, 'post_set_expiration_date', [
892
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
893
-				'itemSource' => $share->getNode()->getId(),
894
-				'date' => $share->getExpirationDate(),
895
-				'uidOwner' => $share->getSharedBy(),
896
-			]);
897
-		}
898
-
899
-		if ($share->getPassword() !== $originalShare->getPassword()) {
900
-			\OC_Hook::emit(Share::class, 'post_update_password', [
901
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
902
-				'itemSource' => $share->getNode()->getId(),
903
-				'uidOwner' => $share->getSharedBy(),
904
-				'token' => $share->getToken(),
905
-				'disabled' => is_null($share->getPassword()),
906
-			]);
907
-		}
908
-
909
-		if ($share->getPermissions() !== $originalShare->getPermissions()) {
910
-			if ($this->userManager->userExists($share->getShareOwner())) {
911
-				$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
912
-			} else {
913
-				$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
914
-			}
915
-			\OC_Hook::emit(Share::class, 'post_update_permissions', array(
916
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
917
-				'itemSource' => $share->getNode()->getId(),
918
-				'shareType' => $share->getShareType(),
919
-				'shareWith' => $share->getSharedWith(),
920
-				'uidOwner' => $share->getSharedBy(),
921
-				'permissions' => $share->getPermissions(),
922
-				'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
923
-			));
924
-		}
925
-
926
-		return $share;
927
-	}
928
-
929
-	/**
930
-	 * Updates the password of the given share if it is not the same as the
931
-	 * password of the original share.
932
-	 *
933
-	 * @param \OCP\Share\IShare $share the share to update its password.
934
-	 * @param \OCP\Share\IShare $originalShare the original share to compare its
935
-	 *        password with.
936
-	 * @return boolean whether the password was updated or not.
937
-	 */
938
-	private function updateSharePasswordIfNeeded(\OCP\Share\IShare $share, \OCP\Share\IShare $originalShare) {
939
-		// Password updated.
940
-		if ($share->getPassword() !== $originalShare->getPassword()) {
941
-			//Verify the password
942
-			$this->verifyPassword($share->getPassword());
943
-
944
-			// If a password is set. Hash it!
945
-			if ($share->getPassword() !== null) {
946
-				$share->setPassword($this->hasher->hash($share->getPassword()));
947
-
948
-				return true;
949
-			}
950
-		}
951
-
952
-		return false;
953
-	}
954
-
955
-	/**
956
-	 * Delete all the children of this share
957
-	 * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
958
-	 *
959
-	 * @param \OCP\Share\IShare $share
960
-	 * @return \OCP\Share\IShare[] List of deleted shares
961
-	 */
962
-	protected function deleteChildren(\OCP\Share\IShare $share) {
963
-		$deletedShares = [];
964
-
965
-		$provider = $this->factory->getProviderForType($share->getShareType());
966
-
967
-		foreach ($provider->getChildren($share) as $child) {
968
-			$deletedChildren = $this->deleteChildren($child);
969
-			$deletedShares = array_merge($deletedShares, $deletedChildren);
970
-
971
-			$provider->delete($child);
972
-			$deletedShares[] = $child;
973
-		}
974
-
975
-		return $deletedShares;
976
-	}
977
-
978
-	/**
979
-	 * Delete a share
980
-	 *
981
-	 * @param \OCP\Share\IShare $share
982
-	 * @throws ShareNotFound
983
-	 * @throws \InvalidArgumentException
984
-	 */
985
-	public function deleteShare(\OCP\Share\IShare $share) {
986
-
987
-		try {
988
-			$share->getFullId();
989
-		} catch (\UnexpectedValueException $e) {
990
-			throw new \InvalidArgumentException('Share does not have a full id');
991
-		}
992
-
993
-		$event = new GenericEvent($share);
994
-		$this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event);
995
-
996
-		// Get all children and delete them as well
997
-		$deletedShares = $this->deleteChildren($share);
998
-
999
-		// Do the actual delete
1000
-		$provider = $this->factory->getProviderForType($share->getShareType());
1001
-		$provider->delete($share);
1002
-
1003
-		// All the deleted shares caused by this delete
1004
-		$deletedShares[] = $share;
1005
-
1006
-		// Emit post hook
1007
-		$event->setArgument('deletedShares', $deletedShares);
1008
-		$this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event);
1009
-	}
1010
-
1011
-
1012
-	/**
1013
-	 * Unshare a file as the recipient.
1014
-	 * This can be different from a regular delete for example when one of
1015
-	 * the users in a groups deletes that share. But the provider should
1016
-	 * handle this.
1017
-	 *
1018
-	 * @param \OCP\Share\IShare $share
1019
-	 * @param string $recipientId
1020
-	 */
1021
-	public function deleteFromSelf(\OCP\Share\IShare $share, $recipientId) {
1022
-		list($providerId, ) = $this->splitFullId($share->getFullId());
1023
-		$provider = $this->factory->getProvider($providerId);
1024
-
1025
-		$provider->deleteFromSelf($share, $recipientId);
1026
-		$event = new GenericEvent($share);
1027
-		$this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
1028
-	}
1029
-
1030
-	public function restoreShare(IShare $share, string $recipientId): IShare {
1031
-		list($providerId, ) = $this->splitFullId($share->getFullId());
1032
-		$provider = $this->factory->getProvider($providerId);
1033
-
1034
-		return $provider->restore($share, $recipientId);
1035
-	}
1036
-
1037
-	/**
1038
-	 * @inheritdoc
1039
-	 */
1040
-	public function moveShare(\OCP\Share\IShare $share, $recipientId) {
1041
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
1042
-			throw new \InvalidArgumentException('Can’t change target of link share');
1043
-		}
1044
-
1045
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipientId) {
1046
-			throw new \InvalidArgumentException('Invalid recipient');
1047
-		}
1048
-
1049
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
1050
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
1051
-			if (is_null($sharedWith)) {
1052
-				throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
1053
-			}
1054
-			$recipient = $this->userManager->get($recipientId);
1055
-			if (!$sharedWith->inGroup($recipient)) {
1056
-				throw new \InvalidArgumentException('Invalid recipient');
1057
-			}
1058
-		}
1059
-
1060
-		list($providerId, ) = $this->splitFullId($share->getFullId());
1061
-		$provider = $this->factory->getProvider($providerId);
1062
-
1063
-		$provider->move($share, $recipientId);
1064
-	}
1065
-
1066
-	public function getSharesInFolder($userId, Folder $node, $reshares = false) {
1067
-		$providers = $this->factory->getAllProviders();
1068
-
1069
-		return array_reduce($providers, function($shares, IShareProvider $provider) use ($userId, $node, $reshares) {
1070
-			$newShares = $provider->getSharesInFolder($userId, $node, $reshares);
1071
-			foreach ($newShares as $fid => $data) {
1072
-				if (!isset($shares[$fid])) {
1073
-					$shares[$fid] = [];
1074
-				}
1075
-
1076
-				$shares[$fid] = array_merge($shares[$fid], $data);
1077
-			}
1078
-			return $shares;
1079
-		}, []);
1080
-	}
1081
-
1082
-	/**
1083
-	 * @inheritdoc
1084
-	 */
1085
-	public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
1086
-		if ($path !== null &&
1087
-				!($path instanceof \OCP\Files\File) &&
1088
-				!($path instanceof \OCP\Files\Folder)) {
1089
-			throw new \InvalidArgumentException('invalid path');
1090
-		}
1091
-
1092
-		try {
1093
-			$provider = $this->factory->getProviderForType($shareType);
1094
-		} catch (ProviderException $e) {
1095
-			return [];
1096
-		}
1097
-
1098
-		$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1099
-
1100
-		/*
646
+            $share->setToken(
647
+                $this->secureRandom->generate(
648
+                    \OC\Share\Constants::TOKEN_LENGTH,
649
+                    \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
650
+                )
651
+            );
652
+
653
+            //Verify the expiration date
654
+            $this->validateExpirationDate($share);
655
+
656
+            //Verify the password
657
+            $this->verifyPassword($share->getPassword());
658
+
659
+            // If a password is set. Hash it!
660
+            if ($share->getPassword() !== null) {
661
+                $share->setPassword($this->hasher->hash($share->getPassword()));
662
+            }
663
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
664
+            $share->setToken(
665
+                $this->secureRandom->generate(
666
+                    \OC\Share\Constants::TOKEN_LENGTH,
667
+                    \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
668
+                )
669
+            );
670
+        }
671
+
672
+        // Cannot share with the owner
673
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
674
+            $share->getSharedWith() === $share->getShareOwner()) {
675
+            throw new \InvalidArgumentException('Can’t share with the share owner');
676
+        }
677
+
678
+        // Generate the target
679
+        $target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
680
+        $target = \OC\Files\Filesystem::normalizePath($target);
681
+        $share->setTarget($target);
682
+
683
+        // Pre share event
684
+        $event = new GenericEvent($share);
685
+        $this->eventDispatcher->dispatch('OCP\Share::preShare', $event);
686
+        if ($event->isPropagationStopped() && $event->hasArgument('error')) {
687
+            throw new \Exception($event->getArgument('error'));
688
+        }
689
+
690
+        $oldShare = $share;
691
+        $provider = $this->factory->getProviderForType($share->getShareType());
692
+        $share = $provider->create($share);
693
+        //reuse the node we already have
694
+        $share->setNode($oldShare->getNode());
695
+
696
+        // Post share event
697
+        $event = new GenericEvent($share);
698
+        $this->eventDispatcher->dispatch('OCP\Share::postShare', $event);
699
+
700
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
701
+            $mailSend = $share->getMailSend();
702
+            if($mailSend === true) {
703
+                $user = $this->userManager->get($share->getSharedWith());
704
+                if ($user !== null) {
705
+                    $emailAddress = $user->getEMailAddress();
706
+                    if ($emailAddress !== null && $emailAddress !== '') {
707
+                        $userLang = $this->config->getUserValue($share->getSharedWith(), 'core', 'lang', null);
708
+                        $l = $this->l10nFactory->get('lib', $userLang);
709
+                        $this->sendMailNotification(
710
+                            $l,
711
+                            $share->getNode()->getName(),
712
+                            $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]),
713
+                            $share->getSharedBy(),
714
+                            $emailAddress,
715
+                            $share->getExpirationDate()
716
+                        );
717
+                        $this->logger->debug('Sent share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
718
+                    } else {
719
+                        $this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
720
+                    }
721
+                } else {
722
+                    $this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
723
+                }
724
+            } else {
725
+                $this->logger->debug('Share notification not sent because mailsend is false.', ['app' => 'share']);
726
+            }
727
+        }
728
+
729
+        return $share;
730
+    }
731
+
732
+    /**
733
+     * Send mail notifications
734
+     *
735
+     * This method will catch and log mail transmission errors
736
+     *
737
+     * @param IL10N $l Language of the recipient
738
+     * @param string $filename file/folder name
739
+     * @param string $link link to the file/folder
740
+     * @param string $initiator user ID of share sender
741
+     * @param string $shareWith email address of share receiver
742
+     * @param \DateTime|null $expiration
743
+     */
744
+    protected function sendMailNotification(IL10N $l,
745
+                                            $filename,
746
+                                            $link,
747
+                                            $initiator,
748
+                                            $shareWith,
749
+                                            \DateTime $expiration = null) {
750
+        $initiatorUser = $this->userManager->get($initiator);
751
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
752
+
753
+        $message = $this->mailer->createMessage();
754
+
755
+        $emailTemplate = $this->mailer->createEMailTemplate('files_sharing.RecipientNotification', [
756
+            'filename' => $filename,
757
+            'link' => $link,
758
+            'initiator' => $initiatorDisplayName,
759
+            'expiration' => $expiration,
760
+            'shareWith' => $shareWith,
761
+        ]);
762
+
763
+        $emailTemplate->setSubject($l->t('%1$s shared »%2$s« with you', array($initiatorDisplayName, $filename)));
764
+        $emailTemplate->addHeader();
765
+        $emailTemplate->addHeading($l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
766
+        $text = $l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
767
+
768
+        $emailTemplate->addBodyText(
769
+            htmlspecialchars($text . ' ' . $l->t('Click the button below to open it.')),
770
+            $text
771
+        );
772
+        $emailTemplate->addBodyButton(
773
+            $l->t('Open »%s«', [$filename]),
774
+            $link
775
+        );
776
+
777
+        $message->setTo([$shareWith]);
778
+
779
+        // The "From" contains the sharers name
780
+        $instanceName = $this->defaults->getName();
781
+        $senderName = $l->t(
782
+            '%1$s via %2$s',
783
+            [
784
+                $initiatorDisplayName,
785
+                $instanceName
786
+            ]
787
+        );
788
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
789
+
790
+        // The "Reply-To" is set to the sharer if an mail address is configured
791
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
792
+        $initiatorEmail = $initiatorUser->getEMailAddress();
793
+        if($initiatorEmail !== null) {
794
+            $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
795
+            $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
796
+        } else {
797
+            $emailTemplate->addFooter();
798
+        }
799
+
800
+        $message->useTemplate($emailTemplate);
801
+        try {
802
+            $failedRecipients = $this->mailer->send($message);
803
+            if(!empty($failedRecipients)) {
804
+                $this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
805
+                return;
806
+            }
807
+        } catch (\Exception $e) {
808
+            $this->logger->logException($e, ['message' => 'Share notification mail could not be sent']);
809
+        }
810
+    }
811
+
812
+    /**
813
+     * Update a share
814
+     *
815
+     * @param \OCP\Share\IShare $share
816
+     * @return \OCP\Share\IShare The share object
817
+     * @throws \InvalidArgumentException
818
+     */
819
+    public function updateShare(\OCP\Share\IShare $share) {
820
+        $expirationDateUpdated = false;
821
+
822
+        $this->canShare($share);
823
+
824
+        try {
825
+            $originalShare = $this->getShareById($share->getFullId());
826
+        } catch (\UnexpectedValueException $e) {
827
+            throw new \InvalidArgumentException('Share does not have a full id');
828
+        }
829
+
830
+        // We can't change the share type!
831
+        if ($share->getShareType() !== $originalShare->getShareType()) {
832
+            throw new \InvalidArgumentException('Can’t change share type');
833
+        }
834
+
835
+        // We can only change the recipient on user shares
836
+        if ($share->getSharedWith() !== $originalShare->getSharedWith() &&
837
+            $share->getShareType() !== \OCP\Share::SHARE_TYPE_USER) {
838
+            throw new \InvalidArgumentException('Can only update recipient on user shares');
839
+        }
840
+
841
+        // Cannot share with the owner
842
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
843
+            $share->getSharedWith() === $share->getShareOwner()) {
844
+            throw new \InvalidArgumentException('Can’t share with the share owner');
845
+        }
846
+
847
+        $this->generalCreateChecks($share);
848
+
849
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
850
+            $this->userCreateChecks($share);
851
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
852
+            $this->groupCreateChecks($share);
853
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
854
+            $this->linkCreateChecks($share);
855
+
856
+            $this->updateSharePasswordIfNeeded($share, $originalShare);
857
+
858
+            if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
859
+                //Verify the expiration date
860
+                $this->validateExpirationDate($share);
861
+                $expirationDateUpdated = true;
862
+            }
863
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
864
+            // The new password is not set again if it is the same as the old
865
+            // one, unless when switching from sending by Talk to sending by
866
+            // mail.
867
+            $plainTextPassword = $share->getPassword();
868
+            if (!empty($plainTextPassword) && !$this->updateSharePasswordIfNeeded($share, $originalShare) &&
869
+                    !($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk())) {
870
+                $plainTextPassword = null;
871
+            }
872
+            if (empty($plainTextPassword) && !$originalShare->getSendPasswordByTalk() && $share->getSendPasswordByTalk()) {
873
+                // If the same password was already sent by mail the recipient
874
+                // would already have access to the share without having to call
875
+                // the sharer to verify her identity
876
+                throw new \InvalidArgumentException('Can’t enable sending the password by Talk without setting a new password');
877
+            }
878
+        }
879
+
880
+        $this->pathCreateChecks($share->getNode());
881
+
882
+        // Now update the share!
883
+        $provider = $this->factory->getProviderForType($share->getShareType());
884
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
885
+            $share = $provider->update($share, $plainTextPassword);
886
+        } else {
887
+            $share = $provider->update($share);
888
+        }
889
+
890
+        if ($expirationDateUpdated === true) {
891
+            \OC_Hook::emit(Share::class, 'post_set_expiration_date', [
892
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
893
+                'itemSource' => $share->getNode()->getId(),
894
+                'date' => $share->getExpirationDate(),
895
+                'uidOwner' => $share->getSharedBy(),
896
+            ]);
897
+        }
898
+
899
+        if ($share->getPassword() !== $originalShare->getPassword()) {
900
+            \OC_Hook::emit(Share::class, 'post_update_password', [
901
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
902
+                'itemSource' => $share->getNode()->getId(),
903
+                'uidOwner' => $share->getSharedBy(),
904
+                'token' => $share->getToken(),
905
+                'disabled' => is_null($share->getPassword()),
906
+            ]);
907
+        }
908
+
909
+        if ($share->getPermissions() !== $originalShare->getPermissions()) {
910
+            if ($this->userManager->userExists($share->getShareOwner())) {
911
+                $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
912
+            } else {
913
+                $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
914
+            }
915
+            \OC_Hook::emit(Share::class, 'post_update_permissions', array(
916
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
917
+                'itemSource' => $share->getNode()->getId(),
918
+                'shareType' => $share->getShareType(),
919
+                'shareWith' => $share->getSharedWith(),
920
+                'uidOwner' => $share->getSharedBy(),
921
+                'permissions' => $share->getPermissions(),
922
+                'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
923
+            ));
924
+        }
925
+
926
+        return $share;
927
+    }
928
+
929
+    /**
930
+     * Updates the password of the given share if it is not the same as the
931
+     * password of the original share.
932
+     *
933
+     * @param \OCP\Share\IShare $share the share to update its password.
934
+     * @param \OCP\Share\IShare $originalShare the original share to compare its
935
+     *        password with.
936
+     * @return boolean whether the password was updated or not.
937
+     */
938
+    private function updateSharePasswordIfNeeded(\OCP\Share\IShare $share, \OCP\Share\IShare $originalShare) {
939
+        // Password updated.
940
+        if ($share->getPassword() !== $originalShare->getPassword()) {
941
+            //Verify the password
942
+            $this->verifyPassword($share->getPassword());
943
+
944
+            // If a password is set. Hash it!
945
+            if ($share->getPassword() !== null) {
946
+                $share->setPassword($this->hasher->hash($share->getPassword()));
947
+
948
+                return true;
949
+            }
950
+        }
951
+
952
+        return false;
953
+    }
954
+
955
+    /**
956
+     * Delete all the children of this share
957
+     * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
958
+     *
959
+     * @param \OCP\Share\IShare $share
960
+     * @return \OCP\Share\IShare[] List of deleted shares
961
+     */
962
+    protected function deleteChildren(\OCP\Share\IShare $share) {
963
+        $deletedShares = [];
964
+
965
+        $provider = $this->factory->getProviderForType($share->getShareType());
966
+
967
+        foreach ($provider->getChildren($share) as $child) {
968
+            $deletedChildren = $this->deleteChildren($child);
969
+            $deletedShares = array_merge($deletedShares, $deletedChildren);
970
+
971
+            $provider->delete($child);
972
+            $deletedShares[] = $child;
973
+        }
974
+
975
+        return $deletedShares;
976
+    }
977
+
978
+    /**
979
+     * Delete a share
980
+     *
981
+     * @param \OCP\Share\IShare $share
982
+     * @throws ShareNotFound
983
+     * @throws \InvalidArgumentException
984
+     */
985
+    public function deleteShare(\OCP\Share\IShare $share) {
986
+
987
+        try {
988
+            $share->getFullId();
989
+        } catch (\UnexpectedValueException $e) {
990
+            throw new \InvalidArgumentException('Share does not have a full id');
991
+        }
992
+
993
+        $event = new GenericEvent($share);
994
+        $this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event);
995
+
996
+        // Get all children and delete them as well
997
+        $deletedShares = $this->deleteChildren($share);
998
+
999
+        // Do the actual delete
1000
+        $provider = $this->factory->getProviderForType($share->getShareType());
1001
+        $provider->delete($share);
1002
+
1003
+        // All the deleted shares caused by this delete
1004
+        $deletedShares[] = $share;
1005
+
1006
+        // Emit post hook
1007
+        $event->setArgument('deletedShares', $deletedShares);
1008
+        $this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event);
1009
+    }
1010
+
1011
+
1012
+    /**
1013
+     * Unshare a file as the recipient.
1014
+     * This can be different from a regular delete for example when one of
1015
+     * the users in a groups deletes that share. But the provider should
1016
+     * handle this.
1017
+     *
1018
+     * @param \OCP\Share\IShare $share
1019
+     * @param string $recipientId
1020
+     */
1021
+    public function deleteFromSelf(\OCP\Share\IShare $share, $recipientId) {
1022
+        list($providerId, ) = $this->splitFullId($share->getFullId());
1023
+        $provider = $this->factory->getProvider($providerId);
1024
+
1025
+        $provider->deleteFromSelf($share, $recipientId);
1026
+        $event = new GenericEvent($share);
1027
+        $this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
1028
+    }
1029
+
1030
+    public function restoreShare(IShare $share, string $recipientId): IShare {
1031
+        list($providerId, ) = $this->splitFullId($share->getFullId());
1032
+        $provider = $this->factory->getProvider($providerId);
1033
+
1034
+        return $provider->restore($share, $recipientId);
1035
+    }
1036
+
1037
+    /**
1038
+     * @inheritdoc
1039
+     */
1040
+    public function moveShare(\OCP\Share\IShare $share, $recipientId) {
1041
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
1042
+            throw new \InvalidArgumentException('Can’t change target of link share');
1043
+        }
1044
+
1045
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipientId) {
1046
+            throw new \InvalidArgumentException('Invalid recipient');
1047
+        }
1048
+
1049
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
1050
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
1051
+            if (is_null($sharedWith)) {
1052
+                throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
1053
+            }
1054
+            $recipient = $this->userManager->get($recipientId);
1055
+            if (!$sharedWith->inGroup($recipient)) {
1056
+                throw new \InvalidArgumentException('Invalid recipient');
1057
+            }
1058
+        }
1059
+
1060
+        list($providerId, ) = $this->splitFullId($share->getFullId());
1061
+        $provider = $this->factory->getProvider($providerId);
1062
+
1063
+        $provider->move($share, $recipientId);
1064
+    }
1065
+
1066
+    public function getSharesInFolder($userId, Folder $node, $reshares = false) {
1067
+        $providers = $this->factory->getAllProviders();
1068
+
1069
+        return array_reduce($providers, function($shares, IShareProvider $provider) use ($userId, $node, $reshares) {
1070
+            $newShares = $provider->getSharesInFolder($userId, $node, $reshares);
1071
+            foreach ($newShares as $fid => $data) {
1072
+                if (!isset($shares[$fid])) {
1073
+                    $shares[$fid] = [];
1074
+                }
1075
+
1076
+                $shares[$fid] = array_merge($shares[$fid], $data);
1077
+            }
1078
+            return $shares;
1079
+        }, []);
1080
+    }
1081
+
1082
+    /**
1083
+     * @inheritdoc
1084
+     */
1085
+    public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
1086
+        if ($path !== null &&
1087
+                !($path instanceof \OCP\Files\File) &&
1088
+                !($path instanceof \OCP\Files\Folder)) {
1089
+            throw new \InvalidArgumentException('invalid path');
1090
+        }
1091
+
1092
+        try {
1093
+            $provider = $this->factory->getProviderForType($shareType);
1094
+        } catch (ProviderException $e) {
1095
+            return [];
1096
+        }
1097
+
1098
+        $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1099
+
1100
+        /*
1101 1101
 		 * Work around so we don't return expired shares but still follow
1102 1102
 		 * proper pagination.
1103 1103
 		 */
1104 1104
 
1105
-		$shares2 = [];
1106
-
1107
-		while(true) {
1108
-			$added = 0;
1109
-			foreach ($shares as $share) {
1110
-
1111
-				try {
1112
-					$this->checkExpireDate($share);
1113
-				} catch (ShareNotFound $e) {
1114
-					//Ignore since this basically means the share is deleted
1115
-					continue;
1116
-				}
1117
-
1118
-				$added++;
1119
-				$shares2[] = $share;
1120
-
1121
-				if (count($shares2) === $limit) {
1122
-					break;
1123
-				}
1124
-			}
1125
-
1126
-			// If we did not fetch more shares than the limit then there are no more shares
1127
-			if (count($shares) < $limit) {
1128
-				break;
1129
-			}
1130
-
1131
-			if (count($shares2) === $limit) {
1132
-				break;
1133
-			}
1134
-
1135
-			// If there was no limit on the select we are done
1136
-			if ($limit === -1) {
1137
-				break;
1138
-			}
1139
-
1140
-			$offset += $added;
1141
-
1142
-			// Fetch again $limit shares
1143
-			$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1144
-
1145
-			// No more shares means we are done
1146
-			if (empty($shares)) {
1147
-				break;
1148
-			}
1149
-		}
1150
-
1151
-		$shares = $shares2;
1152
-
1153
-		return $shares;
1154
-	}
1155
-
1156
-	/**
1157
-	 * @inheritdoc
1158
-	 */
1159
-	public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1160
-		try {
1161
-			$provider = $this->factory->getProviderForType($shareType);
1162
-		} catch (ProviderException $e) {
1163
-			return [];
1164
-		}
1165
-
1166
-		$shares = $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
1167
-
1168
-		// remove all shares which are already expired
1169
-		foreach ($shares as $key => $share) {
1170
-			try {
1171
-				$this->checkExpireDate($share);
1172
-			} catch (ShareNotFound $e) {
1173
-				unset($shares[$key]);
1174
-			}
1175
-		}
1176
-
1177
-		return $shares;
1178
-	}
1179
-
1180
-	/**
1181
-	 * @inheritdoc
1182
-	 */
1183
-	public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1184
-		$shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);
1185
-
1186
-		// Only get deleted shares
1187
-		$shares = array_filter($shares, function(IShare $share) {
1188
-			return $share->getPermissions() === 0;
1189
-		});
1190
-
1191
-		// Only get shares where the owner still exists
1192
-		$shares = array_filter($shares, function (IShare $share) {
1193
-			return $this->userManager->userExists($share->getShareOwner());
1194
-		});
1195
-
1196
-		return $shares;
1197
-	}
1198
-
1199
-	/**
1200
-	 * @inheritdoc
1201
-	 */
1202
-	public function getShareById($id, $recipient = null) {
1203
-		if ($id === null) {
1204
-			throw new ShareNotFound();
1205
-		}
1206
-
1207
-		list($providerId, $id) = $this->splitFullId($id);
1208
-
1209
-		try {
1210
-			$provider = $this->factory->getProvider($providerId);
1211
-		} catch (ProviderException $e) {
1212
-			throw new ShareNotFound();
1213
-		}
1214
-
1215
-		$share = $provider->getShareById($id, $recipient);
1216
-
1217
-		$this->checkExpireDate($share);
1218
-
1219
-		return $share;
1220
-	}
1221
-
1222
-	/**
1223
-	 * Get all the shares for a given path
1224
-	 *
1225
-	 * @param \OCP\Files\Node $path
1226
-	 * @param int $page
1227
-	 * @param int $perPage
1228
-	 *
1229
-	 * @return Share[]
1230
-	 */
1231
-	public function getSharesByPath(\OCP\Files\Node $path, $page=0, $perPage=50) {
1232
-		return [];
1233
-	}
1234
-
1235
-	/**
1236
-	 * Get the share by token possible with password
1237
-	 *
1238
-	 * @param string $token
1239
-	 * @return Share
1240
-	 *
1241
-	 * @throws ShareNotFound
1242
-	 */
1243
-	public function getShareByToken($token) {
1244
-		// tokens can't be valid local user names
1245
-		if ($this->userManager->userExists($token)) {
1246
-			throw new ShareNotFound();
1247
-		}
1248
-		$share = null;
1249
-		try {
1250
-			if($this->shareApiAllowLinks()) {
1251
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK);
1252
-				$share = $provider->getShareByToken($token);
1253
-			}
1254
-		} catch (ProviderException $e) {
1255
-		} catch (ShareNotFound $e) {
1256
-		}
1257
-
1258
-
1259
-		// If it is not a link share try to fetch a federated share by token
1260
-		if ($share === null) {
1261
-			try {
1262
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE);
1263
-				$share = $provider->getShareByToken($token);
1264
-			} catch (ProviderException $e) {
1265
-			} catch (ShareNotFound $e) {
1266
-			}
1267
-		}
1268
-
1269
-		// If it is not a link share try to fetch a mail share by token
1270
-		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
1271
-			try {
1272
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_EMAIL);
1273
-				$share = $provider->getShareByToken($token);
1274
-			} catch (ProviderException $e) {
1275
-			} catch (ShareNotFound $e) {
1276
-			}
1277
-		}
1278
-
1279
-		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) {
1280
-			try {
1281
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_CIRCLE);
1282
-				$share = $provider->getShareByToken($token);
1283
-			} catch (ProviderException $e) {
1284
-			} catch (ShareNotFound $e) {
1285
-			}
1286
-		}
1287
-
1288
-		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_ROOM)) {
1289
-			try {
1290
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_ROOM);
1291
-				$share = $provider->getShareByToken($token);
1292
-			} catch (ProviderException $e) {
1293
-			} catch (ShareNotFound $e) {
1294
-			}
1295
-		}
1296
-
1297
-		if ($share === null) {
1298
-			throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1299
-		}
1300
-
1301
-		$this->checkExpireDate($share);
1302
-
1303
-		/*
1105
+        $shares2 = [];
1106
+
1107
+        while(true) {
1108
+            $added = 0;
1109
+            foreach ($shares as $share) {
1110
+
1111
+                try {
1112
+                    $this->checkExpireDate($share);
1113
+                } catch (ShareNotFound $e) {
1114
+                    //Ignore since this basically means the share is deleted
1115
+                    continue;
1116
+                }
1117
+
1118
+                $added++;
1119
+                $shares2[] = $share;
1120
+
1121
+                if (count($shares2) === $limit) {
1122
+                    break;
1123
+                }
1124
+            }
1125
+
1126
+            // If we did not fetch more shares than the limit then there are no more shares
1127
+            if (count($shares) < $limit) {
1128
+                break;
1129
+            }
1130
+
1131
+            if (count($shares2) === $limit) {
1132
+                break;
1133
+            }
1134
+
1135
+            // If there was no limit on the select we are done
1136
+            if ($limit === -1) {
1137
+                break;
1138
+            }
1139
+
1140
+            $offset += $added;
1141
+
1142
+            // Fetch again $limit shares
1143
+            $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1144
+
1145
+            // No more shares means we are done
1146
+            if (empty($shares)) {
1147
+                break;
1148
+            }
1149
+        }
1150
+
1151
+        $shares = $shares2;
1152
+
1153
+        return $shares;
1154
+    }
1155
+
1156
+    /**
1157
+     * @inheritdoc
1158
+     */
1159
+    public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1160
+        try {
1161
+            $provider = $this->factory->getProviderForType($shareType);
1162
+        } catch (ProviderException $e) {
1163
+            return [];
1164
+        }
1165
+
1166
+        $shares = $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
1167
+
1168
+        // remove all shares which are already expired
1169
+        foreach ($shares as $key => $share) {
1170
+            try {
1171
+                $this->checkExpireDate($share);
1172
+            } catch (ShareNotFound $e) {
1173
+                unset($shares[$key]);
1174
+            }
1175
+        }
1176
+
1177
+        return $shares;
1178
+    }
1179
+
1180
+    /**
1181
+     * @inheritdoc
1182
+     */
1183
+    public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1184
+        $shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);
1185
+
1186
+        // Only get deleted shares
1187
+        $shares = array_filter($shares, function(IShare $share) {
1188
+            return $share->getPermissions() === 0;
1189
+        });
1190
+
1191
+        // Only get shares where the owner still exists
1192
+        $shares = array_filter($shares, function (IShare $share) {
1193
+            return $this->userManager->userExists($share->getShareOwner());
1194
+        });
1195
+
1196
+        return $shares;
1197
+    }
1198
+
1199
+    /**
1200
+     * @inheritdoc
1201
+     */
1202
+    public function getShareById($id, $recipient = null) {
1203
+        if ($id === null) {
1204
+            throw new ShareNotFound();
1205
+        }
1206
+
1207
+        list($providerId, $id) = $this->splitFullId($id);
1208
+
1209
+        try {
1210
+            $provider = $this->factory->getProvider($providerId);
1211
+        } catch (ProviderException $e) {
1212
+            throw new ShareNotFound();
1213
+        }
1214
+
1215
+        $share = $provider->getShareById($id, $recipient);
1216
+
1217
+        $this->checkExpireDate($share);
1218
+
1219
+        return $share;
1220
+    }
1221
+
1222
+    /**
1223
+     * Get all the shares for a given path
1224
+     *
1225
+     * @param \OCP\Files\Node $path
1226
+     * @param int $page
1227
+     * @param int $perPage
1228
+     *
1229
+     * @return Share[]
1230
+     */
1231
+    public function getSharesByPath(\OCP\Files\Node $path, $page=0, $perPage=50) {
1232
+        return [];
1233
+    }
1234
+
1235
+    /**
1236
+     * Get the share by token possible with password
1237
+     *
1238
+     * @param string $token
1239
+     * @return Share
1240
+     *
1241
+     * @throws ShareNotFound
1242
+     */
1243
+    public function getShareByToken($token) {
1244
+        // tokens can't be valid local user names
1245
+        if ($this->userManager->userExists($token)) {
1246
+            throw new ShareNotFound();
1247
+        }
1248
+        $share = null;
1249
+        try {
1250
+            if($this->shareApiAllowLinks()) {
1251
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK);
1252
+                $share = $provider->getShareByToken($token);
1253
+            }
1254
+        } catch (ProviderException $e) {
1255
+        } catch (ShareNotFound $e) {
1256
+        }
1257
+
1258
+
1259
+        // If it is not a link share try to fetch a federated share by token
1260
+        if ($share === null) {
1261
+            try {
1262
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE);
1263
+                $share = $provider->getShareByToken($token);
1264
+            } catch (ProviderException $e) {
1265
+            } catch (ShareNotFound $e) {
1266
+            }
1267
+        }
1268
+
1269
+        // If it is not a link share try to fetch a mail share by token
1270
+        if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
1271
+            try {
1272
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_EMAIL);
1273
+                $share = $provider->getShareByToken($token);
1274
+            } catch (ProviderException $e) {
1275
+            } catch (ShareNotFound $e) {
1276
+            }
1277
+        }
1278
+
1279
+        if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) {
1280
+            try {
1281
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_CIRCLE);
1282
+                $share = $provider->getShareByToken($token);
1283
+            } catch (ProviderException $e) {
1284
+            } catch (ShareNotFound $e) {
1285
+            }
1286
+        }
1287
+
1288
+        if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_ROOM)) {
1289
+            try {
1290
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_ROOM);
1291
+                $share = $provider->getShareByToken($token);
1292
+            } catch (ProviderException $e) {
1293
+            } catch (ShareNotFound $e) {
1294
+            }
1295
+        }
1296
+
1297
+        if ($share === null) {
1298
+            throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1299
+        }
1300
+
1301
+        $this->checkExpireDate($share);
1302
+
1303
+        /*
1304 1304
 		 * Reduce the permissions for link shares if public upload is not enabled
1305 1305
 		 */
1306
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
1307
-			!$this->shareApiLinkAllowPublicUpload()) {
1308
-			$share->setPermissions($share->getPermissions() & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE));
1309
-		}
1310
-
1311
-		return $share;
1312
-	}
1313
-
1314
-	protected function checkExpireDate($share) {
1315
-		if ($share->getExpirationDate() !== null &&
1316
-			$share->getExpirationDate() <= new \DateTime()) {
1317
-			$this->deleteShare($share);
1318
-			throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1319
-		}
1320
-
1321
-	}
1322
-
1323
-	/**
1324
-	 * Verify the password of a public share
1325
-	 *
1326
-	 * @param \OCP\Share\IShare $share
1327
-	 * @param string $password
1328
-	 * @return bool
1329
-	 */
1330
-	public function checkPassword(\OCP\Share\IShare $share, $password) {
1331
-		$passwordProtected = $share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK
1332
-			|| $share->getShareType() !== \OCP\Share::SHARE_TYPE_EMAIL;
1333
-		if (!$passwordProtected) {
1334
-			//TODO maybe exception?
1335
-			return false;
1336
-		}
1337
-
1338
-		if ($password === null || $share->getPassword() === null) {
1339
-			return false;
1340
-		}
1341
-
1342
-		$newHash = '';
1343
-		if (!$this->hasher->verify($password, $share->getPassword(), $newHash)) {
1344
-			return false;
1345
-		}
1346
-
1347
-		if (!empty($newHash)) {
1348
-			$share->setPassword($newHash);
1349
-			$provider = $this->factory->getProviderForType($share->getShareType());
1350
-			$provider->update($share);
1351
-		}
1352
-
1353
-		return true;
1354
-	}
1355
-
1356
-	/**
1357
-	 * @inheritdoc
1358
-	 */
1359
-	public function userDeleted($uid) {
1360
-		$types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];
1361
-
1362
-		foreach ($types as $type) {
1363
-			try {
1364
-				$provider = $this->factory->getProviderForType($type);
1365
-			} catch (ProviderException $e) {
1366
-				continue;
1367
-			}
1368
-			$provider->userDeleted($uid, $type);
1369
-		}
1370
-	}
1371
-
1372
-	/**
1373
-	 * @inheritdoc
1374
-	 */
1375
-	public function groupDeleted($gid) {
1376
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1377
-		$provider->groupDeleted($gid);
1378
-	}
1379
-
1380
-	/**
1381
-	 * @inheritdoc
1382
-	 */
1383
-	public function userDeletedFromGroup($uid, $gid) {
1384
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1385
-		$provider->userDeletedFromGroup($uid, $gid);
1386
-	}
1387
-
1388
-	/**
1389
-	 * Get access list to a path. This means
1390
-	 * all the users that can access a given path.
1391
-	 *
1392
-	 * Consider:
1393
-	 * -root
1394
-	 * |-folder1 (23)
1395
-	 *  |-folder2 (32)
1396
-	 *   |-fileA (42)
1397
-	 *
1398
-	 * fileA is shared with user1 and user1@server1
1399
-	 * folder2 is shared with group2 (user4 is a member of group2)
1400
-	 * folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
1401
-	 *
1402
-	 * Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
1403
-	 * [
1404
-	 *  users  => [
1405
-	 *      'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
1406
-	 *      'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
1407
-	 *      'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
1408
-	 *  ],
1409
-	 *  remote => [
1410
-	 *      'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
1411
-	 *      'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
1412
-	 *  ],
1413
-	 *  public => bool
1414
-	 *  mail => bool
1415
-	 * ]
1416
-	 *
1417
-	 * The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
1418
-	 * [
1419
-	 *  users  => ['user1', 'user2', 'user4'],
1420
-	 *  remote => bool,
1421
-	 *  public => bool
1422
-	 *  mail => bool
1423
-	 * ]
1424
-	 *
1425
-	 * This is required for encryption/activity
1426
-	 *
1427
-	 * @param \OCP\Files\Node $path
1428
-	 * @param bool $recursive Should we check all parent folders as well
1429
-	 * @param bool $currentAccess Ensure the recipient has access to the file (e.g. did not unshare it)
1430
-	 * @return array
1431
-	 */
1432
-	public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
1433
-		$owner = $path->getOwner();
1434
-
1435
-		if ($owner === null) {
1436
-			return [];
1437
-		}
1438
-
1439
-		$owner = $owner->getUID();
1440
-
1441
-		if ($currentAccess) {
1442
-			$al = ['users' => [], 'remote' => [], 'public' => false];
1443
-		} else {
1444
-			$al = ['users' => [], 'remote' => false, 'public' => false];
1445
-		}
1446
-		if (!$this->userManager->userExists($owner)) {
1447
-			return $al;
1448
-		}
1449
-
1450
-		//Get node for the owner and correct the owner in case of external storages
1451
-		$userFolder = $this->rootFolder->getUserFolder($owner);
1452
-		if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) {
1453
-			$nodes = $userFolder->getById($path->getId());
1454
-			$path = array_shift($nodes);
1455
-			if ($path->getOwner() === null) {
1456
-				return [];
1457
-			}
1458
-			$owner = $path->getOwner()->getUID();
1459
-		}
1460
-
1461
-		$providers = $this->factory->getAllProviders();
1462
-
1463
-		/** @var Node[] $nodes */
1464
-		$nodes = [];
1465
-
1466
-
1467
-		if ($currentAccess) {
1468
-			$ownerPath = $path->getPath();
1469
-			$ownerPath = explode('/', $ownerPath, 4);
1470
-			if (count($ownerPath) < 4) {
1471
-				$ownerPath = '';
1472
-			} else {
1473
-				$ownerPath = $ownerPath[3];
1474
-			}
1475
-			$al['users'][$owner] = [
1476
-				'node_id' => $path->getId(),
1477
-				'node_path' => '/' . $ownerPath,
1478
-			];
1479
-		} else {
1480
-			$al['users'][] = $owner;
1481
-		}
1482
-
1483
-		// Collect all the shares
1484
-		while ($path->getPath() !== $userFolder->getPath()) {
1485
-			$nodes[] = $path;
1486
-			if (!$recursive) {
1487
-				break;
1488
-			}
1489
-			$path = $path->getParent();
1490
-		}
1491
-
1492
-		foreach ($providers as $provider) {
1493
-			$tmp = $provider->getAccessList($nodes, $currentAccess);
1494
-
1495
-			foreach ($tmp as $k => $v) {
1496
-				if (isset($al[$k])) {
1497
-					if (is_array($al[$k])) {
1498
-						if ($currentAccess) {
1499
-							$al[$k] += $v;
1500
-						} else {
1501
-							$al[$k] = array_merge($al[$k], $v);
1502
-							$al[$k] = array_unique($al[$k]);
1503
-							$al[$k] = array_values($al[$k]);
1504
-						}
1505
-					} else {
1506
-						$al[$k] = $al[$k] || $v;
1507
-					}
1508
-				} else {
1509
-					$al[$k] = $v;
1510
-				}
1511
-			}
1512
-		}
1513
-
1514
-		return $al;
1515
-	}
1516
-
1517
-	/**
1518
-	 * Create a new share
1519
-	 * @return \OCP\Share\IShare
1520
-	 */
1521
-	public function newShare() {
1522
-		return new \OC\Share20\Share($this->rootFolder, $this->userManager);
1523
-	}
1524
-
1525
-	/**
1526
-	 * Is the share API enabled
1527
-	 *
1528
-	 * @return bool
1529
-	 */
1530
-	public function shareApiEnabled() {
1531
-		return $this->config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes';
1532
-	}
1533
-
1534
-	/**
1535
-	 * Is public link sharing enabled
1536
-	 *
1537
-	 * @return bool
1538
-	 */
1539
-	public function shareApiAllowLinks() {
1540
-		return $this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes';
1541
-	}
1542
-
1543
-	/**
1544
-	 * Is password on public link requires
1545
-	 *
1546
-	 * @return bool
1547
-	 */
1548
-	public function shareApiLinkEnforcePassword() {
1549
-		return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes';
1550
-	}
1551
-
1552
-	/**
1553
-	 * Is default expire date enabled
1554
-	 *
1555
-	 * @return bool
1556
-	 */
1557
-	public function shareApiLinkDefaultExpireDate() {
1558
-		return $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
1559
-	}
1560
-
1561
-	/**
1562
-	 * Is default expire date enforced
1563
-	 *`
1564
-	 * @return bool
1565
-	 */
1566
-	public function shareApiLinkDefaultExpireDateEnforced() {
1567
-		return $this->shareApiLinkDefaultExpireDate() &&
1568
-			$this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
1569
-	}
1570
-
1571
-	/**
1572
-	 * Number of default expire days
1573
-	 *shareApiLinkAllowPublicUpload
1574
-	 * @return int
1575
-	 */
1576
-	public function shareApiLinkDefaultExpireDays() {
1577
-		return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1578
-	}
1579
-
1580
-	/**
1581
-	 * Allow public upload on link shares
1582
-	 *
1583
-	 * @return bool
1584
-	 */
1585
-	public function shareApiLinkAllowPublicUpload() {
1586
-		return $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
1587
-	}
1588
-
1589
-	/**
1590
-	 * check if user can only share with group members
1591
-	 * @return bool
1592
-	 */
1593
-	public function shareWithGroupMembersOnly() {
1594
-		return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
1595
-	}
1596
-
1597
-	/**
1598
-	 * Check if users can share with groups
1599
-	 * @return bool
1600
-	 */
1601
-	public function allowGroupSharing() {
1602
-		return $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes';
1603
-	}
1604
-
1605
-	/**
1606
-	 * Copied from \OC_Util::isSharingDisabledForUser
1607
-	 *
1608
-	 * TODO: Deprecate fuction from OC_Util
1609
-	 *
1610
-	 * @param string $userId
1611
-	 * @return bool
1612
-	 */
1613
-	public function sharingDisabledForUser($userId) {
1614
-		if ($userId === null) {
1615
-			return false;
1616
-		}
1617
-
1618
-		if (isset($this->sharingDisabledForUsersCache[$userId])) {
1619
-			return $this->sharingDisabledForUsersCache[$userId];
1620
-		}
1621
-
1622
-		if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
1623
-			$groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
1624
-			$excludedGroups = json_decode($groupsList);
1625
-			if (is_null($excludedGroups)) {
1626
-				$excludedGroups = explode(',', $groupsList);
1627
-				$newValue = json_encode($excludedGroups);
1628
-				$this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
1629
-			}
1630
-			$user = $this->userManager->get($userId);
1631
-			$usersGroups = $this->groupManager->getUserGroupIds($user);
1632
-			if (!empty($usersGroups)) {
1633
-				$remainingGroups = array_diff($usersGroups, $excludedGroups);
1634
-				// if the user is only in groups which are disabled for sharing then
1635
-				// sharing is also disabled for the user
1636
-				if (empty($remainingGroups)) {
1637
-					$this->sharingDisabledForUsersCache[$userId] = true;
1638
-					return true;
1639
-				}
1640
-			}
1641
-		}
1642
-
1643
-		$this->sharingDisabledForUsersCache[$userId] = false;
1644
-		return false;
1645
-	}
1646
-
1647
-	/**
1648
-	 * @inheritdoc
1649
-	 */
1650
-	public function outgoingServer2ServerSharesAllowed() {
1651
-		return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
1652
-	}
1653
-
1654
-	/**
1655
-	 * @inheritdoc
1656
-	 */
1657
-	public function outgoingServer2ServerGroupSharesAllowed() {
1658
-		return $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no') === 'yes';
1659
-	}
1660
-
1661
-	/**
1662
-	 * @inheritdoc
1663
-	 */
1664
-	public function shareProviderExists($shareType) {
1665
-		try {
1666
-			$this->factory->getProviderForType($shareType);
1667
-		} catch (ProviderException $e) {
1668
-			return false;
1669
-		}
1670
-
1671
-		return true;
1672
-	}
1306
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
1307
+            !$this->shareApiLinkAllowPublicUpload()) {
1308
+            $share->setPermissions($share->getPermissions() & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE));
1309
+        }
1310
+
1311
+        return $share;
1312
+    }
1313
+
1314
+    protected function checkExpireDate($share) {
1315
+        if ($share->getExpirationDate() !== null &&
1316
+            $share->getExpirationDate() <= new \DateTime()) {
1317
+            $this->deleteShare($share);
1318
+            throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1319
+        }
1320
+
1321
+    }
1322
+
1323
+    /**
1324
+     * Verify the password of a public share
1325
+     *
1326
+     * @param \OCP\Share\IShare $share
1327
+     * @param string $password
1328
+     * @return bool
1329
+     */
1330
+    public function checkPassword(\OCP\Share\IShare $share, $password) {
1331
+        $passwordProtected = $share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK
1332
+            || $share->getShareType() !== \OCP\Share::SHARE_TYPE_EMAIL;
1333
+        if (!$passwordProtected) {
1334
+            //TODO maybe exception?
1335
+            return false;
1336
+        }
1337
+
1338
+        if ($password === null || $share->getPassword() === null) {
1339
+            return false;
1340
+        }
1341
+
1342
+        $newHash = '';
1343
+        if (!$this->hasher->verify($password, $share->getPassword(), $newHash)) {
1344
+            return false;
1345
+        }
1346
+
1347
+        if (!empty($newHash)) {
1348
+            $share->setPassword($newHash);
1349
+            $provider = $this->factory->getProviderForType($share->getShareType());
1350
+            $provider->update($share);
1351
+        }
1352
+
1353
+        return true;
1354
+    }
1355
+
1356
+    /**
1357
+     * @inheritdoc
1358
+     */
1359
+    public function userDeleted($uid) {
1360
+        $types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];
1361
+
1362
+        foreach ($types as $type) {
1363
+            try {
1364
+                $provider = $this->factory->getProviderForType($type);
1365
+            } catch (ProviderException $e) {
1366
+                continue;
1367
+            }
1368
+            $provider->userDeleted($uid, $type);
1369
+        }
1370
+    }
1371
+
1372
+    /**
1373
+     * @inheritdoc
1374
+     */
1375
+    public function groupDeleted($gid) {
1376
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1377
+        $provider->groupDeleted($gid);
1378
+    }
1379
+
1380
+    /**
1381
+     * @inheritdoc
1382
+     */
1383
+    public function userDeletedFromGroup($uid, $gid) {
1384
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1385
+        $provider->userDeletedFromGroup($uid, $gid);
1386
+    }
1387
+
1388
+    /**
1389
+     * Get access list to a path. This means
1390
+     * all the users that can access a given path.
1391
+     *
1392
+     * Consider:
1393
+     * -root
1394
+     * |-folder1 (23)
1395
+     *  |-folder2 (32)
1396
+     *   |-fileA (42)
1397
+     *
1398
+     * fileA is shared with user1 and user1@server1
1399
+     * folder2 is shared with group2 (user4 is a member of group2)
1400
+     * folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
1401
+     *
1402
+     * Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
1403
+     * [
1404
+     *  users  => [
1405
+     *      'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
1406
+     *      'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
1407
+     *      'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
1408
+     *  ],
1409
+     *  remote => [
1410
+     *      'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
1411
+     *      'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
1412
+     *  ],
1413
+     *  public => bool
1414
+     *  mail => bool
1415
+     * ]
1416
+     *
1417
+     * The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
1418
+     * [
1419
+     *  users  => ['user1', 'user2', 'user4'],
1420
+     *  remote => bool,
1421
+     *  public => bool
1422
+     *  mail => bool
1423
+     * ]
1424
+     *
1425
+     * This is required for encryption/activity
1426
+     *
1427
+     * @param \OCP\Files\Node $path
1428
+     * @param bool $recursive Should we check all parent folders as well
1429
+     * @param bool $currentAccess Ensure the recipient has access to the file (e.g. did not unshare it)
1430
+     * @return array
1431
+     */
1432
+    public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
1433
+        $owner = $path->getOwner();
1434
+
1435
+        if ($owner === null) {
1436
+            return [];
1437
+        }
1438
+
1439
+        $owner = $owner->getUID();
1440
+
1441
+        if ($currentAccess) {
1442
+            $al = ['users' => [], 'remote' => [], 'public' => false];
1443
+        } else {
1444
+            $al = ['users' => [], 'remote' => false, 'public' => false];
1445
+        }
1446
+        if (!$this->userManager->userExists($owner)) {
1447
+            return $al;
1448
+        }
1449
+
1450
+        //Get node for the owner and correct the owner in case of external storages
1451
+        $userFolder = $this->rootFolder->getUserFolder($owner);
1452
+        if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) {
1453
+            $nodes = $userFolder->getById($path->getId());
1454
+            $path = array_shift($nodes);
1455
+            if ($path->getOwner() === null) {
1456
+                return [];
1457
+            }
1458
+            $owner = $path->getOwner()->getUID();
1459
+        }
1460
+
1461
+        $providers = $this->factory->getAllProviders();
1462
+
1463
+        /** @var Node[] $nodes */
1464
+        $nodes = [];
1465
+
1466
+
1467
+        if ($currentAccess) {
1468
+            $ownerPath = $path->getPath();
1469
+            $ownerPath = explode('/', $ownerPath, 4);
1470
+            if (count($ownerPath) < 4) {
1471
+                $ownerPath = '';
1472
+            } else {
1473
+                $ownerPath = $ownerPath[3];
1474
+            }
1475
+            $al['users'][$owner] = [
1476
+                'node_id' => $path->getId(),
1477
+                'node_path' => '/' . $ownerPath,
1478
+            ];
1479
+        } else {
1480
+            $al['users'][] = $owner;
1481
+        }
1482
+
1483
+        // Collect all the shares
1484
+        while ($path->getPath() !== $userFolder->getPath()) {
1485
+            $nodes[] = $path;
1486
+            if (!$recursive) {
1487
+                break;
1488
+            }
1489
+            $path = $path->getParent();
1490
+        }
1491
+
1492
+        foreach ($providers as $provider) {
1493
+            $tmp = $provider->getAccessList($nodes, $currentAccess);
1494
+
1495
+            foreach ($tmp as $k => $v) {
1496
+                if (isset($al[$k])) {
1497
+                    if (is_array($al[$k])) {
1498
+                        if ($currentAccess) {
1499
+                            $al[$k] += $v;
1500
+                        } else {
1501
+                            $al[$k] = array_merge($al[$k], $v);
1502
+                            $al[$k] = array_unique($al[$k]);
1503
+                            $al[$k] = array_values($al[$k]);
1504
+                        }
1505
+                    } else {
1506
+                        $al[$k] = $al[$k] || $v;
1507
+                    }
1508
+                } else {
1509
+                    $al[$k] = $v;
1510
+                }
1511
+            }
1512
+        }
1513
+
1514
+        return $al;
1515
+    }
1516
+
1517
+    /**
1518
+     * Create a new share
1519
+     * @return \OCP\Share\IShare
1520
+     */
1521
+    public function newShare() {
1522
+        return new \OC\Share20\Share($this->rootFolder, $this->userManager);
1523
+    }
1524
+
1525
+    /**
1526
+     * Is the share API enabled
1527
+     *
1528
+     * @return bool
1529
+     */
1530
+    public function shareApiEnabled() {
1531
+        return $this->config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes';
1532
+    }
1533
+
1534
+    /**
1535
+     * Is public link sharing enabled
1536
+     *
1537
+     * @return bool
1538
+     */
1539
+    public function shareApiAllowLinks() {
1540
+        return $this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes';
1541
+    }
1542
+
1543
+    /**
1544
+     * Is password on public link requires
1545
+     *
1546
+     * @return bool
1547
+     */
1548
+    public function shareApiLinkEnforcePassword() {
1549
+        return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes';
1550
+    }
1551
+
1552
+    /**
1553
+     * Is default expire date enabled
1554
+     *
1555
+     * @return bool
1556
+     */
1557
+    public function shareApiLinkDefaultExpireDate() {
1558
+        return $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
1559
+    }
1560
+
1561
+    /**
1562
+     * Is default expire date enforced
1563
+     *`
1564
+     * @return bool
1565
+     */
1566
+    public function shareApiLinkDefaultExpireDateEnforced() {
1567
+        return $this->shareApiLinkDefaultExpireDate() &&
1568
+            $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
1569
+    }
1570
+
1571
+    /**
1572
+     * Number of default expire days
1573
+     *shareApiLinkAllowPublicUpload
1574
+     * @return int
1575
+     */
1576
+    public function shareApiLinkDefaultExpireDays() {
1577
+        return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1578
+    }
1579
+
1580
+    /**
1581
+     * Allow public upload on link shares
1582
+     *
1583
+     * @return bool
1584
+     */
1585
+    public function shareApiLinkAllowPublicUpload() {
1586
+        return $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
1587
+    }
1588
+
1589
+    /**
1590
+     * check if user can only share with group members
1591
+     * @return bool
1592
+     */
1593
+    public function shareWithGroupMembersOnly() {
1594
+        return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
1595
+    }
1596
+
1597
+    /**
1598
+     * Check if users can share with groups
1599
+     * @return bool
1600
+     */
1601
+    public function allowGroupSharing() {
1602
+        return $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes';
1603
+    }
1604
+
1605
+    /**
1606
+     * Copied from \OC_Util::isSharingDisabledForUser
1607
+     *
1608
+     * TODO: Deprecate fuction from OC_Util
1609
+     *
1610
+     * @param string $userId
1611
+     * @return bool
1612
+     */
1613
+    public function sharingDisabledForUser($userId) {
1614
+        if ($userId === null) {
1615
+            return false;
1616
+        }
1617
+
1618
+        if (isset($this->sharingDisabledForUsersCache[$userId])) {
1619
+            return $this->sharingDisabledForUsersCache[$userId];
1620
+        }
1621
+
1622
+        if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
1623
+            $groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
1624
+            $excludedGroups = json_decode($groupsList);
1625
+            if (is_null($excludedGroups)) {
1626
+                $excludedGroups = explode(',', $groupsList);
1627
+                $newValue = json_encode($excludedGroups);
1628
+                $this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
1629
+            }
1630
+            $user = $this->userManager->get($userId);
1631
+            $usersGroups = $this->groupManager->getUserGroupIds($user);
1632
+            if (!empty($usersGroups)) {
1633
+                $remainingGroups = array_diff($usersGroups, $excludedGroups);
1634
+                // if the user is only in groups which are disabled for sharing then
1635
+                // sharing is also disabled for the user
1636
+                if (empty($remainingGroups)) {
1637
+                    $this->sharingDisabledForUsersCache[$userId] = true;
1638
+                    return true;
1639
+                }
1640
+            }
1641
+        }
1642
+
1643
+        $this->sharingDisabledForUsersCache[$userId] = false;
1644
+        return false;
1645
+    }
1646
+
1647
+    /**
1648
+     * @inheritdoc
1649
+     */
1650
+    public function outgoingServer2ServerSharesAllowed() {
1651
+        return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
1652
+    }
1653
+
1654
+    /**
1655
+     * @inheritdoc
1656
+     */
1657
+    public function outgoingServer2ServerGroupSharesAllowed() {
1658
+        return $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no') === 'yes';
1659
+    }
1660
+
1661
+    /**
1662
+     * @inheritdoc
1663
+     */
1664
+    public function shareProviderExists($shareType) {
1665
+        try {
1666
+            $this->factory->getProviderForType($shareType);
1667
+        } catch (ProviderException $e) {
1668
+            return false;
1669
+        }
1670
+
1671
+        return true;
1672
+    }
1673 1673
 
1674 1674
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Controller/ShareAPIController.php 1 patch
Indentation   +1136 added lines, -1136 removed lines patch added patch discarded remove patch
@@ -65,1147 +65,1147 @@
 block discarded – undo
65 65
  */
66 66
 class ShareAPIController extends OCSController {
67 67
 
68
-	/** @var IManager */
69
-	private $shareManager;
70
-	/** @var IGroupManager */
71
-	private $groupManager;
72
-	/** @var IUserManager */
73
-	private $userManager;
74
-	/** @var IRootFolder */
75
-	private $rootFolder;
76
-	/** @var IURLGenerator */
77
-	private $urlGenerator;
78
-	/** @var string */
79
-	private $currentUser;
80
-	/** @var IL10N */
81
-	private $l;
82
-	/** @var \OCP\Files\Node */
83
-	private $lockedNode;
84
-	/** @var IConfig */
85
-	private $config;
86
-	/** @var IAppManager */
87
-	private $appManager;
88
-	/** @var IServerContainer */
89
-	private $serverContainer;
90
-
91
-	/**
92
-	 * Share20OCS constructor.
93
-	 *
94
-	 * @param string $appName
95
-	 * @param IRequest $request
96
-	 * @param IManager $shareManager
97
-	 * @param IGroupManager $groupManager
98
-	 * @param IUserManager $userManager
99
-	 * @param IRootFolder $rootFolder
100
-	 * @param IURLGenerator $urlGenerator
101
-	 * @param string $userId
102
-	 * @param IL10N $l10n
103
-	 * @param IConfig $config
104
-	 * @param IAppManager $appManager
105
-	 * @param IServerContainer $serverContainer
106
-	 */
107
-	public function __construct(
108
-		string $appName,
109
-		IRequest $request,
110
-		IManager $shareManager,
111
-		IGroupManager $groupManager,
112
-		IUserManager $userManager,
113
-		IRootFolder $rootFolder,
114
-		IURLGenerator $urlGenerator,
115
-		string $userId = null,
116
-		IL10N $l10n,
117
-		IConfig $config,
118
-		IAppManager $appManager,
119
-		IServerContainer $serverContainer
120
-	) {
121
-		parent::__construct($appName, $request);
122
-
123
-		$this->shareManager = $shareManager;
124
-		$this->userManager = $userManager;
125
-		$this->groupManager = $groupManager;
126
-		$this->request = $request;
127
-		$this->rootFolder = $rootFolder;
128
-		$this->urlGenerator = $urlGenerator;
129
-		$this->currentUser = $userId;
130
-		$this->l = $l10n;
131
-		$this->config = $config;
132
-		$this->appManager = $appManager;
133
-		$this->serverContainer = $serverContainer;
134
-	}
135
-
136
-	/**
137
-	 * Convert an IShare to an array for OCS output
138
-	 *
139
-	 * @param \OCP\Share\IShare $share
140
-	 * @param Node|null $recipientNode
141
-	 * @return array
142
-	 * @throws NotFoundException In case the node can't be resolved.
143
-	 *
144
-	 * @suppress PhanUndeclaredClassMethod
145
-	 */
146
-	protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = null): array {
147
-		$sharedBy = $this->userManager->get($share->getSharedBy());
148
-		$shareOwner = $this->userManager->get($share->getShareOwner());
149
-
150
-		$result = [
151
-			'id' => $share->getId(),
152
-			'share_type' => $share->getShareType(),
153
-			'uid_owner' => $share->getSharedBy(),
154
-			'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(),
155
-			'permissions' => $share->getPermissions(),
156
-			'stime' => $share->getShareTime()->getTimestamp(),
157
-			'parent' => null,
158
-			'expiration' => null,
159
-			'token' => null,
160
-			'uid_file_owner' => $share->getShareOwner(),
161
-			'note' => $share->getNote(),
162
-			'label' => $share->getLabel(),
163
-			'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(),
164
-		];
165
-
166
-		$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
167
-		if ($recipientNode) {
168
-			$node = $recipientNode;
169
-		} else {
170
-			$nodes = $userFolder->getById($share->getNodeId());
171
-			if (empty($nodes)) {
172
-				// fallback to guessing the path
173
-				$node = $userFolder->get($share->getTarget());
174
-				if ($node === null || $share->getTarget() === '') {
175
-					throw new NotFoundException();
176
-				}
177
-			} else {
178
-				$node = $nodes[0];
179
-			}
180
-		}
181
-
182
-		$result['path'] = $userFolder->getRelativePath($node->getPath());
183
-		if ($node instanceOf \OCP\Files\Folder) {
184
-			$result['item_type'] = 'folder';
185
-		} else {
186
-			$result['item_type'] = 'file';
187
-		}
188
-		$result['mimetype'] = $node->getMimetype();
189
-		$result['storage_id'] = $node->getStorage()->getId();
190
-		$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
191
-		$result['item_source'] = $node->getId();
192
-		$result['file_source'] = $node->getId();
193
-		$result['file_parent'] = $node->getParent()->getId();
194
-		$result['file_target'] = $share->getTarget();
195
-
196
-		$expiration = $share->getExpirationDate();
197
-		if ($expiration !== null) {
198
-			$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
199
-		}
200
-
201
-		if ($share->getShareType() === Share::SHARE_TYPE_USER) {
202
-			$sharedWith = $this->userManager->get($share->getSharedWith());
203
-			$result['share_with'] = $share->getSharedWith();
204
-			$result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
205
-		} else if ($share->getShareType() === Share::SHARE_TYPE_GROUP) {
206
-			$group = $this->groupManager->get($share->getSharedWith());
207
-			$result['share_with'] = $share->getSharedWith();
208
-			$result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
209
-		} else if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
210
-
211
-			// "share_with" and "share_with_displayname" for passwords of link
212
-			// shares was deprecated in Nextcloud 15, use "password" instead.
213
-			$result['share_with'] = $share->getPassword();
214
-			$result['share_with_displayname'] = $share->getPassword();
215
-
216
-			$result['password'] = $share->getPassword();
217
-
218
-			$result['send_password_by_talk'] = $share->getSendPasswordByTalk();
219
-
220
-			$result['token'] = $share->getToken();
221
-			$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
222
-
223
-		} else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() === Share::SHARE_TYPE_REMOTE_GROUP) {
224
-			$result['share_with'] = $share->getSharedWith();
225
-			$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
226
-			$result['token'] = $share->getToken();
227
-		} else if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
228
-			$result['share_with'] = $share->getSharedWith();
229
-			$result['password'] = $share->getPassword();
230
-			$result['send_password_by_talk'] = $share->getSendPasswordByTalk();
231
-			$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
232
-			$result['token'] = $share->getToken();
233
-		} else if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
234
-			// getSharedWith() returns either "name (type, owner)" or
235
-			// "name (type, owner) [id]", depending on the Circles app version.
236
-			$hasCircleId = (substr($share->getSharedWith(), -1) === ']');
237
-
238
-			$result['share_with_displayname'] = $share->getSharedWithDisplayName();
239
-			if (empty($result['share_with_displayname'])) {
240
-				$displayNameLength = ($hasCircleId? strrpos($share->getSharedWith(), ' '): strlen($share->getSharedWith()));
241
-				$result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
242
-			}
243
-
244
-			$result['share_with_avatar'] = $share->getSharedWithAvatar();
245
-
246
-			$shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0);
247
-			$shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' '));
248
-			if (is_bool($shareWithLength)) {
249
-				$shareWithLength = -1;
250
-			}
251
-			$result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
252
-		} else if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
253
-			$result['share_with'] = $share->getSharedWith();
254
-			$result['share_with_displayname'] = '';
255
-
256
-			try {
257
-				$result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
258
-			} catch (QueryException $e) {
259
-			}
260
-		}
261
-
262
-
263
-		$result['mail_send'] = $share->getMailSend() ? 1 : 0;
264
-		$result['hide_download'] = $share->getHideDownload() ? 1 : 0;
265
-
266
-		return $result;
267
-	}
268
-
269
-	/**
270
-	 * Check if one of the users address books knows the exact property, if
271
-	 * yes we return the full name.
272
-	 *
273
-	 * @param string $query
274
-	 * @param string $property
275
-	 * @return string
276
-	 */
277
-	private function getDisplayNameFromAddressBook(string $query, string $property): string {
278
-		// FIXME: If we inject the contacts manager it gets initialized bofore any address books are registered
279
-		$result = \OC::$server->getContactsManager()->search($query, [$property]);
280
-		foreach ($result as $r) {
281
-			foreach($r[$property] as $value) {
282
-				if ($value === $query) {
283
-					return $r['FN'];
284
-				}
285
-			}
286
-		}
287
-
288
-		return $query;
289
-	}
290
-
291
-	/**
292
-	 * Get a specific share by id
293
-	 *
294
-	 * @NoAdminRequired
295
-	 *
296
-	 * @param string $id
297
-	 * @return DataResponse
298
-	 * @throws OCSNotFoundException
299
-	 */
300
-	public function getShare(string $id): DataResponse {
301
-		try {
302
-			$share = $this->getShareById($id);
303
-		} catch (ShareNotFound $e) {
304
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
305
-		}
306
-
307
-		if ($this->canAccessShare($share)) {
308
-			try {
309
-				$share = $this->formatShare($share);
310
-				return new DataResponse([$share]);
311
-			} catch (NotFoundException $e) {
312
-				//Fall trough
313
-			}
314
-		}
315
-
316
-		throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
317
-	}
318
-
319
-	/**
320
-	 * Delete a share
321
-	 *
322
-	 * @NoAdminRequired
323
-	 *
324
-	 * @param string $id
325
-	 * @return DataResponse
326
-	 * @throws OCSNotFoundException
327
-	 */
328
-	public function deleteShare(string $id): DataResponse {
329
-		try {
330
-			$share = $this->getShareById($id);
331
-		} catch (ShareNotFound $e) {
332
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
333
-		}
334
-
335
-		try {
336
-			$this->lock($share->getNode());
337
-		} catch (LockedException $e) {
338
-			throw new OCSNotFoundException($this->l->t('could not delete share'));
339
-		}
340
-
341
-		if (!$this->canAccessShare($share)) {
342
-			throw new OCSNotFoundException($this->l->t('Could not delete share'));
343
-		}
344
-
345
-		if (($share->getShareType() === Share::SHARE_TYPE_GROUP ||
346
-				$share->getShareType() === Share::SHARE_TYPE_ROOM) &&
347
-			$share->getShareOwner() !== $this->currentUser &&
348
-			$share->getSharedBy() !== $this->currentUser) {
349
-			$this->shareManager->deleteFromSelf($share, $this->currentUser);
350
-		} else {
351
-			$this->shareManager->deleteShare($share);
352
-		}
353
-
354
-		return new DataResponse();
355
-	}
356
-
357
-	/**
358
-	 * @NoAdminRequired
359
-	 *
360
-	 * @param string $path
361
-	 * @param int $permissions
362
-	 * @param int $shareType
363
-	 * @param string $shareWith
364
-	 * @param string $publicUpload
365
-	 * @param string $password
366
-	 * @param string $sendPasswordByTalk
367
-	 * @param string $expireDate
368
-	 * @param string $label
369
-	 *
370
-	 * @return DataResponse
371
-	 * @throws NotFoundException
372
-	 * @throws OCSBadRequestException
373
-	 * @throws OCSException
374
-	 * @throws OCSForbiddenException
375
-	 * @throws OCSNotFoundException
376
-	 * @throws \OCP\Files\InvalidPathException
377
-	 * @suppress PhanUndeclaredClassMethod
378
-	 */
379
-	public function createShare(
380
-		string $path = null,
381
-		int $permissions = null,
382
-		int $shareType = -1,
383
-		string $shareWith = null,
384
-		string $publicUpload = 'false',
385
-		string $password = '',
386
-		string $sendPasswordByTalk = null,
387
-		string $expireDate = '',
388
-		string $label = ''
389
-	): DataResponse {
390
-		$share = $this->shareManager->newShare();
391
-
392
-		if ($permissions === null) {
393
-			$permissions = $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL);
394
-		}
395
-
396
-		// Verify path
397
-		if ($path === null) {
398
-			throw new OCSNotFoundException($this->l->t('Please specify a file or folder path'));
399
-		}
400
-
401
-		$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
402
-		try {
403
-			$path = $userFolder->get($path);
404
-		} catch (NotFoundException $e) {
405
-			throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
406
-		}
407
-
408
-		$share->setNode($path);
409
-
410
-		try {
411
-			$this->lock($share->getNode());
412
-		} catch (LockedException $e) {
413
-			throw new OCSNotFoundException($this->l->t('Could not create share'));
414
-		}
415
-
416
-		if ($permissions < 0 || $permissions > Constants::PERMISSION_ALL) {
417
-			throw new OCSNotFoundException($this->l->t('invalid permissions'));
418
-		}
419
-
420
-		// Shares always require read permissions
421
-		$permissions |= Constants::PERMISSION_READ;
422
-
423
-		if ($path instanceof \OCP\Files\File) {
424
-			// Single file shares should never have delete or create permissions
425
-			$permissions &= ~Constants::PERMISSION_DELETE;
426
-			$permissions &= ~Constants::PERMISSION_CREATE;
427
-		}
428
-
429
-		/*
68
+    /** @var IManager */
69
+    private $shareManager;
70
+    /** @var IGroupManager */
71
+    private $groupManager;
72
+    /** @var IUserManager */
73
+    private $userManager;
74
+    /** @var IRootFolder */
75
+    private $rootFolder;
76
+    /** @var IURLGenerator */
77
+    private $urlGenerator;
78
+    /** @var string */
79
+    private $currentUser;
80
+    /** @var IL10N */
81
+    private $l;
82
+    /** @var \OCP\Files\Node */
83
+    private $lockedNode;
84
+    /** @var IConfig */
85
+    private $config;
86
+    /** @var IAppManager */
87
+    private $appManager;
88
+    /** @var IServerContainer */
89
+    private $serverContainer;
90
+
91
+    /**
92
+     * Share20OCS constructor.
93
+     *
94
+     * @param string $appName
95
+     * @param IRequest $request
96
+     * @param IManager $shareManager
97
+     * @param IGroupManager $groupManager
98
+     * @param IUserManager $userManager
99
+     * @param IRootFolder $rootFolder
100
+     * @param IURLGenerator $urlGenerator
101
+     * @param string $userId
102
+     * @param IL10N $l10n
103
+     * @param IConfig $config
104
+     * @param IAppManager $appManager
105
+     * @param IServerContainer $serverContainer
106
+     */
107
+    public function __construct(
108
+        string $appName,
109
+        IRequest $request,
110
+        IManager $shareManager,
111
+        IGroupManager $groupManager,
112
+        IUserManager $userManager,
113
+        IRootFolder $rootFolder,
114
+        IURLGenerator $urlGenerator,
115
+        string $userId = null,
116
+        IL10N $l10n,
117
+        IConfig $config,
118
+        IAppManager $appManager,
119
+        IServerContainer $serverContainer
120
+    ) {
121
+        parent::__construct($appName, $request);
122
+
123
+        $this->shareManager = $shareManager;
124
+        $this->userManager = $userManager;
125
+        $this->groupManager = $groupManager;
126
+        $this->request = $request;
127
+        $this->rootFolder = $rootFolder;
128
+        $this->urlGenerator = $urlGenerator;
129
+        $this->currentUser = $userId;
130
+        $this->l = $l10n;
131
+        $this->config = $config;
132
+        $this->appManager = $appManager;
133
+        $this->serverContainer = $serverContainer;
134
+    }
135
+
136
+    /**
137
+     * Convert an IShare to an array for OCS output
138
+     *
139
+     * @param \OCP\Share\IShare $share
140
+     * @param Node|null $recipientNode
141
+     * @return array
142
+     * @throws NotFoundException In case the node can't be resolved.
143
+     *
144
+     * @suppress PhanUndeclaredClassMethod
145
+     */
146
+    protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = null): array {
147
+        $sharedBy = $this->userManager->get($share->getSharedBy());
148
+        $shareOwner = $this->userManager->get($share->getShareOwner());
149
+
150
+        $result = [
151
+            'id' => $share->getId(),
152
+            'share_type' => $share->getShareType(),
153
+            'uid_owner' => $share->getSharedBy(),
154
+            'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(),
155
+            'permissions' => $share->getPermissions(),
156
+            'stime' => $share->getShareTime()->getTimestamp(),
157
+            'parent' => null,
158
+            'expiration' => null,
159
+            'token' => null,
160
+            'uid_file_owner' => $share->getShareOwner(),
161
+            'note' => $share->getNote(),
162
+            'label' => $share->getLabel(),
163
+            'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(),
164
+        ];
165
+
166
+        $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
167
+        if ($recipientNode) {
168
+            $node = $recipientNode;
169
+        } else {
170
+            $nodes = $userFolder->getById($share->getNodeId());
171
+            if (empty($nodes)) {
172
+                // fallback to guessing the path
173
+                $node = $userFolder->get($share->getTarget());
174
+                if ($node === null || $share->getTarget() === '') {
175
+                    throw new NotFoundException();
176
+                }
177
+            } else {
178
+                $node = $nodes[0];
179
+            }
180
+        }
181
+
182
+        $result['path'] = $userFolder->getRelativePath($node->getPath());
183
+        if ($node instanceOf \OCP\Files\Folder) {
184
+            $result['item_type'] = 'folder';
185
+        } else {
186
+            $result['item_type'] = 'file';
187
+        }
188
+        $result['mimetype'] = $node->getMimetype();
189
+        $result['storage_id'] = $node->getStorage()->getId();
190
+        $result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
191
+        $result['item_source'] = $node->getId();
192
+        $result['file_source'] = $node->getId();
193
+        $result['file_parent'] = $node->getParent()->getId();
194
+        $result['file_target'] = $share->getTarget();
195
+
196
+        $expiration = $share->getExpirationDate();
197
+        if ($expiration !== null) {
198
+            $result['expiration'] = $expiration->format('Y-m-d 00:00:00');
199
+        }
200
+
201
+        if ($share->getShareType() === Share::SHARE_TYPE_USER) {
202
+            $sharedWith = $this->userManager->get($share->getSharedWith());
203
+            $result['share_with'] = $share->getSharedWith();
204
+            $result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
205
+        } else if ($share->getShareType() === Share::SHARE_TYPE_GROUP) {
206
+            $group = $this->groupManager->get($share->getSharedWith());
207
+            $result['share_with'] = $share->getSharedWith();
208
+            $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
209
+        } else if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
210
+
211
+            // "share_with" and "share_with_displayname" for passwords of link
212
+            // shares was deprecated in Nextcloud 15, use "password" instead.
213
+            $result['share_with'] = $share->getPassword();
214
+            $result['share_with_displayname'] = $share->getPassword();
215
+
216
+            $result['password'] = $share->getPassword();
217
+
218
+            $result['send_password_by_talk'] = $share->getSendPasswordByTalk();
219
+
220
+            $result['token'] = $share->getToken();
221
+            $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
222
+
223
+        } else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() === Share::SHARE_TYPE_REMOTE_GROUP) {
224
+            $result['share_with'] = $share->getSharedWith();
225
+            $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
226
+            $result['token'] = $share->getToken();
227
+        } else if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
228
+            $result['share_with'] = $share->getSharedWith();
229
+            $result['password'] = $share->getPassword();
230
+            $result['send_password_by_talk'] = $share->getSendPasswordByTalk();
231
+            $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
232
+            $result['token'] = $share->getToken();
233
+        } else if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
234
+            // getSharedWith() returns either "name (type, owner)" or
235
+            // "name (type, owner) [id]", depending on the Circles app version.
236
+            $hasCircleId = (substr($share->getSharedWith(), -1) === ']');
237
+
238
+            $result['share_with_displayname'] = $share->getSharedWithDisplayName();
239
+            if (empty($result['share_with_displayname'])) {
240
+                $displayNameLength = ($hasCircleId? strrpos($share->getSharedWith(), ' '): strlen($share->getSharedWith()));
241
+                $result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
242
+            }
243
+
244
+            $result['share_with_avatar'] = $share->getSharedWithAvatar();
245
+
246
+            $shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0);
247
+            $shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' '));
248
+            if (is_bool($shareWithLength)) {
249
+                $shareWithLength = -1;
250
+            }
251
+            $result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
252
+        } else if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
253
+            $result['share_with'] = $share->getSharedWith();
254
+            $result['share_with_displayname'] = '';
255
+
256
+            try {
257
+                $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
258
+            } catch (QueryException $e) {
259
+            }
260
+        }
261
+
262
+
263
+        $result['mail_send'] = $share->getMailSend() ? 1 : 0;
264
+        $result['hide_download'] = $share->getHideDownload() ? 1 : 0;
265
+
266
+        return $result;
267
+    }
268
+
269
+    /**
270
+     * Check if one of the users address books knows the exact property, if
271
+     * yes we return the full name.
272
+     *
273
+     * @param string $query
274
+     * @param string $property
275
+     * @return string
276
+     */
277
+    private function getDisplayNameFromAddressBook(string $query, string $property): string {
278
+        // FIXME: If we inject the contacts manager it gets initialized bofore any address books are registered
279
+        $result = \OC::$server->getContactsManager()->search($query, [$property]);
280
+        foreach ($result as $r) {
281
+            foreach($r[$property] as $value) {
282
+                if ($value === $query) {
283
+                    return $r['FN'];
284
+                }
285
+            }
286
+        }
287
+
288
+        return $query;
289
+    }
290
+
291
+    /**
292
+     * Get a specific share by id
293
+     *
294
+     * @NoAdminRequired
295
+     *
296
+     * @param string $id
297
+     * @return DataResponse
298
+     * @throws OCSNotFoundException
299
+     */
300
+    public function getShare(string $id): DataResponse {
301
+        try {
302
+            $share = $this->getShareById($id);
303
+        } catch (ShareNotFound $e) {
304
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
305
+        }
306
+
307
+        if ($this->canAccessShare($share)) {
308
+            try {
309
+                $share = $this->formatShare($share);
310
+                return new DataResponse([$share]);
311
+            } catch (NotFoundException $e) {
312
+                //Fall trough
313
+            }
314
+        }
315
+
316
+        throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
317
+    }
318
+
319
+    /**
320
+     * Delete a share
321
+     *
322
+     * @NoAdminRequired
323
+     *
324
+     * @param string $id
325
+     * @return DataResponse
326
+     * @throws OCSNotFoundException
327
+     */
328
+    public function deleteShare(string $id): DataResponse {
329
+        try {
330
+            $share = $this->getShareById($id);
331
+        } catch (ShareNotFound $e) {
332
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
333
+        }
334
+
335
+        try {
336
+            $this->lock($share->getNode());
337
+        } catch (LockedException $e) {
338
+            throw new OCSNotFoundException($this->l->t('could not delete share'));
339
+        }
340
+
341
+        if (!$this->canAccessShare($share)) {
342
+            throw new OCSNotFoundException($this->l->t('Could not delete share'));
343
+        }
344
+
345
+        if (($share->getShareType() === Share::SHARE_TYPE_GROUP ||
346
+                $share->getShareType() === Share::SHARE_TYPE_ROOM) &&
347
+            $share->getShareOwner() !== $this->currentUser &&
348
+            $share->getSharedBy() !== $this->currentUser) {
349
+            $this->shareManager->deleteFromSelf($share, $this->currentUser);
350
+        } else {
351
+            $this->shareManager->deleteShare($share);
352
+        }
353
+
354
+        return new DataResponse();
355
+    }
356
+
357
+    /**
358
+     * @NoAdminRequired
359
+     *
360
+     * @param string $path
361
+     * @param int $permissions
362
+     * @param int $shareType
363
+     * @param string $shareWith
364
+     * @param string $publicUpload
365
+     * @param string $password
366
+     * @param string $sendPasswordByTalk
367
+     * @param string $expireDate
368
+     * @param string $label
369
+     *
370
+     * @return DataResponse
371
+     * @throws NotFoundException
372
+     * @throws OCSBadRequestException
373
+     * @throws OCSException
374
+     * @throws OCSForbiddenException
375
+     * @throws OCSNotFoundException
376
+     * @throws \OCP\Files\InvalidPathException
377
+     * @suppress PhanUndeclaredClassMethod
378
+     */
379
+    public function createShare(
380
+        string $path = null,
381
+        int $permissions = null,
382
+        int $shareType = -1,
383
+        string $shareWith = null,
384
+        string $publicUpload = 'false',
385
+        string $password = '',
386
+        string $sendPasswordByTalk = null,
387
+        string $expireDate = '',
388
+        string $label = ''
389
+    ): DataResponse {
390
+        $share = $this->shareManager->newShare();
391
+
392
+        if ($permissions === null) {
393
+            $permissions = $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL);
394
+        }
395
+
396
+        // Verify path
397
+        if ($path === null) {
398
+            throw new OCSNotFoundException($this->l->t('Please specify a file or folder path'));
399
+        }
400
+
401
+        $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
402
+        try {
403
+            $path = $userFolder->get($path);
404
+        } catch (NotFoundException $e) {
405
+            throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
406
+        }
407
+
408
+        $share->setNode($path);
409
+
410
+        try {
411
+            $this->lock($share->getNode());
412
+        } catch (LockedException $e) {
413
+            throw new OCSNotFoundException($this->l->t('Could not create share'));
414
+        }
415
+
416
+        if ($permissions < 0 || $permissions > Constants::PERMISSION_ALL) {
417
+            throw new OCSNotFoundException($this->l->t('invalid permissions'));
418
+        }
419
+
420
+        // Shares always require read permissions
421
+        $permissions |= Constants::PERMISSION_READ;
422
+
423
+        if ($path instanceof \OCP\Files\File) {
424
+            // Single file shares should never have delete or create permissions
425
+            $permissions &= ~Constants::PERMISSION_DELETE;
426
+            $permissions &= ~Constants::PERMISSION_CREATE;
427
+        }
428
+
429
+        /*
430 430
 		 * Hack for https://github.com/owncloud/core/issues/22587
431 431
 		 * We check the permissions via webdav. But the permissions of the mount point
432 432
 		 * do not equal the share permissions. Here we fix that for federated mounts.
433 433
 		 */
434
-		if ($path->getStorage()->instanceOfStorage(Storage::class)) {
435
-			$permissions &= ~($permissions & ~$path->getPermissions());
436
-		}
437
-
438
-		if ($shareType === Share::SHARE_TYPE_USER) {
439
-			// Valid user is required to share
440
-			if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
441
-				throw new OCSNotFoundException($this->l->t('Please specify a valid user'));
442
-			}
443
-			$share->setSharedWith($shareWith);
444
-			$share->setPermissions($permissions);
445
-		} else if ($shareType === Share::SHARE_TYPE_GROUP) {
446
-			if (!$this->shareManager->allowGroupSharing()) {
447
-				throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
448
-			}
449
-
450
-			// Valid group is required to share
451
-			if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
452
-				throw new OCSNotFoundException($this->l->t('Please specify a valid group'));
453
-			}
454
-			$share->setSharedWith($shareWith);
455
-			$share->setPermissions($permissions);
456
-		} else if ($shareType === Share::SHARE_TYPE_LINK) {
457
-			//Can we even share links?
458
-			if (!$this->shareManager->shareApiAllowLinks()) {
459
-				throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
460
-			}
461
-
462
-			if ($publicUpload === 'true') {
463
-				// Check if public upload is allowed
464
-				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
465
-					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
466
-				}
467
-
468
-				// Public upload can only be set for folders
469
-				if ($path instanceof \OCP\Files\File) {
470
-					throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders'));
471
-				}
472
-
473
-				$share->setPermissions(
474
-					Constants::PERMISSION_READ |
475
-					Constants::PERMISSION_CREATE |
476
-					Constants::PERMISSION_UPDATE |
477
-					Constants::PERMISSION_DELETE
478
-				);
479
-			} else {
480
-				$share->setPermissions(Constants::PERMISSION_READ);
481
-			}
482
-
483
-			// Set password
484
-			if ($password !== '') {
485
-				$share->setPassword($password);
486
-			}
487
-
488
-
489
-			if (!empty($label)) {
490
-				$share->setLabel($label);
491
-			}
492
-
493
-			if ($sendPasswordByTalk === 'true') {
494
-				if (!$this->appManager->isEnabledForUser('spreed')) {
495
-					throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
496
-				}
497
-
498
-				$share->setSendPasswordByTalk(true);
499
-			}
500
-
501
-			//Expire date
502
-			if ($expireDate !== '') {
503
-				try {
504
-					$expireDate = $this->parseDate($expireDate);
505
-					$share->setExpirationDate($expireDate);
506
-				} catch (\Exception $e) {
507
-					throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
508
-				}
509
-			}
510
-
511
-		} else if ($shareType === Share::SHARE_TYPE_REMOTE) {
512
-			if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
513
-				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
514
-			}
515
-
516
-			$share->setSharedWith($shareWith);
517
-			$share->setPermissions($permissions);
518
-		}  else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
519
-			if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
520
-				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
521
-			}
522
-
523
-			$share->setSharedWith($shareWith);
524
-			$share->setPermissions($permissions);
525
-		} else if ($shareType === Share::SHARE_TYPE_EMAIL) {
526
-			if ($share->getNodeType() === 'file') {
527
-				$share->setPermissions(Constants::PERMISSION_READ);
528
-			} else {
529
-				$share->setPermissions($permissions);
530
-			}
531
-			$share->setSharedWith($shareWith);
532
-
533
-			if ($sendPasswordByTalk === 'true') {
534
-				if (!$this->appManager->isEnabledForUser('spreed')) {
535
-					throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
536
-				}
537
-
538
-				$share->setSendPasswordByTalk(true);
539
-			}
540
-		} else if ($shareType === Share::SHARE_TYPE_CIRCLE) {
541
-			if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
542
-				throw new OCSNotFoundException($this->l->t('You cannot share to a Circle if the app is not enabled'));
543
-			}
544
-
545
-			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($shareWith);
546
-
547
-			// Valid circle is required to share
548
-			if ($circle === null) {
549
-				throw new OCSNotFoundException($this->l->t('Please specify a valid circle'));
550
-			}
551
-			$share->setSharedWith($shareWith);
552
-			$share->setPermissions($permissions);
553
-		} else if ($shareType === Share::SHARE_TYPE_ROOM) {
554
-			try {
555
-				$this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate);
556
-			} catch (QueryException $e) {
557
-				throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
558
-			}
559
-		} else {
560
-			throw new OCSBadRequestException($this->l->t('Unknown share type'));
561
-		}
562
-
563
-		$share->setShareType($shareType);
564
-		$share->setSharedBy($this->currentUser);
565
-
566
-		try {
567
-			$share = $this->shareManager->createShare($share);
568
-		} catch (GenericShareException $e) {
569
-			$code = $e->getCode() === 0 ? 403 : $e->getCode();
570
-			throw new OCSException($e->getHint(), $code);
571
-		} catch (\Exception $e) {
572
-			throw new OCSForbiddenException($e->getMessage(), $e);
573
-		}
574
-
575
-		$output = $this->formatShare($share);
576
-
577
-		return new DataResponse($output);
578
-	}
579
-
580
-	/**
581
-	 * @param \OCP\Files\File|\OCP\Files\Folder $node
582
-	 * @param boolean $includeTags
583
-	 * @return DataResponse
584
-	 */
585
-	private function getSharedWithMe($node = null, bool $includeTags): DataResponse {
586
-
587
-		$userShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $node, -1, 0);
588
-		$groupShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $node, -1, 0);
589
-		$circleShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_CIRCLE, $node, -1, 0);
590
-		$roomShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $node, -1, 0);
591
-
592
-		$shares = array_merge($userShares, $groupShares, $circleShares, $roomShares);
593
-
594
-		$shares = array_filter($shares, function (IShare $share) {
595
-			return $share->getShareOwner() !== $this->currentUser;
596
-		});
597
-
598
-		$formatted = [];
599
-		foreach ($shares as $share) {
600
-			if ($this->canAccessShare($share)) {
601
-				try {
602
-					$formatted[] = $this->formatShare($share);
603
-				} catch (NotFoundException $e) {
604
-					// Ignore this share
605
-				}
606
-			}
607
-		}
608
-
609
-		if ($includeTags) {
610
-			$formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
611
-		}
612
-
613
-		return new DataResponse($formatted);
614
-	}
615
-
616
-	/**
617
-	 * @param \OCP\Files\Folder $folder
618
-	 * @return DataResponse
619
-	 * @throws OCSBadRequestException
620
-	 */
621
-	private function getSharesInDir(Node $folder): DataResponse {
622
-		if (!($folder instanceof \OCP\Files\Folder)) {
623
-			throw new OCSBadRequestException($this->l->t('Not a directory'));
624
-		}
625
-
626
-		$nodes = $folder->getDirectoryListing();
627
-		/** @var \OCP\Share\IShare[] $shares */
628
-		$shares = [];
629
-		foreach ($nodes as $node) {
630
-
631
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, true, -1, 0));
632
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, true, -1, 0));
633
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, true, -1, 0));
634
-			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
635
-				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, true, -1, 0));
636
-			}
637
-			if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
638
-				$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, true, -1, 0));
639
-			}
640
-			$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, true, -1, 0));
641
-		}
642
-
643
-		$formatted = $miniFormatted = [];
644
-		$resharingRight = false;
645
-		$known = [];
646
-		foreach ($shares as $share) {
647
-			if (in_array($share->getId(), $known) || $share->getSharedWith() === $this->currentUser) {
648
-				continue;
649
-			}
650
-
651
-			try {
652
-				$format = $this->formatShare($share);
653
-
654
-				$known[] = $share->getId();
655
-				$formatted[] = $format;
656
-				if ($share->getSharedBy() === $this->currentUser) {
657
-					$miniFormatted[] = $format;
658
-				}
659
-				if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $folder)) {
660
-					$resharingRight = true;
661
-				}
662
-			} catch (\Exception $e) {
663
-				//Ignore this share
664
-			}
665
-		}
666
-
667
-		if (!$resharingRight) {
668
-			$formatted = $miniFormatted;
669
-		}
670
-
671
-		return new DataResponse($formatted);
672
-	}
673
-
674
-	/**
675
-	 * The getShares function.
676
-	 *
677
-	 * @NoAdminRequired
678
-	 *
679
-	 * @param string $shared_with_me
680
-	 * @param string $reshares
681
-	 * @param string $subfiles
682
-	 * @param string $path
683
-	 *
684
-	 * - Get shares by the current user
685
-	 * - Get shares by the current user and reshares (?reshares=true)
686
-	 * - Get shares with the current user (?shared_with_me=true)
687
-	 * - Get shares for a specific path (?path=...)
688
-	 * - Get all shares in a folder (?subfiles=true&path=..)
689
-	 *
690
-	 * @return DataResponse
691
-	 * @throws OCSNotFoundException
692
-	 */
693
-	public function getShares(
694
-		string $shared_with_me = 'false',
695
-		string $reshares = 'false',
696
-		string $subfiles = 'false',
697
-		string $path = null,
698
-		string $include_tags = 'false'
699
-	): DataResponse {
700
-
701
-		if ($path !== null) {
702
-			$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
703
-			try {
704
-				$path = $userFolder->get($path);
705
-				$this->lock($path);
706
-			} catch (\OCP\Files\NotFoundException $e) {
707
-				throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
708
-			} catch (LockedException $e) {
709
-				throw new OCSNotFoundException($this->l->t('Could not lock path'));
710
-			}
711
-		}
712
-
713
-		$include_tags = $include_tags === 'true';
714
-
715
-		if ($shared_with_me === 'true') {
716
-			$result = $this->getSharedWithMe($path, $include_tags);
717
-			return $result;
718
-		}
719
-
720
-		if ($subfiles === 'true') {
721
-			$result = $this->getSharesInDir($path);
722
-			return $result;
723
-		}
724
-
725
-		if ($reshares === 'true') {
726
-			$reshares = true;
727
-		} else {
728
-			$reshares = false;
729
-		}
730
-
731
-		// Get all shares
732
-		$userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
733
-		$groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
734
-		$linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
735
-		if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
736
-			$mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
737
-		} else {
738
-			$mailShares = [];
739
-		}
740
-		if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
741
-			$circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0);
742
-		} else {
743
-			$circleShares = [];
744
-		}
745
-		$roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0);
746
-
747
-		$shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares);
748
-
749
-		if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
750
-			$federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
751
-			$shares = array_merge($shares, $federatedShares);
752
-		}
753
-
754
-		if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
755
-			$federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
756
-			$shares = array_merge($shares, $federatedShares);
757
-		}
758
-
759
-		$formatted = $miniFormatted = [];
760
-		$resharingRight = false;
761
-		foreach ($shares as $share) {
762
-			/** @var IShare $share */
763
-			try {
764
-				$format = $this->formatShare($share, $path);
765
-				$formatted[] = $format;
766
-				if ($share->getSharedBy() === $this->currentUser) {
767
-					$miniFormatted[] = $format;
768
-				}
769
-
770
-				if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $path)) {
771
-					$resharingRight = true;
772
-				}
773
-			} catch (\Exception $e) {
774
-				//Ignore share
775
-			}
776
-		}
777
-
778
-		if (!$resharingRight) {
779
-			$formatted = $miniFormatted;
780
-		}
781
-
782
-		if ($include_tags) {
783
-			$formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
784
-		}
785
-
786
-		return new DataResponse($formatted);
787
-	}
788
-
789
-	/**
790
-	 * @NoAdminRequired
791
-	 *
792
-	 * @param string $id
793
-	 * @param int $permissions
794
-	 * @param string $password
795
-	 * @param string $sendPasswordByTalk
796
-	 * @param string $publicUpload
797
-	 * @param string $expireDate
798
-	 * @param string $note
799
-	 * @param string $label
800
-	 * @param string $hideDownload
801
-	 * @return DataResponse
802
-	 * @throws LockedException
803
-	 * @throws NotFoundException
804
-	 * @throws OCSBadRequestException
805
-	 * @throws OCSForbiddenException
806
-	 * @throws OCSNotFoundException
807
-	 */
808
-	public function updateShare(
809
-		string $id,
810
-		int $permissions = null,
811
-		string $password = null,
812
-		string $sendPasswordByTalk = null,
813
-		string $publicUpload = null,
814
-		string $expireDate = null,
815
-		string $note = null,
816
-		string $label = null,
817
-		string $hideDownload = null
818
-	): DataResponse {
819
-		try {
820
-			$share = $this->getShareById($id);
821
-		} catch (ShareNotFound $e) {
822
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
823
-		}
824
-
825
-		$this->lock($share->getNode());
826
-
827
-		if (!$this->canAccessShare($share, false)) {
828
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
829
-		}
830
-
831
-		if ($share->getShareOwner() !== $this->currentUser && $share->getSharedBy() !== $this->currentUser) {
832
-			throw new OCSForbiddenException('You are not allowed to edit incoming shares');
833
-		}
834
-
835
-		if ($permissions === null &&
836
-			$password === null &&
837
-			$sendPasswordByTalk === null &&
838
-			$publicUpload === null &&
839
-			$expireDate === null &&
840
-			$note === null &&
841
-			$label === null &&
842
-			$hideDownload === null
843
-		) {
844
-			throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
845
-		}
846
-
847
-		if($note !== null) {
848
-			$share->setNote($note);
849
-		}
850
-
851
-		/*
434
+        if ($path->getStorage()->instanceOfStorage(Storage::class)) {
435
+            $permissions &= ~($permissions & ~$path->getPermissions());
436
+        }
437
+
438
+        if ($shareType === Share::SHARE_TYPE_USER) {
439
+            // Valid user is required to share
440
+            if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
441
+                throw new OCSNotFoundException($this->l->t('Please specify a valid user'));
442
+            }
443
+            $share->setSharedWith($shareWith);
444
+            $share->setPermissions($permissions);
445
+        } else if ($shareType === Share::SHARE_TYPE_GROUP) {
446
+            if (!$this->shareManager->allowGroupSharing()) {
447
+                throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
448
+            }
449
+
450
+            // Valid group is required to share
451
+            if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
452
+                throw new OCSNotFoundException($this->l->t('Please specify a valid group'));
453
+            }
454
+            $share->setSharedWith($shareWith);
455
+            $share->setPermissions($permissions);
456
+        } else if ($shareType === Share::SHARE_TYPE_LINK) {
457
+            //Can we even share links?
458
+            if (!$this->shareManager->shareApiAllowLinks()) {
459
+                throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
460
+            }
461
+
462
+            if ($publicUpload === 'true') {
463
+                // Check if public upload is allowed
464
+                if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
465
+                    throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
466
+                }
467
+
468
+                // Public upload can only be set for folders
469
+                if ($path instanceof \OCP\Files\File) {
470
+                    throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders'));
471
+                }
472
+
473
+                $share->setPermissions(
474
+                    Constants::PERMISSION_READ |
475
+                    Constants::PERMISSION_CREATE |
476
+                    Constants::PERMISSION_UPDATE |
477
+                    Constants::PERMISSION_DELETE
478
+                );
479
+            } else {
480
+                $share->setPermissions(Constants::PERMISSION_READ);
481
+            }
482
+
483
+            // Set password
484
+            if ($password !== '') {
485
+                $share->setPassword($password);
486
+            }
487
+
488
+
489
+            if (!empty($label)) {
490
+                $share->setLabel($label);
491
+            }
492
+
493
+            if ($sendPasswordByTalk === 'true') {
494
+                if (!$this->appManager->isEnabledForUser('spreed')) {
495
+                    throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
496
+                }
497
+
498
+                $share->setSendPasswordByTalk(true);
499
+            }
500
+
501
+            //Expire date
502
+            if ($expireDate !== '') {
503
+                try {
504
+                    $expireDate = $this->parseDate($expireDate);
505
+                    $share->setExpirationDate($expireDate);
506
+                } catch (\Exception $e) {
507
+                    throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD'));
508
+                }
509
+            }
510
+
511
+        } else if ($shareType === Share::SHARE_TYPE_REMOTE) {
512
+            if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
513
+                throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
514
+            }
515
+
516
+            $share->setSharedWith($shareWith);
517
+            $share->setPermissions($permissions);
518
+        }  else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) {
519
+            if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
520
+                throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
521
+            }
522
+
523
+            $share->setSharedWith($shareWith);
524
+            $share->setPermissions($permissions);
525
+        } else if ($shareType === Share::SHARE_TYPE_EMAIL) {
526
+            if ($share->getNodeType() === 'file') {
527
+                $share->setPermissions(Constants::PERMISSION_READ);
528
+            } else {
529
+                $share->setPermissions($permissions);
530
+            }
531
+            $share->setSharedWith($shareWith);
532
+
533
+            if ($sendPasswordByTalk === 'true') {
534
+                if (!$this->appManager->isEnabledForUser('spreed')) {
535
+                    throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
536
+                }
537
+
538
+                $share->setSendPasswordByTalk(true);
539
+            }
540
+        } else if ($shareType === Share::SHARE_TYPE_CIRCLE) {
541
+            if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
542
+                throw new OCSNotFoundException($this->l->t('You cannot share to a Circle if the app is not enabled'));
543
+            }
544
+
545
+            $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($shareWith);
546
+
547
+            // Valid circle is required to share
548
+            if ($circle === null) {
549
+                throw new OCSNotFoundException($this->l->t('Please specify a valid circle'));
550
+            }
551
+            $share->setSharedWith($shareWith);
552
+            $share->setPermissions($permissions);
553
+        } else if ($shareType === Share::SHARE_TYPE_ROOM) {
554
+            try {
555
+                $this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate);
556
+            } catch (QueryException $e) {
557
+                throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
558
+            }
559
+        } else {
560
+            throw new OCSBadRequestException($this->l->t('Unknown share type'));
561
+        }
562
+
563
+        $share->setShareType($shareType);
564
+        $share->setSharedBy($this->currentUser);
565
+
566
+        try {
567
+            $share = $this->shareManager->createShare($share);
568
+        } catch (GenericShareException $e) {
569
+            $code = $e->getCode() === 0 ? 403 : $e->getCode();
570
+            throw new OCSException($e->getHint(), $code);
571
+        } catch (\Exception $e) {
572
+            throw new OCSForbiddenException($e->getMessage(), $e);
573
+        }
574
+
575
+        $output = $this->formatShare($share);
576
+
577
+        return new DataResponse($output);
578
+    }
579
+
580
+    /**
581
+     * @param \OCP\Files\File|\OCP\Files\Folder $node
582
+     * @param boolean $includeTags
583
+     * @return DataResponse
584
+     */
585
+    private function getSharedWithMe($node = null, bool $includeTags): DataResponse {
586
+
587
+        $userShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $node, -1, 0);
588
+        $groupShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $node, -1, 0);
589
+        $circleShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_CIRCLE, $node, -1, 0);
590
+        $roomShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $node, -1, 0);
591
+
592
+        $shares = array_merge($userShares, $groupShares, $circleShares, $roomShares);
593
+
594
+        $shares = array_filter($shares, function (IShare $share) {
595
+            return $share->getShareOwner() !== $this->currentUser;
596
+        });
597
+
598
+        $formatted = [];
599
+        foreach ($shares as $share) {
600
+            if ($this->canAccessShare($share)) {
601
+                try {
602
+                    $formatted[] = $this->formatShare($share);
603
+                } catch (NotFoundException $e) {
604
+                    // Ignore this share
605
+                }
606
+            }
607
+        }
608
+
609
+        if ($includeTags) {
610
+            $formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
611
+        }
612
+
613
+        return new DataResponse($formatted);
614
+    }
615
+
616
+    /**
617
+     * @param \OCP\Files\Folder $folder
618
+     * @return DataResponse
619
+     * @throws OCSBadRequestException
620
+     */
621
+    private function getSharesInDir(Node $folder): DataResponse {
622
+        if (!($folder instanceof \OCP\Files\Folder)) {
623
+            throw new OCSBadRequestException($this->l->t('Not a directory'));
624
+        }
625
+
626
+        $nodes = $folder->getDirectoryListing();
627
+        /** @var \OCP\Share\IShare[] $shares */
628
+        $shares = [];
629
+        foreach ($nodes as $node) {
630
+
631
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, true, -1, 0));
632
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, true, -1, 0));
633
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, true, -1, 0));
634
+            if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
635
+                $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, true, -1, 0));
636
+            }
637
+            if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
638
+                $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, true, -1, 0));
639
+            }
640
+            $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, true, -1, 0));
641
+        }
642
+
643
+        $formatted = $miniFormatted = [];
644
+        $resharingRight = false;
645
+        $known = [];
646
+        foreach ($shares as $share) {
647
+            if (in_array($share->getId(), $known) || $share->getSharedWith() === $this->currentUser) {
648
+                continue;
649
+            }
650
+
651
+            try {
652
+                $format = $this->formatShare($share);
653
+
654
+                $known[] = $share->getId();
655
+                $formatted[] = $format;
656
+                if ($share->getSharedBy() === $this->currentUser) {
657
+                    $miniFormatted[] = $format;
658
+                }
659
+                if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $folder)) {
660
+                    $resharingRight = true;
661
+                }
662
+            } catch (\Exception $e) {
663
+                //Ignore this share
664
+            }
665
+        }
666
+
667
+        if (!$resharingRight) {
668
+            $formatted = $miniFormatted;
669
+        }
670
+
671
+        return new DataResponse($formatted);
672
+    }
673
+
674
+    /**
675
+     * The getShares function.
676
+     *
677
+     * @NoAdminRequired
678
+     *
679
+     * @param string $shared_with_me
680
+     * @param string $reshares
681
+     * @param string $subfiles
682
+     * @param string $path
683
+     *
684
+     * - Get shares by the current user
685
+     * - Get shares by the current user and reshares (?reshares=true)
686
+     * - Get shares with the current user (?shared_with_me=true)
687
+     * - Get shares for a specific path (?path=...)
688
+     * - Get all shares in a folder (?subfiles=true&path=..)
689
+     *
690
+     * @return DataResponse
691
+     * @throws OCSNotFoundException
692
+     */
693
+    public function getShares(
694
+        string $shared_with_me = 'false',
695
+        string $reshares = 'false',
696
+        string $subfiles = 'false',
697
+        string $path = null,
698
+        string $include_tags = 'false'
699
+    ): DataResponse {
700
+
701
+        if ($path !== null) {
702
+            $userFolder = $this->rootFolder->getUserFolder($this->currentUser);
703
+            try {
704
+                $path = $userFolder->get($path);
705
+                $this->lock($path);
706
+            } catch (\OCP\Files\NotFoundException $e) {
707
+                throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist'));
708
+            } catch (LockedException $e) {
709
+                throw new OCSNotFoundException($this->l->t('Could not lock path'));
710
+            }
711
+        }
712
+
713
+        $include_tags = $include_tags === 'true';
714
+
715
+        if ($shared_with_me === 'true') {
716
+            $result = $this->getSharedWithMe($path, $include_tags);
717
+            return $result;
718
+        }
719
+
720
+        if ($subfiles === 'true') {
721
+            $result = $this->getSharesInDir($path);
722
+            return $result;
723
+        }
724
+
725
+        if ($reshares === 'true') {
726
+            $reshares = true;
727
+        } else {
728
+            $reshares = false;
729
+        }
730
+
731
+        // Get all shares
732
+        $userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0);
733
+        $groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0);
734
+        $linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0);
735
+        if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
736
+            $mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0);
737
+        } else {
738
+            $mailShares = [];
739
+        }
740
+        if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
741
+            $circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0);
742
+        } else {
743
+            $circleShares = [];
744
+        }
745
+        $roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0);
746
+
747
+        $shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares);
748
+
749
+        if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
750
+            $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
751
+            $shares = array_merge($shares, $federatedShares);
752
+        }
753
+
754
+        if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
755
+            $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
756
+            $shares = array_merge($shares, $federatedShares);
757
+        }
758
+
759
+        $formatted = $miniFormatted = [];
760
+        $resharingRight = false;
761
+        foreach ($shares as $share) {
762
+            /** @var IShare $share */
763
+            try {
764
+                $format = $this->formatShare($share, $path);
765
+                $formatted[] = $format;
766
+                if ($share->getSharedBy() === $this->currentUser) {
767
+                    $miniFormatted[] = $format;
768
+                }
769
+
770
+                if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $path)) {
771
+                    $resharingRight = true;
772
+                }
773
+            } catch (\Exception $e) {
774
+                //Ignore share
775
+            }
776
+        }
777
+
778
+        if (!$resharingRight) {
779
+            $formatted = $miniFormatted;
780
+        }
781
+
782
+        if ($include_tags) {
783
+            $formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager());
784
+        }
785
+
786
+        return new DataResponse($formatted);
787
+    }
788
+
789
+    /**
790
+     * @NoAdminRequired
791
+     *
792
+     * @param string $id
793
+     * @param int $permissions
794
+     * @param string $password
795
+     * @param string $sendPasswordByTalk
796
+     * @param string $publicUpload
797
+     * @param string $expireDate
798
+     * @param string $note
799
+     * @param string $label
800
+     * @param string $hideDownload
801
+     * @return DataResponse
802
+     * @throws LockedException
803
+     * @throws NotFoundException
804
+     * @throws OCSBadRequestException
805
+     * @throws OCSForbiddenException
806
+     * @throws OCSNotFoundException
807
+     */
808
+    public function updateShare(
809
+        string $id,
810
+        int $permissions = null,
811
+        string $password = null,
812
+        string $sendPasswordByTalk = null,
813
+        string $publicUpload = null,
814
+        string $expireDate = null,
815
+        string $note = null,
816
+        string $label = null,
817
+        string $hideDownload = null
818
+    ): DataResponse {
819
+        try {
820
+            $share = $this->getShareById($id);
821
+        } catch (ShareNotFound $e) {
822
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
823
+        }
824
+
825
+        $this->lock($share->getNode());
826
+
827
+        if (!$this->canAccessShare($share, false)) {
828
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
829
+        }
830
+
831
+        if ($share->getShareOwner() !== $this->currentUser && $share->getSharedBy() !== $this->currentUser) {
832
+            throw new OCSForbiddenException('You are not allowed to edit incoming shares');
833
+        }
834
+
835
+        if ($permissions === null &&
836
+            $password === null &&
837
+            $sendPasswordByTalk === null &&
838
+            $publicUpload === null &&
839
+            $expireDate === null &&
840
+            $note === null &&
841
+            $label === null &&
842
+            $hideDownload === null
843
+        ) {
844
+            throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
845
+        }
846
+
847
+        if($note !== null) {
848
+            $share->setNote($note);
849
+        }
850
+
851
+        /*
852 852
 		 * expirationdate, password and publicUpload only make sense for link shares
853 853
 		 */
854
-		if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
855
-
856
-			// Update hide download state
857
-			if ($hideDownload === 'true') {
858
-				$share->setHideDownload(true);
859
-			} else if ($hideDownload === 'false') {
860
-				$share->setHideDownload(false);
861
-			}
862
-
863
-			$newPermissions = null;
864
-			if ($publicUpload === 'true') {
865
-				$newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
866
-			} else if ($publicUpload === 'false') {
867
-				$newPermissions = Constants::PERMISSION_READ;
868
-			}
869
-
870
-			if ($permissions !== null) {
871
-				$newPermissions = (int)$permissions;
872
-				$newPermissions = $newPermissions & ~Constants::PERMISSION_SHARE;
873
-			}
874
-
875
-			if ($newPermissions !== null &&
876
-				!in_array($newPermissions, [
877
-					Constants::PERMISSION_READ,
878
-					Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE, // legacy
879
-					Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE, // correct
880
-					Constants::PERMISSION_CREATE, // hidden file list
881
-					Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, // allow to edit single files
882
-				], true)
883
-			) {
884
-				throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links'));
885
-			}
886
-
887
-			if (
888
-				// legacy
889
-				$newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) ||
890
-				// correct
891
-				$newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
892
-			) {
893
-				if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
894
-					throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
895
-				}
896
-
897
-				if (!($share->getNode() instanceof \OCP\Files\Folder)) {
898
-					throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
899
-				}
900
-
901
-				// normalize to correct public upload permissions
902
-				$newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
903
-			}
904
-
905
-			if ($newPermissions !== null) {
906
-				$share->setPermissions($newPermissions);
907
-				$permissions = $newPermissions;
908
-			}
909
-
910
-			if ($expireDate === '') {
911
-				$share->setExpirationDate(null);
912
-			} else if ($expireDate !== null) {
913
-				try {
914
-					$expireDate = $this->parseDate($expireDate);
915
-				} catch (\Exception $e) {
916
-					throw new OCSBadRequestException($e->getMessage(), $e);
917
-				}
918
-				$share->setExpirationDate($expireDate);
919
-			}
920
-
921
-			if ($password === '') {
922
-				$share->setPassword(null);
923
-			} else if ($password !== null) {
924
-				$share->setPassword($password);
925
-			}
926
-
927
-			if ($label !== null) {
928
-				$share->setLabel($label);
929
-			}
930
-
931
-			if ($sendPasswordByTalk === 'true') {
932
-				if (!$this->appManager->isEnabledForUser('spreed')) {
933
-					throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
934
-				}
935
-
936
-				$share->setSendPasswordByTalk(true);
937
-			} else if ($sendPasswordByTalk !== null) {
938
-				$share->setSendPasswordByTalk(false);
939
-			}
940
-		} else {
941
-			if ($permissions !== null) {
942
-				$permissions = (int)$permissions;
943
-				$share->setPermissions($permissions);
944
-			}
945
-
946
-			if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
947
-				if ($password === '') {
948
-					$share->setPassword(null);
949
-				} else if ($password !== null) {
950
-					$share->setPassword($password);
951
-				}
952
-
953
-				if ($sendPasswordByTalk === 'true') {
954
-					if (!$this->appManager->isEnabledForUser('spreed')) {
955
-						throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
956
-					}
957
-
958
-					$share->setSendPasswordByTalk(true);
959
-				} else {
960
-					$share->setSendPasswordByTalk(false);
961
-				}
962
-			}
963
-
964
-			if ($expireDate === '') {
965
-				$share->setExpirationDate(null);
966
-			} else if ($expireDate !== null) {
967
-				try {
968
-					$expireDate = $this->parseDate($expireDate);
969
-				} catch (\Exception $e) {
970
-					throw new OCSBadRequestException($e->getMessage(), $e);
971
-				}
972
-				$share->setExpirationDate($expireDate);
973
-			}
974
-		}
975
-
976
-		try {
977
-			$share = $this->shareManager->updateShare($share);
978
-		} catch (GenericShareException $e) {
979
-			$code = $e->getCode() === 0 ? 403 : $e->getCode();
980
-			throw new OCSException($e->getHint(), $code);
981
-		} catch (\Exception $e) {
982
-			throw new OCSBadRequestException($e->getMessage(), $e);
983
-		}
984
-
985
-		return new DataResponse($this->formatShare($share));
986
-	}
987
-
988
-	/**
989
-	 * @suppress PhanUndeclaredClassMethod
990
-	 */
991
-	protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool {
992
-		// A file with permissions 0 can't be accessed by us. So Don't show it
993
-		if ($share->getPermissions() === 0) {
994
-			return false;
995
-		}
996
-
997
-		// Owner of the file and the sharer of the file can always get share
998
-		if ($share->getShareOwner() === $this->currentUser ||
999
-			$share->getSharedBy() === $this->currentUser
1000
-		) {
1001
-			return true;
1002
-		}
1003
-
1004
-		// If the share is shared with you (or a group you are a member of)
1005
-		if ($share->getShareType() === Share::SHARE_TYPE_USER &&
1006
-			$share->getSharedWith() === $this->currentUser
1007
-		) {
1008
-			return true;
1009
-		}
1010
-
1011
-		if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) {
1012
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
1013
-			$user = $this->userManager->get($this->currentUser);
1014
-			if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
1015
-				return true;
1016
-			}
1017
-		}
1018
-
1019
-		if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
1020
-			// TODO: have a sanity check like above?
1021
-			return true;
1022
-		}
1023
-
1024
-		if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
1025
-			try {
1026
-				return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser);
1027
-			} catch (QueryException $e) {
1028
-				return false;
1029
-			}
1030
-		}
1031
-
1032
-		return false;
1033
-	}
1034
-
1035
-	/**
1036
-	 * Make sure that the passed date is valid ISO 8601
1037
-	 * So YYYY-MM-DD
1038
-	 * If not throw an exception
1039
-	 *
1040
-	 * @param string $expireDate
1041
-	 *
1042
-	 * @throws \Exception
1043
-	 * @return \DateTime
1044
-	 */
1045
-	private function parseDate(string $expireDate): \DateTime {
1046
-		try {
1047
-			$date = new \DateTime($expireDate);
1048
-		} catch (\Exception $e) {
1049
-			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1050
-		}
1051
-
1052
-		if ($date === false) {
1053
-			throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1054
-		}
1055
-
1056
-		$date->setTime(0, 0, 0);
1057
-
1058
-		return $date;
1059
-	}
1060
-
1061
-	/**
1062
-	 * Since we have multiple providers but the OCS Share API v1 does
1063
-	 * not support this we need to check all backends.
1064
-	 *
1065
-	 * @param string $id
1066
-	 * @return \OCP\Share\IShare
1067
-	 * @throws ShareNotFound
1068
-	 */
1069
-	private function getShareById(string $id): IShare {
1070
-		$share = null;
1071
-
1072
-		// First check if it is an internal share.
1073
-		try {
1074
-			$share = $this->shareManager->getShareById('ocinternal:' . $id, $this->currentUser);
1075
-			return $share;
1076
-		} catch (ShareNotFound $e) {
1077
-			// Do nothing, just try the other share type
1078
-		}
1079
-
1080
-
1081
-		try {
1082
-			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
1083
-				$share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser);
1084
-				return $share;
1085
-			}
1086
-		} catch (ShareNotFound $e) {
1087
-			// Do nothing, just try the other share type
1088
-		}
1089
-
1090
-		try {
1091
-			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
1092
-				$share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser);
1093
-				return $share;
1094
-			}
1095
-		} catch (ShareNotFound $e) {
1096
-			// Do nothing, just try the other share type
1097
-		}
1098
-
1099
-		try {
1100
-			$share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser);
1101
-			return $share;
1102
-		} catch (ShareNotFound $e) {
1103
-			// Do nothing, just try the other share type
1104
-		}
1105
-
1106
-		if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1107
-			throw new ShareNotFound();
1108
-		}
1109
-		$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->currentUser);
1110
-
1111
-		return $share;
1112
-	}
1113
-
1114
-	/**
1115
-	 * Lock a Node
1116
-	 *
1117
-	 * @param \OCP\Files\Node $node
1118
-	 * @throws LockedException
1119
-	 */
1120
-	private function lock(\OCP\Files\Node $node) {
1121
-		$node->lock(ILockingProvider::LOCK_SHARED);
1122
-		$this->lockedNode = $node;
1123
-	}
1124
-
1125
-	/**
1126
-	 * Cleanup the remaining locks
1127
-	 * @throws @LockedException
1128
-	 */
1129
-	public function cleanup() {
1130
-		if ($this->lockedNode !== null) {
1131
-			$this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
1132
-		}
1133
-	}
1134
-
1135
-	/**
1136
-	 * Returns the helper of ShareAPIController for room shares.
1137
-	 *
1138
-	 * If the Talk application is not enabled or the helper is not available
1139
-	 * a QueryException is thrown instead.
1140
-	 *
1141
-	 * @return \OCA\Spreed\Share\Helper\ShareAPIController
1142
-	 * @throws QueryException
1143
-	 */
1144
-	private function getRoomShareHelper() {
1145
-		if (!$this->appManager->isEnabledForUser('spreed')) {
1146
-			throw new QueryException();
1147
-		}
1148
-
1149
-		return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController');
1150
-	}
1151
-
1152
-
1153
-	/**
1154
-	 * Returns if we can find resharing rights in an IShare object for a specific user.
1155
-	 *
1156
-	 * @suppress PhanUndeclaredClassMethod
1157
-	 *
1158
-	 * @param string $userId
1159
-	 * @param IShare $share
1160
-	 * @param Node $node
1161
-	 * @return bool
1162
-	 * @throws NotFoundException
1163
-	 * @throws \OCP\Files\InvalidPathException
1164
-	 */
1165
-	private function shareProviderResharingRights(string $userId, IShare $share, $node): bool {
1166
-
1167
-		if ($share->getShareOwner() === $userId) {
1168
-			return true;
1169
-		}
1170
-
1171
-		// we check that current user have parent resharing rights on the current file
1172
-		if ($node !== null && ($node->getPermissions() & \OCP\Constants::PERMISSION_SHARE) !== 0) {
1173
-			return true;
1174
-		}
1175
-
1176
-		if ((\OCP\Constants::PERMISSION_SHARE & $share->getPermissions()) === 0) {
1177
-			return false;
1178
-		}
1179
-
1180
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() === $userId) {
1181
-			return true;
1182
-		}
1183
-
1184
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && $this->groupManager->isInGroup($userId, $share->getSharedWith())) {
1185
-			return true;
1186
-		}
1187
-
1188
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE && \OC::$server->getAppManager()->isEnabledForUser('circles') &&
1189
-			class_exists('\OCA\Circles\Api\v1\Circles')) {
1190
-			$hasCircleId = (substr($share->getSharedWith(), -1) === ']');
1191
-			$shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
1192
-			$shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
1193
-			if (is_bool($shareWithLength)) {
1194
-				$shareWithLength = -1;
1195
-			}
1196
-			$sharedWith = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
1197
-			try {
1198
-				$member = \OCA\Circles\Api\v1\Circles::getMember($sharedWith, $userId, 1);
1199
-				if ($member->getLevel() >= 4) {
1200
-					return true;
1201
-				}
1202
-				return false;
1203
-			} catch (QueryException $e) {
1204
-				return false;
1205
-			}
1206
-		}
1207
-
1208
-		return false;
1209
-	}
854
+        if ($share->getShareType() === Share::SHARE_TYPE_LINK) {
855
+
856
+            // Update hide download state
857
+            if ($hideDownload === 'true') {
858
+                $share->setHideDownload(true);
859
+            } else if ($hideDownload === 'false') {
860
+                $share->setHideDownload(false);
861
+            }
862
+
863
+            $newPermissions = null;
864
+            if ($publicUpload === 'true') {
865
+                $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
866
+            } else if ($publicUpload === 'false') {
867
+                $newPermissions = Constants::PERMISSION_READ;
868
+            }
869
+
870
+            if ($permissions !== null) {
871
+                $newPermissions = (int)$permissions;
872
+                $newPermissions = $newPermissions & ~Constants::PERMISSION_SHARE;
873
+            }
874
+
875
+            if ($newPermissions !== null &&
876
+                !in_array($newPermissions, [
877
+                    Constants::PERMISSION_READ,
878
+                    Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE, // legacy
879
+                    Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE, // correct
880
+                    Constants::PERMISSION_CREATE, // hidden file list
881
+                    Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, // allow to edit single files
882
+                ], true)
883
+            ) {
884
+                throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links'));
885
+            }
886
+
887
+            if (
888
+                // legacy
889
+                $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) ||
890
+                // correct
891
+                $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
892
+            ) {
893
+                if (!$this->shareManager->shareApiLinkAllowPublicUpload()) {
894
+                    throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
895
+                }
896
+
897
+                if (!($share->getNode() instanceof \OCP\Files\Folder)) {
898
+                    throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
899
+                }
900
+
901
+                // normalize to correct public upload permissions
902
+                $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE;
903
+            }
904
+
905
+            if ($newPermissions !== null) {
906
+                $share->setPermissions($newPermissions);
907
+                $permissions = $newPermissions;
908
+            }
909
+
910
+            if ($expireDate === '') {
911
+                $share->setExpirationDate(null);
912
+            } else if ($expireDate !== null) {
913
+                try {
914
+                    $expireDate = $this->parseDate($expireDate);
915
+                } catch (\Exception $e) {
916
+                    throw new OCSBadRequestException($e->getMessage(), $e);
917
+                }
918
+                $share->setExpirationDate($expireDate);
919
+            }
920
+
921
+            if ($password === '') {
922
+                $share->setPassword(null);
923
+            } else if ($password !== null) {
924
+                $share->setPassword($password);
925
+            }
926
+
927
+            if ($label !== null) {
928
+                $share->setLabel($label);
929
+            }
930
+
931
+            if ($sendPasswordByTalk === 'true') {
932
+                if (!$this->appManager->isEnabledForUser('spreed')) {
933
+                    throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
934
+                }
935
+
936
+                $share->setSendPasswordByTalk(true);
937
+            } else if ($sendPasswordByTalk !== null) {
938
+                $share->setSendPasswordByTalk(false);
939
+            }
940
+        } else {
941
+            if ($permissions !== null) {
942
+                $permissions = (int)$permissions;
943
+                $share->setPermissions($permissions);
944
+            }
945
+
946
+            if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) {
947
+                if ($password === '') {
948
+                    $share->setPassword(null);
949
+                } else if ($password !== null) {
950
+                    $share->setPassword($password);
951
+                }
952
+
953
+                if ($sendPasswordByTalk === 'true') {
954
+                    if (!$this->appManager->isEnabledForUser('spreed')) {
955
+                        throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled'));
956
+                    }
957
+
958
+                    $share->setSendPasswordByTalk(true);
959
+                } else {
960
+                    $share->setSendPasswordByTalk(false);
961
+                }
962
+            }
963
+
964
+            if ($expireDate === '') {
965
+                $share->setExpirationDate(null);
966
+            } else if ($expireDate !== null) {
967
+                try {
968
+                    $expireDate = $this->parseDate($expireDate);
969
+                } catch (\Exception $e) {
970
+                    throw new OCSBadRequestException($e->getMessage(), $e);
971
+                }
972
+                $share->setExpirationDate($expireDate);
973
+            }
974
+        }
975
+
976
+        try {
977
+            $share = $this->shareManager->updateShare($share);
978
+        } catch (GenericShareException $e) {
979
+            $code = $e->getCode() === 0 ? 403 : $e->getCode();
980
+            throw new OCSException($e->getHint(), $code);
981
+        } catch (\Exception $e) {
982
+            throw new OCSBadRequestException($e->getMessage(), $e);
983
+        }
984
+
985
+        return new DataResponse($this->formatShare($share));
986
+    }
987
+
988
+    /**
989
+     * @suppress PhanUndeclaredClassMethod
990
+     */
991
+    protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool {
992
+        // A file with permissions 0 can't be accessed by us. So Don't show it
993
+        if ($share->getPermissions() === 0) {
994
+            return false;
995
+        }
996
+
997
+        // Owner of the file and the sharer of the file can always get share
998
+        if ($share->getShareOwner() === $this->currentUser ||
999
+            $share->getSharedBy() === $this->currentUser
1000
+        ) {
1001
+            return true;
1002
+        }
1003
+
1004
+        // If the share is shared with you (or a group you are a member of)
1005
+        if ($share->getShareType() === Share::SHARE_TYPE_USER &&
1006
+            $share->getSharedWith() === $this->currentUser
1007
+        ) {
1008
+            return true;
1009
+        }
1010
+
1011
+        if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) {
1012
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
1013
+            $user = $this->userManager->get($this->currentUser);
1014
+            if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
1015
+                return true;
1016
+            }
1017
+        }
1018
+
1019
+        if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) {
1020
+            // TODO: have a sanity check like above?
1021
+            return true;
1022
+        }
1023
+
1024
+        if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
1025
+            try {
1026
+                return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser);
1027
+            } catch (QueryException $e) {
1028
+                return false;
1029
+            }
1030
+        }
1031
+
1032
+        return false;
1033
+    }
1034
+
1035
+    /**
1036
+     * Make sure that the passed date is valid ISO 8601
1037
+     * So YYYY-MM-DD
1038
+     * If not throw an exception
1039
+     *
1040
+     * @param string $expireDate
1041
+     *
1042
+     * @throws \Exception
1043
+     * @return \DateTime
1044
+     */
1045
+    private function parseDate(string $expireDate): \DateTime {
1046
+        try {
1047
+            $date = new \DateTime($expireDate);
1048
+        } catch (\Exception $e) {
1049
+            throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1050
+        }
1051
+
1052
+        if ($date === false) {
1053
+            throw new \Exception('Invalid date. Format must be YYYY-MM-DD');
1054
+        }
1055
+
1056
+        $date->setTime(0, 0, 0);
1057
+
1058
+        return $date;
1059
+    }
1060
+
1061
+    /**
1062
+     * Since we have multiple providers but the OCS Share API v1 does
1063
+     * not support this we need to check all backends.
1064
+     *
1065
+     * @param string $id
1066
+     * @return \OCP\Share\IShare
1067
+     * @throws ShareNotFound
1068
+     */
1069
+    private function getShareById(string $id): IShare {
1070
+        $share = null;
1071
+
1072
+        // First check if it is an internal share.
1073
+        try {
1074
+            $share = $this->shareManager->getShareById('ocinternal:' . $id, $this->currentUser);
1075
+            return $share;
1076
+        } catch (ShareNotFound $e) {
1077
+            // Do nothing, just try the other share type
1078
+        }
1079
+
1080
+
1081
+        try {
1082
+            if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) {
1083
+                $share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser);
1084
+                return $share;
1085
+            }
1086
+        } catch (ShareNotFound $e) {
1087
+            // Do nothing, just try the other share type
1088
+        }
1089
+
1090
+        try {
1091
+            if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
1092
+                $share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser);
1093
+                return $share;
1094
+            }
1095
+        } catch (ShareNotFound $e) {
1096
+            // Do nothing, just try the other share type
1097
+        }
1098
+
1099
+        try {
1100
+            $share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser);
1101
+            return $share;
1102
+        } catch (ShareNotFound $e) {
1103
+            // Do nothing, just try the other share type
1104
+        }
1105
+
1106
+        if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1107
+            throw new ShareNotFound();
1108
+        }
1109
+        $share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->currentUser);
1110
+
1111
+        return $share;
1112
+    }
1113
+
1114
+    /**
1115
+     * Lock a Node
1116
+     *
1117
+     * @param \OCP\Files\Node $node
1118
+     * @throws LockedException
1119
+     */
1120
+    private function lock(\OCP\Files\Node $node) {
1121
+        $node->lock(ILockingProvider::LOCK_SHARED);
1122
+        $this->lockedNode = $node;
1123
+    }
1124
+
1125
+    /**
1126
+     * Cleanup the remaining locks
1127
+     * @throws @LockedException
1128
+     */
1129
+    public function cleanup() {
1130
+        if ($this->lockedNode !== null) {
1131
+            $this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
1132
+        }
1133
+    }
1134
+
1135
+    /**
1136
+     * Returns the helper of ShareAPIController for room shares.
1137
+     *
1138
+     * If the Talk application is not enabled or the helper is not available
1139
+     * a QueryException is thrown instead.
1140
+     *
1141
+     * @return \OCA\Spreed\Share\Helper\ShareAPIController
1142
+     * @throws QueryException
1143
+     */
1144
+    private function getRoomShareHelper() {
1145
+        if (!$this->appManager->isEnabledForUser('spreed')) {
1146
+            throw new QueryException();
1147
+        }
1148
+
1149
+        return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController');
1150
+    }
1151
+
1152
+
1153
+    /**
1154
+     * Returns if we can find resharing rights in an IShare object for a specific user.
1155
+     *
1156
+     * @suppress PhanUndeclaredClassMethod
1157
+     *
1158
+     * @param string $userId
1159
+     * @param IShare $share
1160
+     * @param Node $node
1161
+     * @return bool
1162
+     * @throws NotFoundException
1163
+     * @throws \OCP\Files\InvalidPathException
1164
+     */
1165
+    private function shareProviderResharingRights(string $userId, IShare $share, $node): bool {
1166
+
1167
+        if ($share->getShareOwner() === $userId) {
1168
+            return true;
1169
+        }
1170
+
1171
+        // we check that current user have parent resharing rights on the current file
1172
+        if ($node !== null && ($node->getPermissions() & \OCP\Constants::PERMISSION_SHARE) !== 0) {
1173
+            return true;
1174
+        }
1175
+
1176
+        if ((\OCP\Constants::PERMISSION_SHARE & $share->getPermissions()) === 0) {
1177
+            return false;
1178
+        }
1179
+
1180
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() === $userId) {
1181
+            return true;
1182
+        }
1183
+
1184
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && $this->groupManager->isInGroup($userId, $share->getSharedWith())) {
1185
+            return true;
1186
+        }
1187
+
1188
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE && \OC::$server->getAppManager()->isEnabledForUser('circles') &&
1189
+            class_exists('\OCA\Circles\Api\v1\Circles')) {
1190
+            $hasCircleId = (substr($share->getSharedWith(), -1) === ']');
1191
+            $shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
1192
+            $shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
1193
+            if (is_bool($shareWithLength)) {
1194
+                $shareWithLength = -1;
1195
+            }
1196
+            $sharedWith = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
1197
+            try {
1198
+                $member = \OCA\Circles\Api\v1\Circles::getMember($sharedWith, $userId, 1);
1199
+                if ($member->getLevel() >= 4) {
1200
+                    return true;
1201
+                }
1202
+                return false;
1203
+            } catch (QueryException $e) {
1204
+                return false;
1205
+            }
1206
+        }
1207
+
1208
+        return false;
1209
+    }
1210 1210
 
1211 1211
 }
Please login to merge, or discard this patch.