Passed
Push — master ( 80e12c...127af0 )
by Julius
15:15 queued 16s
created
lib/private/Share20/Manager.php 1 patch
Indentation   +1984 added lines, -1984 removed lines patch added patch discarded remove patch
@@ -82,2009 +82,2009 @@
 block discarded – undo
82 82
  * This class is the communication hub for all sharing related operations.
83 83
  */
84 84
 class Manager implements IManager {
85
-	/** @var IProviderFactory */
86
-	private $factory;
87
-	private LoggerInterface $logger;
88
-	/** @var IConfig */
89
-	private $config;
90
-	/** @var ISecureRandom */
91
-	private $secureRandom;
92
-	/** @var IHasher */
93
-	private $hasher;
94
-	/** @var IMountManager */
95
-	private $mountManager;
96
-	/** @var IGroupManager */
97
-	private $groupManager;
98
-	/** @var IL10N */
99
-	private $l;
100
-	/** @var IFactory */
101
-	private $l10nFactory;
102
-	/** @var IUserManager */
103
-	private $userManager;
104
-	/** @var IRootFolder */
105
-	private $rootFolder;
106
-	/** @var CappedMemoryCache */
107
-	private $sharingDisabledForUsersCache;
108
-	/** @var EventDispatcherInterface */
109
-	private $legacyDispatcher;
110
-	/** @var LegacyHooks */
111
-	private $legacyHooks;
112
-	/** @var IMailer */
113
-	private $mailer;
114
-	/** @var IURLGenerator */
115
-	private $urlGenerator;
116
-	/** @var \OC_Defaults */
117
-	private $defaults;
118
-	/** @var IEventDispatcher */
119
-	private $dispatcher;
120
-	/** @var IUserSession */
121
-	private $userSession;
122
-	/** @var KnownUserService */
123
-	private $knownUserService;
124
-
125
-	public function __construct(
126
-		LoggerInterface $logger,
127
-		IConfig $config,
128
-		ISecureRandom $secureRandom,
129
-		IHasher $hasher,
130
-		IMountManager $mountManager,
131
-		IGroupManager $groupManager,
132
-		IL10N $l,
133
-		IFactory $l10nFactory,
134
-		IProviderFactory $factory,
135
-		IUserManager $userManager,
136
-		IRootFolder $rootFolder,
137
-		EventDispatcherInterface $legacyDispatcher,
138
-		IMailer $mailer,
139
-		IURLGenerator $urlGenerator,
140
-		\OC_Defaults $defaults,
141
-		IEventDispatcher $dispatcher,
142
-		IUserSession $userSession,
143
-		KnownUserService $knownUserService
144
-	) {
145
-		$this->logger = $logger;
146
-		$this->config = $config;
147
-		$this->secureRandom = $secureRandom;
148
-		$this->hasher = $hasher;
149
-		$this->mountManager = $mountManager;
150
-		$this->groupManager = $groupManager;
151
-		$this->l = $l;
152
-		$this->l10nFactory = $l10nFactory;
153
-		$this->factory = $factory;
154
-		$this->userManager = $userManager;
155
-		$this->rootFolder = $rootFolder;
156
-		$this->legacyDispatcher = $legacyDispatcher;
157
-		$this->sharingDisabledForUsersCache = new CappedMemoryCache();
158
-		// The constructor of LegacyHooks registers the listeners of share events
159
-		// do not remove if those are not properly migrated
160
-		$this->legacyHooks = new LegacyHooks($this->legacyDispatcher);
161
-		$this->mailer = $mailer;
162
-		$this->urlGenerator = $urlGenerator;
163
-		$this->defaults = $defaults;
164
-		$this->dispatcher = $dispatcher;
165
-		$this->userSession = $userSession;
166
-		$this->knownUserService = $knownUserService;
167
-	}
168
-
169
-	/**
170
-	 * Convert from a full share id to a tuple (providerId, shareId)
171
-	 *
172
-	 * @param string $id
173
-	 * @return string[]
174
-	 */
175
-	private function splitFullId($id) {
176
-		return explode(':', $id, 2);
177
-	}
178
-
179
-	/**
180
-	 * Verify if a password meets all requirements
181
-	 *
182
-	 * @param string $password
183
-	 * @throws \Exception
184
-	 */
185
-	protected function verifyPassword($password) {
186
-		if ($password === null) {
187
-			// No password is set, check if this is allowed.
188
-			if ($this->shareApiLinkEnforcePassword()) {
189
-				throw new \InvalidArgumentException('Passwords are enforced for link and mail shares');
190
-			}
191
-
192
-			return;
193
-		}
194
-
195
-		// Let others verify the password
196
-		try {
197
-			$this->legacyDispatcher->dispatch(new ValidatePasswordPolicyEvent($password));
198
-		} catch (HintException $e) {
199
-			throw new \Exception($e->getHint());
200
-		}
201
-	}
202
-
203
-	/**
204
-	 * Check for generic requirements before creating a share
205
-	 *
206
-	 * @param IShare $share
207
-	 * @throws \InvalidArgumentException
208
-	 * @throws GenericShareException
209
-	 *
210
-	 * @suppress PhanUndeclaredClassMethod
211
-	 */
212
-	protected function generalCreateChecks(IShare $share) {
213
-		if ($share->getShareType() === IShare::TYPE_USER) {
214
-			// We expect a valid user as sharedWith for user shares
215
-			if (!$this->userManager->userExists($share->getSharedWith())) {
216
-				throw new \InvalidArgumentException('SharedWith is not a valid user');
217
-			}
218
-		} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
219
-			// We expect a valid group as sharedWith for group shares
220
-			if (!$this->groupManager->groupExists($share->getSharedWith())) {
221
-				throw new \InvalidArgumentException('SharedWith is not a valid group');
222
-			}
223
-		} elseif ($share->getShareType() === IShare::TYPE_LINK) {
224
-			// No check for TYPE_EMAIL here as we have a recipient for them
225
-			if ($share->getSharedWith() !== null) {
226
-				throw new \InvalidArgumentException('SharedWith should be empty');
227
-			}
228
-		} elseif ($share->getShareType() === IShare::TYPE_EMAIL) {
229
-			if ($share->getSharedWith() === null) {
230
-				throw new \InvalidArgumentException('SharedWith should not be empty');
231
-			}
232
-		} elseif ($share->getShareType() === IShare::TYPE_REMOTE) {
233
-			if ($share->getSharedWith() === null) {
234
-				throw new \InvalidArgumentException('SharedWith should not be empty');
235
-			}
236
-		} elseif ($share->getShareType() === IShare::TYPE_REMOTE_GROUP) {
237
-			if ($share->getSharedWith() === null) {
238
-				throw new \InvalidArgumentException('SharedWith should not be empty');
239
-			}
240
-		} elseif ($share->getShareType() === IShare::TYPE_CIRCLE) {
241
-			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($share->getSharedWith());
242
-			if ($circle === null) {
243
-				throw new \InvalidArgumentException('SharedWith is not a valid circle');
244
-			}
245
-		} elseif ($share->getShareType() === IShare::TYPE_ROOM) {
246
-		} elseif ($share->getShareType() === IShare::TYPE_DECK) {
247
-		} elseif ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
248
-		} else {
249
-			// We cannot handle other types yet
250
-			throw new \InvalidArgumentException('unknown share type');
251
-		}
252
-
253
-		// Verify the initiator of the share is set
254
-		if ($share->getSharedBy() === null) {
255
-			throw new \InvalidArgumentException('SharedBy should be set');
256
-		}
257
-
258
-		// Cannot share with yourself
259
-		if ($share->getShareType() === IShare::TYPE_USER &&
260
-			$share->getSharedWith() === $share->getSharedBy()) {
261
-			throw new \InvalidArgumentException('Cannot share with yourself');
262
-		}
263
-
264
-		// The path should be set
265
-		if ($share->getNode() === null) {
266
-			throw new \InvalidArgumentException('Path should be set');
267
-		}
268
-
269
-		// And it should be a file or a folder
270
-		if (!($share->getNode() instanceof \OCP\Files\File) &&
271
-			!($share->getNode() instanceof \OCP\Files\Folder)) {
272
-			throw new \InvalidArgumentException('Path should be either a file or a folder');
273
-		}
274
-
275
-		// And you cannot share your rootfolder
276
-		if ($this->userManager->userExists($share->getSharedBy())) {
277
-			$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
278
-		} else {
279
-			$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
280
-		}
281
-		if ($userFolder->getId() === $share->getNode()->getId()) {
282
-			throw new \InvalidArgumentException('You cannot share your root folder');
283
-		}
284
-
285
-		// Check if we actually have share permissions
286
-		if (!$share->getNode()->isShareable()) {
287
-			$message_t = $this->l->t('You are not allowed to share %s', [$share->getNode()->getName()]);
288
-			throw new GenericShareException($message_t, $message_t, 404);
289
-		}
290
-
291
-		// Permissions should be set
292
-		if ($share->getPermissions() === null) {
293
-			throw new \InvalidArgumentException('A share requires permissions');
294
-		}
295
-
296
-		$isFederatedShare = $share->getNode()->getStorage()->instanceOfStorage('\OCA\Files_Sharing\External\Storage');
297
-		$permissions = 0;
298
-
299
-		if (!$isFederatedShare && $share->getNode()->getOwner() && $share->getNode()->getOwner()->getUID() !== $share->getSharedBy()) {
300
-			$userMounts = array_filter($userFolder->getById($share->getNode()->getId()), function ($mount) {
301
-				// We need to filter since there might be other mountpoints that contain the file
302
-				// e.g. if the user has access to the same external storage that the file is originating from
303
-				return $mount->getStorage()->instanceOfStorage(ISharedStorage::class);
304
-			});
305
-			$userMount = array_shift($userMounts);
306
-			if ($userMount === null) {
307
-				throw new GenericShareException('Could not get proper share mount for ' . $share->getNode()->getId() . '. Failing since else the next calls are called with null');
308
-			}
309
-			$mount = $userMount->getMountPoint();
310
-			// When it's a reshare use the parent share permissions as maximum
311
-			$userMountPointId = $mount->getStorageRootId();
312
-			$userMountPoints = $userFolder->getById($userMountPointId);
313
-			$userMountPoint = array_shift($userMountPoints);
314
-
315
-			if ($userMountPoint === null) {
316
-				throw new GenericShareException('Could not get proper user mount for ' . $userMountPointId . '. Failing since else the next calls are called with null');
317
-			}
318
-
319
-			/* Check if this is an incoming share */
320
-			$incomingShares = $this->getSharedWith($share->getSharedBy(), IShare::TYPE_USER, $userMountPoint, -1, 0);
321
-			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), IShare::TYPE_GROUP, $userMountPoint, -1, 0));
322
-			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), IShare::TYPE_CIRCLE, $userMountPoint, -1, 0));
323
-			$incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), IShare::TYPE_ROOM, $userMountPoint, -1, 0));
324
-
325
-			/** @var IShare[] $incomingShares */
326
-			if (!empty($incomingShares)) {
327
-				foreach ($incomingShares as $incomingShare) {
328
-					$permissions |= $incomingShare->getPermissions();
329
-				}
330
-			}
331
-		} else {
332
-			/*
85
+    /** @var IProviderFactory */
86
+    private $factory;
87
+    private LoggerInterface $logger;
88
+    /** @var IConfig */
89
+    private $config;
90
+    /** @var ISecureRandom */
91
+    private $secureRandom;
92
+    /** @var IHasher */
93
+    private $hasher;
94
+    /** @var IMountManager */
95
+    private $mountManager;
96
+    /** @var IGroupManager */
97
+    private $groupManager;
98
+    /** @var IL10N */
99
+    private $l;
100
+    /** @var IFactory */
101
+    private $l10nFactory;
102
+    /** @var IUserManager */
103
+    private $userManager;
104
+    /** @var IRootFolder */
105
+    private $rootFolder;
106
+    /** @var CappedMemoryCache */
107
+    private $sharingDisabledForUsersCache;
108
+    /** @var EventDispatcherInterface */
109
+    private $legacyDispatcher;
110
+    /** @var LegacyHooks */
111
+    private $legacyHooks;
112
+    /** @var IMailer */
113
+    private $mailer;
114
+    /** @var IURLGenerator */
115
+    private $urlGenerator;
116
+    /** @var \OC_Defaults */
117
+    private $defaults;
118
+    /** @var IEventDispatcher */
119
+    private $dispatcher;
120
+    /** @var IUserSession */
121
+    private $userSession;
122
+    /** @var KnownUserService */
123
+    private $knownUserService;
124
+
125
+    public function __construct(
126
+        LoggerInterface $logger,
127
+        IConfig $config,
128
+        ISecureRandom $secureRandom,
129
+        IHasher $hasher,
130
+        IMountManager $mountManager,
131
+        IGroupManager $groupManager,
132
+        IL10N $l,
133
+        IFactory $l10nFactory,
134
+        IProviderFactory $factory,
135
+        IUserManager $userManager,
136
+        IRootFolder $rootFolder,
137
+        EventDispatcherInterface $legacyDispatcher,
138
+        IMailer $mailer,
139
+        IURLGenerator $urlGenerator,
140
+        \OC_Defaults $defaults,
141
+        IEventDispatcher $dispatcher,
142
+        IUserSession $userSession,
143
+        KnownUserService $knownUserService
144
+    ) {
145
+        $this->logger = $logger;
146
+        $this->config = $config;
147
+        $this->secureRandom = $secureRandom;
148
+        $this->hasher = $hasher;
149
+        $this->mountManager = $mountManager;
150
+        $this->groupManager = $groupManager;
151
+        $this->l = $l;
152
+        $this->l10nFactory = $l10nFactory;
153
+        $this->factory = $factory;
154
+        $this->userManager = $userManager;
155
+        $this->rootFolder = $rootFolder;
156
+        $this->legacyDispatcher = $legacyDispatcher;
157
+        $this->sharingDisabledForUsersCache = new CappedMemoryCache();
158
+        // The constructor of LegacyHooks registers the listeners of share events
159
+        // do not remove if those are not properly migrated
160
+        $this->legacyHooks = new LegacyHooks($this->legacyDispatcher);
161
+        $this->mailer = $mailer;
162
+        $this->urlGenerator = $urlGenerator;
163
+        $this->defaults = $defaults;
164
+        $this->dispatcher = $dispatcher;
165
+        $this->userSession = $userSession;
166
+        $this->knownUserService = $knownUserService;
167
+    }
168
+
169
+    /**
170
+     * Convert from a full share id to a tuple (providerId, shareId)
171
+     *
172
+     * @param string $id
173
+     * @return string[]
174
+     */
175
+    private function splitFullId($id) {
176
+        return explode(':', $id, 2);
177
+    }
178
+
179
+    /**
180
+     * Verify if a password meets all requirements
181
+     *
182
+     * @param string $password
183
+     * @throws \Exception
184
+     */
185
+    protected function verifyPassword($password) {
186
+        if ($password === null) {
187
+            // No password is set, check if this is allowed.
188
+            if ($this->shareApiLinkEnforcePassword()) {
189
+                throw new \InvalidArgumentException('Passwords are enforced for link and mail shares');
190
+            }
191
+
192
+            return;
193
+        }
194
+
195
+        // Let others verify the password
196
+        try {
197
+            $this->legacyDispatcher->dispatch(new ValidatePasswordPolicyEvent($password));
198
+        } catch (HintException $e) {
199
+            throw new \Exception($e->getHint());
200
+        }
201
+    }
202
+
203
+    /**
204
+     * Check for generic requirements before creating a share
205
+     *
206
+     * @param IShare $share
207
+     * @throws \InvalidArgumentException
208
+     * @throws GenericShareException
209
+     *
210
+     * @suppress PhanUndeclaredClassMethod
211
+     */
212
+    protected function generalCreateChecks(IShare $share) {
213
+        if ($share->getShareType() === IShare::TYPE_USER) {
214
+            // We expect a valid user as sharedWith for user shares
215
+            if (!$this->userManager->userExists($share->getSharedWith())) {
216
+                throw new \InvalidArgumentException('SharedWith is not a valid user');
217
+            }
218
+        } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
219
+            // We expect a valid group as sharedWith for group shares
220
+            if (!$this->groupManager->groupExists($share->getSharedWith())) {
221
+                throw new \InvalidArgumentException('SharedWith is not a valid group');
222
+            }
223
+        } elseif ($share->getShareType() === IShare::TYPE_LINK) {
224
+            // No check for TYPE_EMAIL here as we have a recipient for them
225
+            if ($share->getSharedWith() !== null) {
226
+                throw new \InvalidArgumentException('SharedWith should be empty');
227
+            }
228
+        } elseif ($share->getShareType() === IShare::TYPE_EMAIL) {
229
+            if ($share->getSharedWith() === null) {
230
+                throw new \InvalidArgumentException('SharedWith should not be empty');
231
+            }
232
+        } elseif ($share->getShareType() === IShare::TYPE_REMOTE) {
233
+            if ($share->getSharedWith() === null) {
234
+                throw new \InvalidArgumentException('SharedWith should not be empty');
235
+            }
236
+        } elseif ($share->getShareType() === IShare::TYPE_REMOTE_GROUP) {
237
+            if ($share->getSharedWith() === null) {
238
+                throw new \InvalidArgumentException('SharedWith should not be empty');
239
+            }
240
+        } elseif ($share->getShareType() === IShare::TYPE_CIRCLE) {
241
+            $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($share->getSharedWith());
242
+            if ($circle === null) {
243
+                throw new \InvalidArgumentException('SharedWith is not a valid circle');
244
+            }
245
+        } elseif ($share->getShareType() === IShare::TYPE_ROOM) {
246
+        } elseif ($share->getShareType() === IShare::TYPE_DECK) {
247
+        } elseif ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
248
+        } else {
249
+            // We cannot handle other types yet
250
+            throw new \InvalidArgumentException('unknown share type');
251
+        }
252
+
253
+        // Verify the initiator of the share is set
254
+        if ($share->getSharedBy() === null) {
255
+            throw new \InvalidArgumentException('SharedBy should be set');
256
+        }
257
+
258
+        // Cannot share with yourself
259
+        if ($share->getShareType() === IShare::TYPE_USER &&
260
+            $share->getSharedWith() === $share->getSharedBy()) {
261
+            throw new \InvalidArgumentException('Cannot share with yourself');
262
+        }
263
+
264
+        // The path should be set
265
+        if ($share->getNode() === null) {
266
+            throw new \InvalidArgumentException('Path should be set');
267
+        }
268
+
269
+        // And it should be a file or a folder
270
+        if (!($share->getNode() instanceof \OCP\Files\File) &&
271
+            !($share->getNode() instanceof \OCP\Files\Folder)) {
272
+            throw new \InvalidArgumentException('Path should be either a file or a folder');
273
+        }
274
+
275
+        // And you cannot share your rootfolder
276
+        if ($this->userManager->userExists($share->getSharedBy())) {
277
+            $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
278
+        } else {
279
+            $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
280
+        }
281
+        if ($userFolder->getId() === $share->getNode()->getId()) {
282
+            throw new \InvalidArgumentException('You cannot share your root folder');
283
+        }
284
+
285
+        // Check if we actually have share permissions
286
+        if (!$share->getNode()->isShareable()) {
287
+            $message_t = $this->l->t('You are not allowed to share %s', [$share->getNode()->getName()]);
288
+            throw new GenericShareException($message_t, $message_t, 404);
289
+        }
290
+
291
+        // Permissions should be set
292
+        if ($share->getPermissions() === null) {
293
+            throw new \InvalidArgumentException('A share requires permissions');
294
+        }
295
+
296
+        $isFederatedShare = $share->getNode()->getStorage()->instanceOfStorage('\OCA\Files_Sharing\External\Storage');
297
+        $permissions = 0;
298
+
299
+        if (!$isFederatedShare && $share->getNode()->getOwner() && $share->getNode()->getOwner()->getUID() !== $share->getSharedBy()) {
300
+            $userMounts = array_filter($userFolder->getById($share->getNode()->getId()), function ($mount) {
301
+                // We need to filter since there might be other mountpoints that contain the file
302
+                // e.g. if the user has access to the same external storage that the file is originating from
303
+                return $mount->getStorage()->instanceOfStorage(ISharedStorage::class);
304
+            });
305
+            $userMount = array_shift($userMounts);
306
+            if ($userMount === null) {
307
+                throw new GenericShareException('Could not get proper share mount for ' . $share->getNode()->getId() . '. Failing since else the next calls are called with null');
308
+            }
309
+            $mount = $userMount->getMountPoint();
310
+            // When it's a reshare use the parent share permissions as maximum
311
+            $userMountPointId = $mount->getStorageRootId();
312
+            $userMountPoints = $userFolder->getById($userMountPointId);
313
+            $userMountPoint = array_shift($userMountPoints);
314
+
315
+            if ($userMountPoint === null) {
316
+                throw new GenericShareException('Could not get proper user mount for ' . $userMountPointId . '. Failing since else the next calls are called with null');
317
+            }
318
+
319
+            /* Check if this is an incoming share */
320
+            $incomingShares = $this->getSharedWith($share->getSharedBy(), IShare::TYPE_USER, $userMountPoint, -1, 0);
321
+            $incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), IShare::TYPE_GROUP, $userMountPoint, -1, 0));
322
+            $incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), IShare::TYPE_CIRCLE, $userMountPoint, -1, 0));
323
+            $incomingShares = array_merge($incomingShares, $this->getSharedWith($share->getSharedBy(), IShare::TYPE_ROOM, $userMountPoint, -1, 0));
324
+
325
+            /** @var IShare[] $incomingShares */
326
+            if (!empty($incomingShares)) {
327
+                foreach ($incomingShares as $incomingShare) {
328
+                    $permissions |= $incomingShare->getPermissions();
329
+                }
330
+            }
331
+        } else {
332
+            /*
333 333
 			 * Quick fix for #23536
334 334
 			 * Non moveable mount points do not have update and delete permissions
335 335
 			 * while we 'most likely' do have that on the storage.
336 336
 			 */
337
-			$permissions = $share->getNode()->getPermissions();
338
-			if (!($share->getNode()->getMountPoint() instanceof MoveableMount)) {
339
-				$permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
340
-			}
341
-		}
342
-
343
-		// Check that we do not share with more permissions than we have
344
-		if ($share->getPermissions() & ~$permissions) {
345
-			$path = $userFolder->getRelativePath($share->getNode()->getPath());
346
-			$message_t = $this->l->t('Cannot increase permissions of %s', [$path]);
347
-			throw new GenericShareException($message_t, $message_t, 404);
348
-		}
349
-
350
-
351
-		// Check that read permissions are always set
352
-		// Link shares are allowed to have no read permissions to allow upload to hidden folders
353
-		$noReadPermissionRequired = $share->getShareType() === IShare::TYPE_LINK
354
-			|| $share->getShareType() === IShare::TYPE_EMAIL;
355
-		if (!$noReadPermissionRequired &&
356
-			($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
357
-			throw new \InvalidArgumentException('Shares need at least read permissions');
358
-		}
359
-
360
-		if ($share->getNode() instanceof \OCP\Files\File) {
361
-			if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
362
-				$message_t = $this->l->t('Files cannot be shared with delete permissions');
363
-				throw new GenericShareException($message_t);
364
-			}
365
-			if ($share->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
366
-				$message_t = $this->l->t('Files cannot be shared with create permissions');
367
-				throw new GenericShareException($message_t);
368
-			}
369
-		}
370
-	}
371
-
372
-	/**
373
-	 * Validate if the expiration date fits the system settings
374
-	 *
375
-	 * @param IShare $share The share to validate the expiration date of
376
-	 * @return IShare The modified share object
377
-	 * @throws GenericShareException
378
-	 * @throws \InvalidArgumentException
379
-	 * @throws \Exception
380
-	 */
381
-	protected function validateExpirationDateInternal(IShare $share) {
382
-		$isRemote = $share->getShareType() === IShare::TYPE_REMOTE || $share->getShareType() === IShare::TYPE_REMOTE_GROUP;
383
-
384
-		$expirationDate = $share->getExpirationDate();
385
-
386
-		if ($expirationDate !== null) {
387
-			//Make sure the expiration date is a date
388
-			$expirationDate->setTime(0, 0, 0);
389
-
390
-			$date = new \DateTime();
391
-			$date->setTime(0, 0, 0);
392
-			if ($date >= $expirationDate) {
393
-				$message = $this->l->t('Expiration date is in the past');
394
-				throw new GenericShareException($message, $message, 404);
395
-			}
396
-		}
397
-
398
-		// If expiredate is empty set a default one if there is a default
399
-		$fullId = null;
400
-		try {
401
-			$fullId = $share->getFullId();
402
-		} catch (\UnexpectedValueException $e) {
403
-			// This is a new share
404
-		}
405
-
406
-		if ($isRemote) {
407
-			$defaultExpireDate = $this->shareApiRemoteDefaultExpireDate();
408
-			$defaultExpireDays = $this->shareApiRemoteDefaultExpireDays();
409
-			$configProp = 'remote_defaultExpDays';
410
-			$isEnforced = $this->shareApiRemoteDefaultExpireDateEnforced();
411
-		} else {
412
-			$defaultExpireDate = $this->shareApiInternalDefaultExpireDate();
413
-			$defaultExpireDays = $this->shareApiInternalDefaultExpireDays();
414
-			$configProp = 'internal_defaultExpDays';
415
-			$isEnforced = $this->shareApiInternalDefaultExpireDateEnforced();
416
-		}
417
-		if ($fullId === null && $expirationDate === null && $defaultExpireDate) {
418
-			$expirationDate = new \DateTime();
419
-			$expirationDate->setTime(0, 0, 0);
420
-
421
-			$days = (int)$this->config->getAppValue('core', $configProp, (string)$defaultExpireDays);
422
-			if ($days > $defaultExpireDays) {
423
-				$days = $defaultExpireDays;
424
-			}
425
-			$expirationDate->add(new \DateInterval('P' . $days . 'D'));
426
-		}
427
-
428
-		// If we enforce the expiration date check that is does not exceed
429
-		if ($isEnforced) {
430
-			if ($expirationDate === null) {
431
-				throw new \InvalidArgumentException('Expiration date is enforced');
432
-			}
433
-
434
-			$date = new \DateTime();
435
-			$date->setTime(0, 0, 0);
436
-			$date->add(new \DateInterval('P' . $defaultExpireDays . 'D'));
437
-			if ($date < $expirationDate) {
438
-				$message = $this->l->n('Cannot set expiration date more than %n day in the future', 'Cannot set expiration date more than %n days in the future', $defaultExpireDays);
439
-				throw new GenericShareException($message, $message, 404);
440
-			}
441
-		}
442
-
443
-		$accepted = true;
444
-		$message = '';
445
-		\OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
446
-			'expirationDate' => &$expirationDate,
447
-			'accepted' => &$accepted,
448
-			'message' => &$message,
449
-			'passwordSet' => $share->getPassword() !== null,
450
-		]);
451
-
452
-		if (!$accepted) {
453
-			throw new \Exception($message);
454
-		}
455
-
456
-		$share->setExpirationDate($expirationDate);
457
-
458
-		return $share;
459
-	}
460
-
461
-	/**
462
-	 * Validate if the expiration date fits the system settings
463
-	 *
464
-	 * @param IShare $share The share to validate the expiration date of
465
-	 * @return IShare The modified share object
466
-	 * @throws GenericShareException
467
-	 * @throws \InvalidArgumentException
468
-	 * @throws \Exception
469
-	 */
470
-	protected function validateExpirationDateLink(IShare $share) {
471
-		$expirationDate = $share->getExpirationDate();
472
-
473
-		if ($expirationDate !== null) {
474
-			//Make sure the expiration date is a date
475
-			$expirationDate->setTime(0, 0, 0);
476
-
477
-			$date = new \DateTime();
478
-			$date->setTime(0, 0, 0);
479
-			if ($date >= $expirationDate) {
480
-				$message = $this->l->t('Expiration date is in the past');
481
-				throw new GenericShareException($message, $message, 404);
482
-			}
483
-		}
484
-
485
-		// If expiredate is empty set a default one if there is a default
486
-		$fullId = null;
487
-		try {
488
-			$fullId = $share->getFullId();
489
-		} catch (\UnexpectedValueException $e) {
490
-			// This is a new share
491
-		}
492
-
493
-		if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
494
-			$expirationDate = new \DateTime();
495
-			$expirationDate->setTime(0, 0, 0);
496
-
497
-			$days = (int)$this->config->getAppValue('core', 'link_defaultExpDays', $this->shareApiLinkDefaultExpireDays());
498
-			if ($days > $this->shareApiLinkDefaultExpireDays()) {
499
-				$days = $this->shareApiLinkDefaultExpireDays();
500
-			}
501
-			$expirationDate->add(new \DateInterval('P' . $days . 'D'));
502
-		}
503
-
504
-		// If we enforce the expiration date check that is does not exceed
505
-		if ($this->shareApiLinkDefaultExpireDateEnforced()) {
506
-			if ($expirationDate === null) {
507
-				throw new \InvalidArgumentException('Expiration date is enforced');
508
-			}
509
-
510
-			$date = new \DateTime();
511
-			$date->setTime(0, 0, 0);
512
-			$date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
513
-			if ($date < $expirationDate) {
514
-				$message = $this->l->n('Cannot set expiration date more than %n day in the future', 'Cannot set expiration date more than %n days in the future', $this->shareApiLinkDefaultExpireDays());
515
-				throw new GenericShareException($message, $message, 404);
516
-			}
517
-		}
518
-
519
-		$accepted = true;
520
-		$message = '';
521
-		\OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
522
-			'expirationDate' => &$expirationDate,
523
-			'accepted' => &$accepted,
524
-			'message' => &$message,
525
-			'passwordSet' => $share->getPassword() !== null,
526
-		]);
527
-
528
-		if (!$accepted) {
529
-			throw new \Exception($message);
530
-		}
531
-
532
-		$share->setExpirationDate($expirationDate);
533
-
534
-		return $share;
535
-	}
536
-
537
-	/**
538
-	 * Check for pre share requirements for user shares
539
-	 *
540
-	 * @param IShare $share
541
-	 * @throws \Exception
542
-	 */
543
-	protected function userCreateChecks(IShare $share) {
544
-		// Check if we can share with group members only
545
-		if ($this->shareWithGroupMembersOnly()) {
546
-			$sharedBy = $this->userManager->get($share->getSharedBy());
547
-			$sharedWith = $this->userManager->get($share->getSharedWith());
548
-			// Verify we can share with this user
549
-			$groups = array_intersect(
550
-				$this->groupManager->getUserGroupIds($sharedBy),
551
-				$this->groupManager->getUserGroupIds($sharedWith)
552
-			);
553
-			if (empty($groups)) {
554
-				$message_t = $this->l->t('Sharing is only allowed with group members');
555
-				throw new \Exception($message_t);
556
-			}
557
-		}
558
-
559
-		/*
337
+            $permissions = $share->getNode()->getPermissions();
338
+            if (!($share->getNode()->getMountPoint() instanceof MoveableMount)) {
339
+                $permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
340
+            }
341
+        }
342
+
343
+        // Check that we do not share with more permissions than we have
344
+        if ($share->getPermissions() & ~$permissions) {
345
+            $path = $userFolder->getRelativePath($share->getNode()->getPath());
346
+            $message_t = $this->l->t('Cannot increase permissions of %s', [$path]);
347
+            throw new GenericShareException($message_t, $message_t, 404);
348
+        }
349
+
350
+
351
+        // Check that read permissions are always set
352
+        // Link shares are allowed to have no read permissions to allow upload to hidden folders
353
+        $noReadPermissionRequired = $share->getShareType() === IShare::TYPE_LINK
354
+            || $share->getShareType() === IShare::TYPE_EMAIL;
355
+        if (!$noReadPermissionRequired &&
356
+            ($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
357
+            throw new \InvalidArgumentException('Shares need at least read permissions');
358
+        }
359
+
360
+        if ($share->getNode() instanceof \OCP\Files\File) {
361
+            if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
362
+                $message_t = $this->l->t('Files cannot be shared with delete permissions');
363
+                throw new GenericShareException($message_t);
364
+            }
365
+            if ($share->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
366
+                $message_t = $this->l->t('Files cannot be shared with create permissions');
367
+                throw new GenericShareException($message_t);
368
+            }
369
+        }
370
+    }
371
+
372
+    /**
373
+     * Validate if the expiration date fits the system settings
374
+     *
375
+     * @param IShare $share The share to validate the expiration date of
376
+     * @return IShare The modified share object
377
+     * @throws GenericShareException
378
+     * @throws \InvalidArgumentException
379
+     * @throws \Exception
380
+     */
381
+    protected function validateExpirationDateInternal(IShare $share) {
382
+        $isRemote = $share->getShareType() === IShare::TYPE_REMOTE || $share->getShareType() === IShare::TYPE_REMOTE_GROUP;
383
+
384
+        $expirationDate = $share->getExpirationDate();
385
+
386
+        if ($expirationDate !== null) {
387
+            //Make sure the expiration date is a date
388
+            $expirationDate->setTime(0, 0, 0);
389
+
390
+            $date = new \DateTime();
391
+            $date->setTime(0, 0, 0);
392
+            if ($date >= $expirationDate) {
393
+                $message = $this->l->t('Expiration date is in the past');
394
+                throw new GenericShareException($message, $message, 404);
395
+            }
396
+        }
397
+
398
+        // If expiredate is empty set a default one if there is a default
399
+        $fullId = null;
400
+        try {
401
+            $fullId = $share->getFullId();
402
+        } catch (\UnexpectedValueException $e) {
403
+            // This is a new share
404
+        }
405
+
406
+        if ($isRemote) {
407
+            $defaultExpireDate = $this->shareApiRemoteDefaultExpireDate();
408
+            $defaultExpireDays = $this->shareApiRemoteDefaultExpireDays();
409
+            $configProp = 'remote_defaultExpDays';
410
+            $isEnforced = $this->shareApiRemoteDefaultExpireDateEnforced();
411
+        } else {
412
+            $defaultExpireDate = $this->shareApiInternalDefaultExpireDate();
413
+            $defaultExpireDays = $this->shareApiInternalDefaultExpireDays();
414
+            $configProp = 'internal_defaultExpDays';
415
+            $isEnforced = $this->shareApiInternalDefaultExpireDateEnforced();
416
+        }
417
+        if ($fullId === null && $expirationDate === null && $defaultExpireDate) {
418
+            $expirationDate = new \DateTime();
419
+            $expirationDate->setTime(0, 0, 0);
420
+
421
+            $days = (int)$this->config->getAppValue('core', $configProp, (string)$defaultExpireDays);
422
+            if ($days > $defaultExpireDays) {
423
+                $days = $defaultExpireDays;
424
+            }
425
+            $expirationDate->add(new \DateInterval('P' . $days . 'D'));
426
+        }
427
+
428
+        // If we enforce the expiration date check that is does not exceed
429
+        if ($isEnforced) {
430
+            if ($expirationDate === null) {
431
+                throw new \InvalidArgumentException('Expiration date is enforced');
432
+            }
433
+
434
+            $date = new \DateTime();
435
+            $date->setTime(0, 0, 0);
436
+            $date->add(new \DateInterval('P' . $defaultExpireDays . 'D'));
437
+            if ($date < $expirationDate) {
438
+                $message = $this->l->n('Cannot set expiration date more than %n day in the future', 'Cannot set expiration date more than %n days in the future', $defaultExpireDays);
439
+                throw new GenericShareException($message, $message, 404);
440
+            }
441
+        }
442
+
443
+        $accepted = true;
444
+        $message = '';
445
+        \OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
446
+            'expirationDate' => &$expirationDate,
447
+            'accepted' => &$accepted,
448
+            'message' => &$message,
449
+            'passwordSet' => $share->getPassword() !== null,
450
+        ]);
451
+
452
+        if (!$accepted) {
453
+            throw new \Exception($message);
454
+        }
455
+
456
+        $share->setExpirationDate($expirationDate);
457
+
458
+        return $share;
459
+    }
460
+
461
+    /**
462
+     * Validate if the expiration date fits the system settings
463
+     *
464
+     * @param IShare $share The share to validate the expiration date of
465
+     * @return IShare The modified share object
466
+     * @throws GenericShareException
467
+     * @throws \InvalidArgumentException
468
+     * @throws \Exception
469
+     */
470
+    protected function validateExpirationDateLink(IShare $share) {
471
+        $expirationDate = $share->getExpirationDate();
472
+
473
+        if ($expirationDate !== null) {
474
+            //Make sure the expiration date is a date
475
+            $expirationDate->setTime(0, 0, 0);
476
+
477
+            $date = new \DateTime();
478
+            $date->setTime(0, 0, 0);
479
+            if ($date >= $expirationDate) {
480
+                $message = $this->l->t('Expiration date is in the past');
481
+                throw new GenericShareException($message, $message, 404);
482
+            }
483
+        }
484
+
485
+        // If expiredate is empty set a default one if there is a default
486
+        $fullId = null;
487
+        try {
488
+            $fullId = $share->getFullId();
489
+        } catch (\UnexpectedValueException $e) {
490
+            // This is a new share
491
+        }
492
+
493
+        if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
494
+            $expirationDate = new \DateTime();
495
+            $expirationDate->setTime(0, 0, 0);
496
+
497
+            $days = (int)$this->config->getAppValue('core', 'link_defaultExpDays', $this->shareApiLinkDefaultExpireDays());
498
+            if ($days > $this->shareApiLinkDefaultExpireDays()) {
499
+                $days = $this->shareApiLinkDefaultExpireDays();
500
+            }
501
+            $expirationDate->add(new \DateInterval('P' . $days . 'D'));
502
+        }
503
+
504
+        // If we enforce the expiration date check that is does not exceed
505
+        if ($this->shareApiLinkDefaultExpireDateEnforced()) {
506
+            if ($expirationDate === null) {
507
+                throw new \InvalidArgumentException('Expiration date is enforced');
508
+            }
509
+
510
+            $date = new \DateTime();
511
+            $date->setTime(0, 0, 0);
512
+            $date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
513
+            if ($date < $expirationDate) {
514
+                $message = $this->l->n('Cannot set expiration date more than %n day in the future', 'Cannot set expiration date more than %n days in the future', $this->shareApiLinkDefaultExpireDays());
515
+                throw new GenericShareException($message, $message, 404);
516
+            }
517
+        }
518
+
519
+        $accepted = true;
520
+        $message = '';
521
+        \OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
522
+            'expirationDate' => &$expirationDate,
523
+            'accepted' => &$accepted,
524
+            'message' => &$message,
525
+            'passwordSet' => $share->getPassword() !== null,
526
+        ]);
527
+
528
+        if (!$accepted) {
529
+            throw new \Exception($message);
530
+        }
531
+
532
+        $share->setExpirationDate($expirationDate);
533
+
534
+        return $share;
535
+    }
536
+
537
+    /**
538
+     * Check for pre share requirements for user shares
539
+     *
540
+     * @param IShare $share
541
+     * @throws \Exception
542
+     */
543
+    protected function userCreateChecks(IShare $share) {
544
+        // Check if we can share with group members only
545
+        if ($this->shareWithGroupMembersOnly()) {
546
+            $sharedBy = $this->userManager->get($share->getSharedBy());
547
+            $sharedWith = $this->userManager->get($share->getSharedWith());
548
+            // Verify we can share with this user
549
+            $groups = array_intersect(
550
+                $this->groupManager->getUserGroupIds($sharedBy),
551
+                $this->groupManager->getUserGroupIds($sharedWith)
552
+            );
553
+            if (empty($groups)) {
554
+                $message_t = $this->l->t('Sharing is only allowed with group members');
555
+                throw new \Exception($message_t);
556
+            }
557
+        }
558
+
559
+        /*
560 560
 		 * TODO: Could be costly, fix
561 561
 		 *
562 562
 		 * Also this is not what we want in the future.. then we want to squash identical shares.
563 563
 		 */
564
-		$provider = $this->factory->getProviderForType(IShare::TYPE_USER);
565
-		$existingShares = $provider->getSharesByPath($share->getNode());
566
-		foreach ($existingShares as $existingShare) {
567
-			// Ignore if it is the same share
568
-			try {
569
-				if ($existingShare->getFullId() === $share->getFullId()) {
570
-					continue;
571
-				}
572
-			} catch (\UnexpectedValueException $e) {
573
-				//Shares are not identical
574
-			}
575
-
576
-			// Identical share already exists
577
-			if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
578
-				$message = $this->l->t('Sharing %s failed, because this item is already shared with user %s', [$share->getNode()->getName(), $share->getSharedWithDisplayName()]);
579
-				throw new AlreadySharedException($message, $existingShare);
580
-			}
581
-
582
-			// The share is already shared with this user via a group share
583
-			if ($existingShare->getShareType() === IShare::TYPE_GROUP) {
584
-				$group = $this->groupManager->get($existingShare->getSharedWith());
585
-				if (!is_null($group)) {
586
-					$user = $this->userManager->get($share->getSharedWith());
587
-
588
-					if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
589
-						$message = $this->l->t('Sharing %s failed, because this item is already shared with user %s', [$share->getNode()->getName(), $share->getSharedWithDisplayName()]);
590
-						throw new AlreadySharedException($message, $existingShare);
591
-					}
592
-				}
593
-			}
594
-		}
595
-	}
596
-
597
-	/**
598
-	 * Check for pre share requirements for group shares
599
-	 *
600
-	 * @param IShare $share
601
-	 * @throws \Exception
602
-	 */
603
-	protected function groupCreateChecks(IShare $share) {
604
-		// Verify group shares are allowed
605
-		if (!$this->allowGroupSharing()) {
606
-			throw new \Exception('Group sharing is now allowed');
607
-		}
608
-
609
-		// Verify if the user can share with this group
610
-		if ($this->shareWithGroupMembersOnly()) {
611
-			$sharedBy = $this->userManager->get($share->getSharedBy());
612
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
613
-			if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
614
-				throw new \Exception('Sharing is only allowed within your own groups');
615
-			}
616
-		}
617
-
618
-		/*
564
+        $provider = $this->factory->getProviderForType(IShare::TYPE_USER);
565
+        $existingShares = $provider->getSharesByPath($share->getNode());
566
+        foreach ($existingShares as $existingShare) {
567
+            // Ignore if it is the same share
568
+            try {
569
+                if ($existingShare->getFullId() === $share->getFullId()) {
570
+                    continue;
571
+                }
572
+            } catch (\UnexpectedValueException $e) {
573
+                //Shares are not identical
574
+            }
575
+
576
+            // Identical share already exists
577
+            if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
578
+                $message = $this->l->t('Sharing %s failed, because this item is already shared with user %s', [$share->getNode()->getName(), $share->getSharedWithDisplayName()]);
579
+                throw new AlreadySharedException($message, $existingShare);
580
+            }
581
+
582
+            // The share is already shared with this user via a group share
583
+            if ($existingShare->getShareType() === IShare::TYPE_GROUP) {
584
+                $group = $this->groupManager->get($existingShare->getSharedWith());
585
+                if (!is_null($group)) {
586
+                    $user = $this->userManager->get($share->getSharedWith());
587
+
588
+                    if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
589
+                        $message = $this->l->t('Sharing %s failed, because this item is already shared with user %s', [$share->getNode()->getName(), $share->getSharedWithDisplayName()]);
590
+                        throw new AlreadySharedException($message, $existingShare);
591
+                    }
592
+                }
593
+            }
594
+        }
595
+    }
596
+
597
+    /**
598
+     * Check for pre share requirements for group shares
599
+     *
600
+     * @param IShare $share
601
+     * @throws \Exception
602
+     */
603
+    protected function groupCreateChecks(IShare $share) {
604
+        // Verify group shares are allowed
605
+        if (!$this->allowGroupSharing()) {
606
+            throw new \Exception('Group sharing is now allowed');
607
+        }
608
+
609
+        // Verify if the user can share with this group
610
+        if ($this->shareWithGroupMembersOnly()) {
611
+            $sharedBy = $this->userManager->get($share->getSharedBy());
612
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
613
+            if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
614
+                throw new \Exception('Sharing is only allowed within your own groups');
615
+            }
616
+        }
617
+
618
+        /*
619 619
 		 * TODO: Could be costly, fix
620 620
 		 *
621 621
 		 * Also this is not what we want in the future.. then we want to squash identical shares.
622 622
 		 */
623
-		$provider = $this->factory->getProviderForType(IShare::TYPE_GROUP);
624
-		$existingShares = $provider->getSharesByPath($share->getNode());
625
-		foreach ($existingShares as $existingShare) {
626
-			try {
627
-				if ($existingShare->getFullId() === $share->getFullId()) {
628
-					continue;
629
-				}
630
-			} catch (\UnexpectedValueException $e) {
631
-				//It is a new share so just continue
632
-			}
633
-
634
-			if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
635
-				throw new AlreadySharedException('Path is already shared with this group', $existingShare);
636
-			}
637
-		}
638
-	}
639
-
640
-	/**
641
-	 * Check for pre share requirements for link shares
642
-	 *
643
-	 * @param IShare $share
644
-	 * @throws \Exception
645
-	 */
646
-	protected function linkCreateChecks(IShare $share) {
647
-		// Are link shares allowed?
648
-		if (!$this->shareApiAllowLinks()) {
649
-			throw new \Exception('Link sharing is not allowed');
650
-		}
651
-
652
-		// Check if public upload is allowed
653
-		if ($share->getNodeType() === 'folder' && !$this->shareApiLinkAllowPublicUpload() &&
654
-			($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
655
-			throw new \InvalidArgumentException('Public upload is not allowed');
656
-		}
657
-	}
658
-
659
-	/**
660
-	 * To make sure we don't get invisible link shares we set the parent
661
-	 * of a link if it is a reshare. This is a quick word around
662
-	 * until we can properly display multiple link shares in the UI
663
-	 *
664
-	 * See: https://github.com/owncloud/core/issues/22295
665
-	 *
666
-	 * FIXME: Remove once multiple link shares can be properly displayed
667
-	 *
668
-	 * @param IShare $share
669
-	 */
670
-	protected function setLinkParent(IShare $share) {
671
-		// No sense in checking if the method is not there.
672
-		if (method_exists($share, 'setParent')) {
673
-			$storage = $share->getNode()->getStorage();
674
-			if ($storage->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
675
-				/** @var \OCA\Files_Sharing\SharedStorage $storage */
676
-				$share->setParent($storage->getShareId());
677
-			}
678
-		}
679
-	}
680
-
681
-	/**
682
-	 * @param File|Folder $path
683
-	 */
684
-	protected function pathCreateChecks($path) {
685
-		// Make sure that we do not share a path that contains a shared mountpoint
686
-		if ($path instanceof \OCP\Files\Folder) {
687
-			$mounts = $this->mountManager->findIn($path->getPath());
688
-			foreach ($mounts as $mount) {
689
-				if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
690
-					throw new \InvalidArgumentException('Path contains files shared with you');
691
-				}
692
-			}
693
-		}
694
-	}
695
-
696
-	/**
697
-	 * Check if the user that is sharing can actually share
698
-	 *
699
-	 * @param IShare $share
700
-	 * @throws \Exception
701
-	 */
702
-	protected function canShare(IShare $share) {
703
-		if (!$this->shareApiEnabled()) {
704
-			throw new \Exception('Sharing is disabled');
705
-		}
706
-
707
-		if ($this->sharingDisabledForUser($share->getSharedBy())) {
708
-			throw new \Exception('Sharing is disabled for you');
709
-		}
710
-	}
711
-
712
-	/**
713
-	 * Share a path
714
-	 *
715
-	 * @param IShare $share
716
-	 * @return IShare The share object
717
-	 * @throws \Exception
718
-	 *
719
-	 * TODO: handle link share permissions or check them
720
-	 */
721
-	public function createShare(IShare $share) {
722
-		$this->canShare($share);
723
-
724
-		$this->generalCreateChecks($share);
725
-
726
-		// Verify if there are any issues with the path
727
-		$this->pathCreateChecks($share->getNode());
728
-
729
-		/*
623
+        $provider = $this->factory->getProviderForType(IShare::TYPE_GROUP);
624
+        $existingShares = $provider->getSharesByPath($share->getNode());
625
+        foreach ($existingShares as $existingShare) {
626
+            try {
627
+                if ($existingShare->getFullId() === $share->getFullId()) {
628
+                    continue;
629
+                }
630
+            } catch (\UnexpectedValueException $e) {
631
+                //It is a new share so just continue
632
+            }
633
+
634
+            if ($existingShare->getSharedWith() === $share->getSharedWith() && $existingShare->getShareType() === $share->getShareType()) {
635
+                throw new AlreadySharedException('Path is already shared with this group', $existingShare);
636
+            }
637
+        }
638
+    }
639
+
640
+    /**
641
+     * Check for pre share requirements for link shares
642
+     *
643
+     * @param IShare $share
644
+     * @throws \Exception
645
+     */
646
+    protected function linkCreateChecks(IShare $share) {
647
+        // Are link shares allowed?
648
+        if (!$this->shareApiAllowLinks()) {
649
+            throw new \Exception('Link sharing is not allowed');
650
+        }
651
+
652
+        // Check if public upload is allowed
653
+        if ($share->getNodeType() === 'folder' && !$this->shareApiLinkAllowPublicUpload() &&
654
+            ($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
655
+            throw new \InvalidArgumentException('Public upload is not allowed');
656
+        }
657
+    }
658
+
659
+    /**
660
+     * To make sure we don't get invisible link shares we set the parent
661
+     * of a link if it is a reshare. This is a quick word around
662
+     * until we can properly display multiple link shares in the UI
663
+     *
664
+     * See: https://github.com/owncloud/core/issues/22295
665
+     *
666
+     * FIXME: Remove once multiple link shares can be properly displayed
667
+     *
668
+     * @param IShare $share
669
+     */
670
+    protected function setLinkParent(IShare $share) {
671
+        // No sense in checking if the method is not there.
672
+        if (method_exists($share, 'setParent')) {
673
+            $storage = $share->getNode()->getStorage();
674
+            if ($storage->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
675
+                /** @var \OCA\Files_Sharing\SharedStorage $storage */
676
+                $share->setParent($storage->getShareId());
677
+            }
678
+        }
679
+    }
680
+
681
+    /**
682
+     * @param File|Folder $path
683
+     */
684
+    protected function pathCreateChecks($path) {
685
+        // Make sure that we do not share a path that contains a shared mountpoint
686
+        if ($path instanceof \OCP\Files\Folder) {
687
+            $mounts = $this->mountManager->findIn($path->getPath());
688
+            foreach ($mounts as $mount) {
689
+                if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
690
+                    throw new \InvalidArgumentException('Path contains files shared with you');
691
+                }
692
+            }
693
+        }
694
+    }
695
+
696
+    /**
697
+     * Check if the user that is sharing can actually share
698
+     *
699
+     * @param IShare $share
700
+     * @throws \Exception
701
+     */
702
+    protected function canShare(IShare $share) {
703
+        if (!$this->shareApiEnabled()) {
704
+            throw new \Exception('Sharing is disabled');
705
+        }
706
+
707
+        if ($this->sharingDisabledForUser($share->getSharedBy())) {
708
+            throw new \Exception('Sharing is disabled for you');
709
+        }
710
+    }
711
+
712
+    /**
713
+     * Share a path
714
+     *
715
+     * @param IShare $share
716
+     * @return IShare The share object
717
+     * @throws \Exception
718
+     *
719
+     * TODO: handle link share permissions or check them
720
+     */
721
+    public function createShare(IShare $share) {
722
+        $this->canShare($share);
723
+
724
+        $this->generalCreateChecks($share);
725
+
726
+        // Verify if there are any issues with the path
727
+        $this->pathCreateChecks($share->getNode());
728
+
729
+        /*
730 730
 		 * On creation of a share the owner is always the owner of the path
731 731
 		 * Except for mounted federated shares.
732 732
 		 */
733
-		$storage = $share->getNode()->getStorage();
734
-		if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
735
-			$parent = $share->getNode()->getParent();
736
-			while ($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
737
-				$parent = $parent->getParent();
738
-			}
739
-			$share->setShareOwner($parent->getOwner()->getUID());
740
-		} else {
741
-			if ($share->getNode()->getOwner()) {
742
-				$share->setShareOwner($share->getNode()->getOwner()->getUID());
743
-			} else {
744
-				$share->setShareOwner($share->getSharedBy());
745
-			}
746
-		}
747
-
748
-		try {
749
-			// Verify share type
750
-			if ($share->getShareType() === IShare::TYPE_USER) {
751
-				$this->userCreateChecks($share);
752
-
753
-				// Verify the expiration date
754
-				$share = $this->validateExpirationDateInternal($share);
755
-			} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
756
-				$this->groupCreateChecks($share);
757
-
758
-				// Verify the expiration date
759
-				$share = $this->validateExpirationDateInternal($share);
760
-			} elseif ($share->getShareType() === IShare::TYPE_REMOTE || $share->getShareType() === IShare::TYPE_REMOTE_GROUP) {
761
-				//Verify the expiration date
762
-				$share = $this->validateExpirationDateInternal($share);
763
-			} elseif ($share->getShareType() === IShare::TYPE_LINK
764
-				|| $share->getShareType() === IShare::TYPE_EMAIL) {
765
-				$this->linkCreateChecks($share);
766
-				$this->setLinkParent($share);
767
-
768
-				// For now ignore a set token.
769
-				$share->setToken(
770
-					$this->secureRandom->generate(
771
-						\OC\Share\Constants::TOKEN_LENGTH,
772
-						\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
773
-					)
774
-				);
775
-
776
-				// Verify the expiration date
777
-				$share = $this->validateExpirationDateLink($share);
778
-
779
-				// Verify the password
780
-				$this->verifyPassword($share->getPassword());
781
-
782
-				// If a password is set. Hash it!
783
-				if ($share->getShareType() === IShare::TYPE_LINK
784
-					&& $share->getPassword() !== null) {
785
-					$share->setPassword($this->hasher->hash($share->getPassword()));
786
-				}
787
-			}
788
-
789
-			// Cannot share with the owner
790
-			if ($share->getShareType() === IShare::TYPE_USER &&
791
-				$share->getSharedWith() === $share->getShareOwner()) {
792
-				throw new \InvalidArgumentException('Cannot share with the share owner');
793
-			}
794
-
795
-			// Generate the target
796
-			$defaultShareFolder = $this->config->getSystemValue('share_folder', '/');
797
-			$allowCustomShareFolder = $this->config->getSystemValueBool('sharing.allow_custom_share_folder', true);
798
-			if ($allowCustomShareFolder) {
799
-				$shareFolder = $this->config->getUserValue($share->getSharedWith(), Application::APP_ID, 'share_folder', $defaultShareFolder);
800
-			} else {
801
-				$shareFolder = $defaultShareFolder;
802
-			}
803
-
804
-			$target = $shareFolder . '/' . $share->getNode()->getName();
805
-			$target = \OC\Files\Filesystem::normalizePath($target);
806
-			$share->setTarget($target);
807
-
808
-			// Pre share event
809
-			$event = new GenericEvent($share);
810
-			$this->legacyDispatcher->dispatch('OCP\Share::preShare', $event);
811
-			if ($event->isPropagationStopped() && $event->hasArgument('error')) {
812
-				throw new \Exception($event->getArgument('error'));
813
-			}
814
-
815
-			$oldShare = $share;
816
-			$provider = $this->factory->getProviderForType($share->getShareType());
817
-			$share = $provider->create($share);
818
-
819
-			// Reuse the node we already have
820
-			$share->setNode($oldShare->getNode());
821
-
822
-			// Reset the target if it is null for the new share
823
-			if ($share->getTarget() === '') {
824
-				$share->setTarget($target);
825
-			}
826
-		} catch (AlreadySharedException $e) {
827
-			// if a share for the same target already exists, dont create a new one, but do trigger the hooks and notifications again
828
-			$share = $e->getExistingShare();
829
-		}
830
-
831
-		// Post share event
832
-		$event = new GenericEvent($share);
833
-		$this->legacyDispatcher->dispatch('OCP\Share::postShare', $event);
834
-
835
-		$this->dispatcher->dispatchTyped(new Share\Events\ShareCreatedEvent($share));
836
-
837
-		if ($this->config->getSystemValueBool('sharing.enable_share_mail', true)
838
-			&& $share->getShareType() === IShare::TYPE_USER) {
839
-			$mailSend = $share->getMailSend();
840
-			if ($mailSend === true) {
841
-				$user = $this->userManager->get($share->getSharedWith());
842
-				if ($user !== null) {
843
-					$emailAddress = $user->getEMailAddress();
844
-					if ($emailAddress !== null && $emailAddress !== '') {
845
-						$userLang = $this->l10nFactory->getUserLanguage($user);
846
-						$l = $this->l10nFactory->get('lib', $userLang);
847
-						$this->sendMailNotification(
848
-							$l,
849
-							$share->getNode()->getName(),
850
-							$this->urlGenerator->linkToRouteAbsolute('files_sharing.Accept.accept', ['shareId' => $share->getFullId()]),
851
-							$share->getSharedBy(),
852
-							$emailAddress,
853
-							$share->getExpirationDate(),
854
-							$share->getNote()
855
-						);
856
-						$this->logger->debug('Sent share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
857
-					} else {
858
-						$this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
859
-					}
860
-				} else {
861
-					$this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
862
-				}
863
-			} else {
864
-				$this->logger->debug('Share notification not sent because mailsend is false.', ['app' => 'share']);
865
-			}
866
-		}
867
-
868
-		return $share;
869
-	}
870
-
871
-	/**
872
-	 * Send mail notifications
873
-	 *
874
-	 * This method will catch and log mail transmission errors
875
-	 *
876
-	 * @param IL10N $l Language of the recipient
877
-	 * @param string $filename file/folder name
878
-	 * @param string $link link to the file/folder
879
-	 * @param string $initiator user ID of share sender
880
-	 * @param string $shareWith email address of share receiver
881
-	 * @param \DateTime|null $expiration
882
-	 */
883
-	protected function sendMailNotification(IL10N $l,
884
-											$filename,
885
-											$link,
886
-											$initiator,
887
-											$shareWith,
888
-											\DateTime $expiration = null,
889
-											$note = '') {
890
-		$initiatorUser = $this->userManager->get($initiator);
891
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
892
-
893
-		$message = $this->mailer->createMessage();
894
-
895
-		$emailTemplate = $this->mailer->createEMailTemplate('files_sharing.RecipientNotification', [
896
-			'filename' => $filename,
897
-			'link' => $link,
898
-			'initiator' => $initiatorDisplayName,
899
-			'expiration' => $expiration,
900
-			'shareWith' => $shareWith,
901
-		]);
902
-
903
-		$emailTemplate->setSubject($l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]));
904
-		$emailTemplate->addHeader();
905
-		$emailTemplate->addHeading($l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
906
-		$text = $l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
907
-
908
-		if ($note !== '') {
909
-			$emailTemplate->addBodyText(htmlspecialchars($note), $note);
910
-		}
911
-
912
-		$emailTemplate->addBodyText(
913
-			htmlspecialchars($text . ' ' . $l->t('Click the button below to open it.')),
914
-			$text
915
-		);
916
-		$emailTemplate->addBodyButton(
917
-			$l->t('Open »%s«', [$filename]),
918
-			$link
919
-		);
920
-
921
-		$message->setTo([$shareWith]);
922
-
923
-		// The "From" contains the sharers name
924
-		$instanceName = $this->defaults->getName();
925
-		$senderName = $l->t(
926
-			'%1$s via %2$s',
927
-			[
928
-				$initiatorDisplayName,
929
-				$instanceName,
930
-			]
931
-		);
932
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress('noreply') => $senderName]);
933
-
934
-		// The "Reply-To" is set to the sharer if an mail address is configured
935
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
936
-		$initiatorEmail = $initiatorUser->getEMailAddress();
937
-		if ($initiatorEmail !== null) {
938
-			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
939
-			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan($l->getLanguageCode()) !== '' ? ' - ' . $this->defaults->getSlogan($l->getLanguageCode()) : ''));
940
-		} else {
941
-			$emailTemplate->addFooter('', $l->getLanguageCode());
942
-		}
943
-
944
-		$message->useTemplate($emailTemplate);
945
-		try {
946
-			$failedRecipients = $this->mailer->send($message);
947
-			if (!empty($failedRecipients)) {
948
-				$this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
949
-				return;
950
-			}
951
-		} catch (\Exception $e) {
952
-			$this->logger->error('Share notification mail could not be sent', ['exception' => $e]);
953
-		}
954
-	}
955
-
956
-	/**
957
-	 * Update a share
958
-	 *
959
-	 * @param IShare $share
960
-	 * @return IShare The share object
961
-	 * @throws \InvalidArgumentException
962
-	 */
963
-	public function updateShare(IShare $share) {
964
-		$expirationDateUpdated = false;
965
-
966
-		$this->canShare($share);
967
-
968
-		try {
969
-			$originalShare = $this->getShareById($share->getFullId());
970
-		} catch (\UnexpectedValueException $e) {
971
-			throw new \InvalidArgumentException('Share does not have a full id');
972
-		}
973
-
974
-		// We cannot change the share type!
975
-		if ($share->getShareType() !== $originalShare->getShareType()) {
976
-			throw new \InvalidArgumentException('Cannot change share type');
977
-		}
978
-
979
-		// We can only change the recipient on user shares
980
-		if ($share->getSharedWith() !== $originalShare->getSharedWith() &&
981
-			$share->getShareType() !== IShare::TYPE_USER) {
982
-			throw new \InvalidArgumentException('Can only update recipient on user shares');
983
-		}
984
-
985
-		// Cannot share with the owner
986
-		if ($share->getShareType() === IShare::TYPE_USER &&
987
-			$share->getSharedWith() === $share->getShareOwner()) {
988
-			throw new \InvalidArgumentException('Cannot share with the share owner');
989
-		}
990
-
991
-		$this->generalCreateChecks($share);
992
-
993
-		if ($share->getShareType() === IShare::TYPE_USER) {
994
-			$this->userCreateChecks($share);
995
-
996
-			if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
997
-				//Verify the expiration date
998
-				$this->validateExpirationDateInternal($share);
999
-				$expirationDateUpdated = true;
1000
-			}
1001
-		} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
1002
-			$this->groupCreateChecks($share);
1003
-
1004
-			if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
1005
-				//Verify the expiration date
1006
-				$this->validateExpirationDateInternal($share);
1007
-				$expirationDateUpdated = true;
1008
-			}
1009
-		} elseif ($share->getShareType() === IShare::TYPE_LINK
1010
-			|| $share->getShareType() === IShare::TYPE_EMAIL) {
1011
-			$this->linkCreateChecks($share);
1012
-
1013
-			// The new password is not set again if it is the same as the old
1014
-			// one, unless when switching from sending by Talk to sending by
1015
-			// mail.
1016
-			$plainTextPassword = $share->getPassword();
1017
-			$updatedPassword = $this->updateSharePasswordIfNeeded($share, $originalShare);
1018
-
1019
-			/**
1020
-			 * Cannot enable the getSendPasswordByTalk if there is no password set
1021
-			 */
1022
-			if (empty($plainTextPassword) && $share->getSendPasswordByTalk()) {
1023
-				throw new \InvalidArgumentException('Cannot enable sending the password by Talk with an empty password');
1024
-			}
1025
-
1026
-			/**
1027
-			 * If we're in a mail share, we need to force a password change
1028
-			 * as either the user is not aware of the password or is already (received by mail)
1029
-			 * Thus the SendPasswordByTalk feature would not make sense
1030
-			 */
1031
-			if (!$updatedPassword && $share->getShareType() === IShare::TYPE_EMAIL) {
1032
-				if (!$originalShare->getSendPasswordByTalk() && $share->getSendPasswordByTalk()) {
1033
-					throw new \InvalidArgumentException('Cannot enable sending the password by Talk without setting a new password');
1034
-				}
1035
-				if ($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()) {
1036
-					throw new \InvalidArgumentException('Cannot disable sending the password by Talk without setting a new password');
1037
-				}
1038
-			}
1039
-
1040
-			if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
1041
-				// Verify the expiration date
1042
-				$this->validateExpirationDateLink($share);
1043
-				$expirationDateUpdated = true;
1044
-			}
1045
-		} elseif ($share->getShareType() === IShare::TYPE_REMOTE || $share->getShareType() === IShare::TYPE_REMOTE_GROUP) {
1046
-			if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
1047
-				//Verify the expiration date
1048
-				$this->validateExpirationDateInternal($share);
1049
-				$expirationDateUpdated = true;
1050
-			}
1051
-		}
1052
-
1053
-		$this->pathCreateChecks($share->getNode());
1054
-
1055
-		// Now update the share!
1056
-		$provider = $this->factory->getProviderForType($share->getShareType());
1057
-		if ($share->getShareType() === IShare::TYPE_EMAIL) {
1058
-			$share = $provider->update($share, $plainTextPassword);
1059
-		} else {
1060
-			$share = $provider->update($share);
1061
-		}
1062
-
1063
-		if ($expirationDateUpdated === true) {
1064
-			\OC_Hook::emit(Share::class, 'post_set_expiration_date', [
1065
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
1066
-				'itemSource' => $share->getNode()->getId(),
1067
-				'date' => $share->getExpirationDate(),
1068
-				'uidOwner' => $share->getSharedBy(),
1069
-			]);
1070
-		}
1071
-
1072
-		if ($share->getPassword() !== $originalShare->getPassword()) {
1073
-			\OC_Hook::emit(Share::class, 'post_update_password', [
1074
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
1075
-				'itemSource' => $share->getNode()->getId(),
1076
-				'uidOwner' => $share->getSharedBy(),
1077
-				'token' => $share->getToken(),
1078
-				'disabled' => is_null($share->getPassword()),
1079
-			]);
1080
-		}
1081
-
1082
-		if ($share->getPermissions() !== $originalShare->getPermissions()) {
1083
-			if ($this->userManager->userExists($share->getShareOwner())) {
1084
-				$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
1085
-			} else {
1086
-				$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
1087
-			}
1088
-			\OC_Hook::emit(Share::class, 'post_update_permissions', [
1089
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
1090
-				'itemSource' => $share->getNode()->getId(),
1091
-				'shareType' => $share->getShareType(),
1092
-				'shareWith' => $share->getSharedWith(),
1093
-				'uidOwner' => $share->getSharedBy(),
1094
-				'permissions' => $share->getPermissions(),
1095
-				'attributes' => $share->getAttributes() !== null ? $share->getAttributes()->toArray() : null,
1096
-				'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
1097
-			]);
1098
-		}
1099
-
1100
-		return $share;
1101
-	}
1102
-
1103
-	/**
1104
-	 * Accept a share.
1105
-	 *
1106
-	 * @param IShare $share
1107
-	 * @param string $recipientId
1108
-	 * @return IShare The share object
1109
-	 * @throws \InvalidArgumentException
1110
-	 * @since 9.0.0
1111
-	 */
1112
-	public function acceptShare(IShare $share, string $recipientId): IShare {
1113
-		[$providerId,] = $this->splitFullId($share->getFullId());
1114
-		$provider = $this->factory->getProvider($providerId);
1115
-
1116
-		if (!method_exists($provider, 'acceptShare')) {
1117
-			// TODO FIX ME
1118
-			throw new \InvalidArgumentException('Share provider does not support accepting');
1119
-		}
1120
-		$provider->acceptShare($share, $recipientId);
1121
-		$event = new GenericEvent($share);
1122
-		$this->legacyDispatcher->dispatch('OCP\Share::postAcceptShare', $event);
1123
-
1124
-		return $share;
1125
-	}
1126
-
1127
-	/**
1128
-	 * Updates the password of the given share if it is not the same as the
1129
-	 * password of the original share.
1130
-	 *
1131
-	 * @param IShare $share the share to update its password.
1132
-	 * @param IShare $originalShare the original share to compare its
1133
-	 *        password with.
1134
-	 * @return boolean whether the password was updated or not.
1135
-	 */
1136
-	private function updateSharePasswordIfNeeded(IShare $share, IShare $originalShare) {
1137
-		$passwordsAreDifferent = ($share->getPassword() !== $originalShare->getPassword()) &&
1138
-			(($share->getPassword() !== null && $originalShare->getPassword() === null) ||
1139
-				($share->getPassword() === null && $originalShare->getPassword() !== null) ||
1140
-				($share->getPassword() !== null && $originalShare->getPassword() !== null &&
1141
-					!$this->hasher->verify($share->getPassword(), $originalShare->getPassword())));
1142
-
1143
-		// Password updated.
1144
-		if ($passwordsAreDifferent) {
1145
-			//Verify the password
1146
-			$this->verifyPassword($share->getPassword());
1147
-
1148
-			// If a password is set. Hash it!
1149
-			if (!empty($share->getPassword())) {
1150
-				$share->setPassword($this->hasher->hash($share->getPassword()));
1151
-				if ($share->getShareType() === IShare::TYPE_EMAIL) {
1152
-					// Shares shared by email have temporary passwords
1153
-					$this->setSharePasswordExpirationTime($share);
1154
-				}
1155
-
1156
-				return true;
1157
-			} else {
1158
-				// Empty string and null are seen as NOT password protected
1159
-				$share->setPassword(null);
1160
-				if ($share->getShareType() === IShare::TYPE_EMAIL) {
1161
-					$share->setPasswordExpirationTime(null);
1162
-				}
1163
-				return true;
1164
-			}
1165
-		} else {
1166
-			// Reset the password to the original one, as it is either the same
1167
-			// as the "new" password or a hashed version of it.
1168
-			$share->setPassword($originalShare->getPassword());
1169
-		}
1170
-
1171
-		return false;
1172
-	}
1173
-
1174
-	/**
1175
-	 * Set the share's password expiration time
1176
-	 */
1177
-	private function setSharePasswordExpirationTime(IShare $share): void {
1178
-		if (!$this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false)) {
1179
-			// Sets password expiration date to NULL
1180
-			$share->setPasswordExpirationTime();
1181
-			return;
1182
-		}
1183
-		// Sets password expiration date
1184
-		$expirationTime = null;
1185
-		$now = new \DateTime();
1186
-		$expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
1187
-		$expirationTime = $now->add(new \DateInterval('PT' . $expirationInterval . 'S'));
1188
-		$share->setPasswordExpirationTime($expirationTime);
1189
-	}
1190
-
1191
-
1192
-	/**
1193
-	 * Delete all the children of this share
1194
-	 * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
1195
-	 *
1196
-	 * @param IShare $share
1197
-	 * @return IShare[] List of deleted shares
1198
-	 */
1199
-	protected function deleteChildren(IShare $share) {
1200
-		$deletedShares = [];
1201
-
1202
-		$provider = $this->factory->getProviderForType($share->getShareType());
1203
-
1204
-		foreach ($provider->getChildren($share) as $child) {
1205
-			$deletedChildren = $this->deleteChildren($child);
1206
-			$deletedShares = array_merge($deletedShares, $deletedChildren);
1207
-
1208
-			$provider->delete($child);
1209
-			$this->dispatcher->dispatchTyped(new Share\Events\ShareDeletedEvent($child));
1210
-			$deletedShares[] = $child;
1211
-		}
1212
-
1213
-		return $deletedShares;
1214
-	}
1215
-
1216
-	/**
1217
-	 * Delete a share
1218
-	 *
1219
-	 * @param IShare $share
1220
-	 * @throws ShareNotFound
1221
-	 * @throws \InvalidArgumentException
1222
-	 */
1223
-	public function deleteShare(IShare $share) {
1224
-		try {
1225
-			$share->getFullId();
1226
-		} catch (\UnexpectedValueException $e) {
1227
-			throw new \InvalidArgumentException('Share does not have a full id');
1228
-		}
1229
-
1230
-		$event = new GenericEvent($share);
1231
-		$this->legacyDispatcher->dispatch('OCP\Share::preUnshare', $event);
1232
-
1233
-		// Get all children and delete them as well
1234
-		$deletedShares = $this->deleteChildren($share);
1235
-
1236
-		// Do the actual delete
1237
-		$provider = $this->factory->getProviderForType($share->getShareType());
1238
-		$provider->delete($share);
1239
-
1240
-		$this->dispatcher->dispatchTyped(new Share\Events\ShareDeletedEvent($share));
1241
-
1242
-		// All the deleted shares caused by this delete
1243
-		$deletedShares[] = $share;
1244
-
1245
-		// Emit post hook
1246
-		$event->setArgument('deletedShares', $deletedShares);
1247
-		$this->legacyDispatcher->dispatch('OCP\Share::postUnshare', $event);
1248
-	}
1249
-
1250
-
1251
-	/**
1252
-	 * Unshare a file as the recipient.
1253
-	 * This can be different from a regular delete for example when one of
1254
-	 * the users in a groups deletes that share. But the provider should
1255
-	 * handle this.
1256
-	 *
1257
-	 * @param IShare $share
1258
-	 * @param string $recipientId
1259
-	 */
1260
-	public function deleteFromSelf(IShare $share, $recipientId) {
1261
-		[$providerId,] = $this->splitFullId($share->getFullId());
1262
-		$provider = $this->factory->getProvider($providerId);
1263
-
1264
-		$provider->deleteFromSelf($share, $recipientId);
1265
-		$event = new GenericEvent($share);
1266
-		$this->legacyDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
1267
-	}
1268
-
1269
-	public function restoreShare(IShare $share, string $recipientId): IShare {
1270
-		[$providerId,] = $this->splitFullId($share->getFullId());
1271
-		$provider = $this->factory->getProvider($providerId);
1272
-
1273
-		return $provider->restore($share, $recipientId);
1274
-	}
1275
-
1276
-	/**
1277
-	 * @inheritdoc
1278
-	 */
1279
-	public function moveShare(IShare $share, $recipientId) {
1280
-		if ($share->getShareType() === IShare::TYPE_LINK
1281
-			|| $share->getShareType() === IShare::TYPE_EMAIL) {
1282
-			throw new \InvalidArgumentException('Cannot change target of link share');
1283
-		}
1284
-
1285
-		if ($share->getShareType() === IShare::TYPE_USER && $share->getSharedWith() !== $recipientId) {
1286
-			throw new \InvalidArgumentException('Invalid recipient');
1287
-		}
1288
-
1289
-		if ($share->getShareType() === IShare::TYPE_GROUP) {
1290
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
1291
-			if (is_null($sharedWith)) {
1292
-				throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
1293
-			}
1294
-			$recipient = $this->userManager->get($recipientId);
1295
-			if (!$sharedWith->inGroup($recipient)) {
1296
-				throw new \InvalidArgumentException('Invalid recipient');
1297
-			}
1298
-		}
1299
-
1300
-		[$providerId,] = $this->splitFullId($share->getFullId());
1301
-		$provider = $this->factory->getProvider($providerId);
1302
-
1303
-		return $provider->move($share, $recipientId);
1304
-	}
1305
-
1306
-	public function getSharesInFolder($userId, Folder $node, $reshares = false, $shallow = true) {
1307
-		$providers = $this->factory->getAllProviders();
1308
-
1309
-		return array_reduce($providers, function ($shares, IShareProvider $provider) use ($userId, $node, $reshares, $shallow) {
1310
-			$newShares = $provider->getSharesInFolder($userId, $node, $reshares, $shallow);
1311
-			foreach ($newShares as $fid => $data) {
1312
-				if (!isset($shares[$fid])) {
1313
-					$shares[$fid] = [];
1314
-				}
1315
-
1316
-				$shares[$fid] = array_merge($shares[$fid], $data);
1317
-			}
1318
-			return $shares;
1319
-		}, []);
1320
-	}
1321
-
1322
-	/**
1323
-	 * @inheritdoc
1324
-	 */
1325
-	public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
1326
-		if ($path !== null &&
1327
-			!($path instanceof \OCP\Files\File) &&
1328
-			!($path instanceof \OCP\Files\Folder)) {
1329
-			throw new \InvalidArgumentException('invalid path');
1330
-		}
1331
-
1332
-		try {
1333
-			$provider = $this->factory->getProviderForType($shareType);
1334
-		} catch (ProviderException $e) {
1335
-			return [];
1336
-		}
1337
-
1338
-		$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1339
-
1340
-		/*
733
+        $storage = $share->getNode()->getStorage();
734
+        if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
735
+            $parent = $share->getNode()->getParent();
736
+            while ($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
737
+                $parent = $parent->getParent();
738
+            }
739
+            $share->setShareOwner($parent->getOwner()->getUID());
740
+        } else {
741
+            if ($share->getNode()->getOwner()) {
742
+                $share->setShareOwner($share->getNode()->getOwner()->getUID());
743
+            } else {
744
+                $share->setShareOwner($share->getSharedBy());
745
+            }
746
+        }
747
+
748
+        try {
749
+            // Verify share type
750
+            if ($share->getShareType() === IShare::TYPE_USER) {
751
+                $this->userCreateChecks($share);
752
+
753
+                // Verify the expiration date
754
+                $share = $this->validateExpirationDateInternal($share);
755
+            } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
756
+                $this->groupCreateChecks($share);
757
+
758
+                // Verify the expiration date
759
+                $share = $this->validateExpirationDateInternal($share);
760
+            } elseif ($share->getShareType() === IShare::TYPE_REMOTE || $share->getShareType() === IShare::TYPE_REMOTE_GROUP) {
761
+                //Verify the expiration date
762
+                $share = $this->validateExpirationDateInternal($share);
763
+            } elseif ($share->getShareType() === IShare::TYPE_LINK
764
+                || $share->getShareType() === IShare::TYPE_EMAIL) {
765
+                $this->linkCreateChecks($share);
766
+                $this->setLinkParent($share);
767
+
768
+                // For now ignore a set token.
769
+                $share->setToken(
770
+                    $this->secureRandom->generate(
771
+                        \OC\Share\Constants::TOKEN_LENGTH,
772
+                        \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
773
+                    )
774
+                );
775
+
776
+                // Verify the expiration date
777
+                $share = $this->validateExpirationDateLink($share);
778
+
779
+                // Verify the password
780
+                $this->verifyPassword($share->getPassword());
781
+
782
+                // If a password is set. Hash it!
783
+                if ($share->getShareType() === IShare::TYPE_LINK
784
+                    && $share->getPassword() !== null) {
785
+                    $share->setPassword($this->hasher->hash($share->getPassword()));
786
+                }
787
+            }
788
+
789
+            // Cannot share with the owner
790
+            if ($share->getShareType() === IShare::TYPE_USER &&
791
+                $share->getSharedWith() === $share->getShareOwner()) {
792
+                throw new \InvalidArgumentException('Cannot share with the share owner');
793
+            }
794
+
795
+            // Generate the target
796
+            $defaultShareFolder = $this->config->getSystemValue('share_folder', '/');
797
+            $allowCustomShareFolder = $this->config->getSystemValueBool('sharing.allow_custom_share_folder', true);
798
+            if ($allowCustomShareFolder) {
799
+                $shareFolder = $this->config->getUserValue($share->getSharedWith(), Application::APP_ID, 'share_folder', $defaultShareFolder);
800
+            } else {
801
+                $shareFolder = $defaultShareFolder;
802
+            }
803
+
804
+            $target = $shareFolder . '/' . $share->getNode()->getName();
805
+            $target = \OC\Files\Filesystem::normalizePath($target);
806
+            $share->setTarget($target);
807
+
808
+            // Pre share event
809
+            $event = new GenericEvent($share);
810
+            $this->legacyDispatcher->dispatch('OCP\Share::preShare', $event);
811
+            if ($event->isPropagationStopped() && $event->hasArgument('error')) {
812
+                throw new \Exception($event->getArgument('error'));
813
+            }
814
+
815
+            $oldShare = $share;
816
+            $provider = $this->factory->getProviderForType($share->getShareType());
817
+            $share = $provider->create($share);
818
+
819
+            // Reuse the node we already have
820
+            $share->setNode($oldShare->getNode());
821
+
822
+            // Reset the target if it is null for the new share
823
+            if ($share->getTarget() === '') {
824
+                $share->setTarget($target);
825
+            }
826
+        } catch (AlreadySharedException $e) {
827
+            // if a share for the same target already exists, dont create a new one, but do trigger the hooks and notifications again
828
+            $share = $e->getExistingShare();
829
+        }
830
+
831
+        // Post share event
832
+        $event = new GenericEvent($share);
833
+        $this->legacyDispatcher->dispatch('OCP\Share::postShare', $event);
834
+
835
+        $this->dispatcher->dispatchTyped(new Share\Events\ShareCreatedEvent($share));
836
+
837
+        if ($this->config->getSystemValueBool('sharing.enable_share_mail', true)
838
+            && $share->getShareType() === IShare::TYPE_USER) {
839
+            $mailSend = $share->getMailSend();
840
+            if ($mailSend === true) {
841
+                $user = $this->userManager->get($share->getSharedWith());
842
+                if ($user !== null) {
843
+                    $emailAddress = $user->getEMailAddress();
844
+                    if ($emailAddress !== null && $emailAddress !== '') {
845
+                        $userLang = $this->l10nFactory->getUserLanguage($user);
846
+                        $l = $this->l10nFactory->get('lib', $userLang);
847
+                        $this->sendMailNotification(
848
+                            $l,
849
+                            $share->getNode()->getName(),
850
+                            $this->urlGenerator->linkToRouteAbsolute('files_sharing.Accept.accept', ['shareId' => $share->getFullId()]),
851
+                            $share->getSharedBy(),
852
+                            $emailAddress,
853
+                            $share->getExpirationDate(),
854
+                            $share->getNote()
855
+                        );
856
+                        $this->logger->debug('Sent share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
857
+                    } else {
858
+                        $this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
859
+                    }
860
+                } else {
861
+                    $this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
862
+                }
863
+            } else {
864
+                $this->logger->debug('Share notification not sent because mailsend is false.', ['app' => 'share']);
865
+            }
866
+        }
867
+
868
+        return $share;
869
+    }
870
+
871
+    /**
872
+     * Send mail notifications
873
+     *
874
+     * This method will catch and log mail transmission errors
875
+     *
876
+     * @param IL10N $l Language of the recipient
877
+     * @param string $filename file/folder name
878
+     * @param string $link link to the file/folder
879
+     * @param string $initiator user ID of share sender
880
+     * @param string $shareWith email address of share receiver
881
+     * @param \DateTime|null $expiration
882
+     */
883
+    protected function sendMailNotification(IL10N $l,
884
+                                            $filename,
885
+                                            $link,
886
+                                            $initiator,
887
+                                            $shareWith,
888
+                                            \DateTime $expiration = null,
889
+                                            $note = '') {
890
+        $initiatorUser = $this->userManager->get($initiator);
891
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
892
+
893
+        $message = $this->mailer->createMessage();
894
+
895
+        $emailTemplate = $this->mailer->createEMailTemplate('files_sharing.RecipientNotification', [
896
+            'filename' => $filename,
897
+            'link' => $link,
898
+            'initiator' => $initiatorDisplayName,
899
+            'expiration' => $expiration,
900
+            'shareWith' => $shareWith,
901
+        ]);
902
+
903
+        $emailTemplate->setSubject($l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]));
904
+        $emailTemplate->addHeader();
905
+        $emailTemplate->addHeading($l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
906
+        $text = $l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
907
+
908
+        if ($note !== '') {
909
+            $emailTemplate->addBodyText(htmlspecialchars($note), $note);
910
+        }
911
+
912
+        $emailTemplate->addBodyText(
913
+            htmlspecialchars($text . ' ' . $l->t('Click the button below to open it.')),
914
+            $text
915
+        );
916
+        $emailTemplate->addBodyButton(
917
+            $l->t('Open »%s«', [$filename]),
918
+            $link
919
+        );
920
+
921
+        $message->setTo([$shareWith]);
922
+
923
+        // The "From" contains the sharers name
924
+        $instanceName = $this->defaults->getName();
925
+        $senderName = $l->t(
926
+            '%1$s via %2$s',
927
+            [
928
+                $initiatorDisplayName,
929
+                $instanceName,
930
+            ]
931
+        );
932
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress('noreply') => $senderName]);
933
+
934
+        // The "Reply-To" is set to the sharer if an mail address is configured
935
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
936
+        $initiatorEmail = $initiatorUser->getEMailAddress();
937
+        if ($initiatorEmail !== null) {
938
+            $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
939
+            $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan($l->getLanguageCode()) !== '' ? ' - ' . $this->defaults->getSlogan($l->getLanguageCode()) : ''));
940
+        } else {
941
+            $emailTemplate->addFooter('', $l->getLanguageCode());
942
+        }
943
+
944
+        $message->useTemplate($emailTemplate);
945
+        try {
946
+            $failedRecipients = $this->mailer->send($message);
947
+            if (!empty($failedRecipients)) {
948
+                $this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
949
+                return;
950
+            }
951
+        } catch (\Exception $e) {
952
+            $this->logger->error('Share notification mail could not be sent', ['exception' => $e]);
953
+        }
954
+    }
955
+
956
+    /**
957
+     * Update a share
958
+     *
959
+     * @param IShare $share
960
+     * @return IShare The share object
961
+     * @throws \InvalidArgumentException
962
+     */
963
+    public function updateShare(IShare $share) {
964
+        $expirationDateUpdated = false;
965
+
966
+        $this->canShare($share);
967
+
968
+        try {
969
+            $originalShare = $this->getShareById($share->getFullId());
970
+        } catch (\UnexpectedValueException $e) {
971
+            throw new \InvalidArgumentException('Share does not have a full id');
972
+        }
973
+
974
+        // We cannot change the share type!
975
+        if ($share->getShareType() !== $originalShare->getShareType()) {
976
+            throw new \InvalidArgumentException('Cannot change share type');
977
+        }
978
+
979
+        // We can only change the recipient on user shares
980
+        if ($share->getSharedWith() !== $originalShare->getSharedWith() &&
981
+            $share->getShareType() !== IShare::TYPE_USER) {
982
+            throw new \InvalidArgumentException('Can only update recipient on user shares');
983
+        }
984
+
985
+        // Cannot share with the owner
986
+        if ($share->getShareType() === IShare::TYPE_USER &&
987
+            $share->getSharedWith() === $share->getShareOwner()) {
988
+            throw new \InvalidArgumentException('Cannot share with the share owner');
989
+        }
990
+
991
+        $this->generalCreateChecks($share);
992
+
993
+        if ($share->getShareType() === IShare::TYPE_USER) {
994
+            $this->userCreateChecks($share);
995
+
996
+            if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
997
+                //Verify the expiration date
998
+                $this->validateExpirationDateInternal($share);
999
+                $expirationDateUpdated = true;
1000
+            }
1001
+        } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
1002
+            $this->groupCreateChecks($share);
1003
+
1004
+            if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
1005
+                //Verify the expiration date
1006
+                $this->validateExpirationDateInternal($share);
1007
+                $expirationDateUpdated = true;
1008
+            }
1009
+        } elseif ($share->getShareType() === IShare::TYPE_LINK
1010
+            || $share->getShareType() === IShare::TYPE_EMAIL) {
1011
+            $this->linkCreateChecks($share);
1012
+
1013
+            // The new password is not set again if it is the same as the old
1014
+            // one, unless when switching from sending by Talk to sending by
1015
+            // mail.
1016
+            $plainTextPassword = $share->getPassword();
1017
+            $updatedPassword = $this->updateSharePasswordIfNeeded($share, $originalShare);
1018
+
1019
+            /**
1020
+             * Cannot enable the getSendPasswordByTalk if there is no password set
1021
+             */
1022
+            if (empty($plainTextPassword) && $share->getSendPasswordByTalk()) {
1023
+                throw new \InvalidArgumentException('Cannot enable sending the password by Talk with an empty password');
1024
+            }
1025
+
1026
+            /**
1027
+             * If we're in a mail share, we need to force a password change
1028
+             * as either the user is not aware of the password or is already (received by mail)
1029
+             * Thus the SendPasswordByTalk feature would not make sense
1030
+             */
1031
+            if (!$updatedPassword && $share->getShareType() === IShare::TYPE_EMAIL) {
1032
+                if (!$originalShare->getSendPasswordByTalk() && $share->getSendPasswordByTalk()) {
1033
+                    throw new \InvalidArgumentException('Cannot enable sending the password by Talk without setting a new password');
1034
+                }
1035
+                if ($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()) {
1036
+                    throw new \InvalidArgumentException('Cannot disable sending the password by Talk without setting a new password');
1037
+                }
1038
+            }
1039
+
1040
+            if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
1041
+                // Verify the expiration date
1042
+                $this->validateExpirationDateLink($share);
1043
+                $expirationDateUpdated = true;
1044
+            }
1045
+        } elseif ($share->getShareType() === IShare::TYPE_REMOTE || $share->getShareType() === IShare::TYPE_REMOTE_GROUP) {
1046
+            if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
1047
+                //Verify the expiration date
1048
+                $this->validateExpirationDateInternal($share);
1049
+                $expirationDateUpdated = true;
1050
+            }
1051
+        }
1052
+
1053
+        $this->pathCreateChecks($share->getNode());
1054
+
1055
+        // Now update the share!
1056
+        $provider = $this->factory->getProviderForType($share->getShareType());
1057
+        if ($share->getShareType() === IShare::TYPE_EMAIL) {
1058
+            $share = $provider->update($share, $plainTextPassword);
1059
+        } else {
1060
+            $share = $provider->update($share);
1061
+        }
1062
+
1063
+        if ($expirationDateUpdated === true) {
1064
+            \OC_Hook::emit(Share::class, 'post_set_expiration_date', [
1065
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
1066
+                'itemSource' => $share->getNode()->getId(),
1067
+                'date' => $share->getExpirationDate(),
1068
+                'uidOwner' => $share->getSharedBy(),
1069
+            ]);
1070
+        }
1071
+
1072
+        if ($share->getPassword() !== $originalShare->getPassword()) {
1073
+            \OC_Hook::emit(Share::class, 'post_update_password', [
1074
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
1075
+                'itemSource' => $share->getNode()->getId(),
1076
+                'uidOwner' => $share->getSharedBy(),
1077
+                'token' => $share->getToken(),
1078
+                'disabled' => is_null($share->getPassword()),
1079
+            ]);
1080
+        }
1081
+
1082
+        if ($share->getPermissions() !== $originalShare->getPermissions()) {
1083
+            if ($this->userManager->userExists($share->getShareOwner())) {
1084
+                $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
1085
+            } else {
1086
+                $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
1087
+            }
1088
+            \OC_Hook::emit(Share::class, 'post_update_permissions', [
1089
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
1090
+                'itemSource' => $share->getNode()->getId(),
1091
+                'shareType' => $share->getShareType(),
1092
+                'shareWith' => $share->getSharedWith(),
1093
+                'uidOwner' => $share->getSharedBy(),
1094
+                'permissions' => $share->getPermissions(),
1095
+                'attributes' => $share->getAttributes() !== null ? $share->getAttributes()->toArray() : null,
1096
+                'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
1097
+            ]);
1098
+        }
1099
+
1100
+        return $share;
1101
+    }
1102
+
1103
+    /**
1104
+     * Accept a share.
1105
+     *
1106
+     * @param IShare $share
1107
+     * @param string $recipientId
1108
+     * @return IShare The share object
1109
+     * @throws \InvalidArgumentException
1110
+     * @since 9.0.0
1111
+     */
1112
+    public function acceptShare(IShare $share, string $recipientId): IShare {
1113
+        [$providerId,] = $this->splitFullId($share->getFullId());
1114
+        $provider = $this->factory->getProvider($providerId);
1115
+
1116
+        if (!method_exists($provider, 'acceptShare')) {
1117
+            // TODO FIX ME
1118
+            throw new \InvalidArgumentException('Share provider does not support accepting');
1119
+        }
1120
+        $provider->acceptShare($share, $recipientId);
1121
+        $event = new GenericEvent($share);
1122
+        $this->legacyDispatcher->dispatch('OCP\Share::postAcceptShare', $event);
1123
+
1124
+        return $share;
1125
+    }
1126
+
1127
+    /**
1128
+     * Updates the password of the given share if it is not the same as the
1129
+     * password of the original share.
1130
+     *
1131
+     * @param IShare $share the share to update its password.
1132
+     * @param IShare $originalShare the original share to compare its
1133
+     *        password with.
1134
+     * @return boolean whether the password was updated or not.
1135
+     */
1136
+    private function updateSharePasswordIfNeeded(IShare $share, IShare $originalShare) {
1137
+        $passwordsAreDifferent = ($share->getPassword() !== $originalShare->getPassword()) &&
1138
+            (($share->getPassword() !== null && $originalShare->getPassword() === null) ||
1139
+                ($share->getPassword() === null && $originalShare->getPassword() !== null) ||
1140
+                ($share->getPassword() !== null && $originalShare->getPassword() !== null &&
1141
+                    !$this->hasher->verify($share->getPassword(), $originalShare->getPassword())));
1142
+
1143
+        // Password updated.
1144
+        if ($passwordsAreDifferent) {
1145
+            //Verify the password
1146
+            $this->verifyPassword($share->getPassword());
1147
+
1148
+            // If a password is set. Hash it!
1149
+            if (!empty($share->getPassword())) {
1150
+                $share->setPassword($this->hasher->hash($share->getPassword()));
1151
+                if ($share->getShareType() === IShare::TYPE_EMAIL) {
1152
+                    // Shares shared by email have temporary passwords
1153
+                    $this->setSharePasswordExpirationTime($share);
1154
+                }
1155
+
1156
+                return true;
1157
+            } else {
1158
+                // Empty string and null are seen as NOT password protected
1159
+                $share->setPassword(null);
1160
+                if ($share->getShareType() === IShare::TYPE_EMAIL) {
1161
+                    $share->setPasswordExpirationTime(null);
1162
+                }
1163
+                return true;
1164
+            }
1165
+        } else {
1166
+            // Reset the password to the original one, as it is either the same
1167
+            // as the "new" password or a hashed version of it.
1168
+            $share->setPassword($originalShare->getPassword());
1169
+        }
1170
+
1171
+        return false;
1172
+    }
1173
+
1174
+    /**
1175
+     * Set the share's password expiration time
1176
+     */
1177
+    private function setSharePasswordExpirationTime(IShare $share): void {
1178
+        if (!$this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false)) {
1179
+            // Sets password expiration date to NULL
1180
+            $share->setPasswordExpirationTime();
1181
+            return;
1182
+        }
1183
+        // Sets password expiration date
1184
+        $expirationTime = null;
1185
+        $now = new \DateTime();
1186
+        $expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
1187
+        $expirationTime = $now->add(new \DateInterval('PT' . $expirationInterval . 'S'));
1188
+        $share->setPasswordExpirationTime($expirationTime);
1189
+    }
1190
+
1191
+
1192
+    /**
1193
+     * Delete all the children of this share
1194
+     * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
1195
+     *
1196
+     * @param IShare $share
1197
+     * @return IShare[] List of deleted shares
1198
+     */
1199
+    protected function deleteChildren(IShare $share) {
1200
+        $deletedShares = [];
1201
+
1202
+        $provider = $this->factory->getProviderForType($share->getShareType());
1203
+
1204
+        foreach ($provider->getChildren($share) as $child) {
1205
+            $deletedChildren = $this->deleteChildren($child);
1206
+            $deletedShares = array_merge($deletedShares, $deletedChildren);
1207
+
1208
+            $provider->delete($child);
1209
+            $this->dispatcher->dispatchTyped(new Share\Events\ShareDeletedEvent($child));
1210
+            $deletedShares[] = $child;
1211
+        }
1212
+
1213
+        return $deletedShares;
1214
+    }
1215
+
1216
+    /**
1217
+     * Delete a share
1218
+     *
1219
+     * @param IShare $share
1220
+     * @throws ShareNotFound
1221
+     * @throws \InvalidArgumentException
1222
+     */
1223
+    public function deleteShare(IShare $share) {
1224
+        try {
1225
+            $share->getFullId();
1226
+        } catch (\UnexpectedValueException $e) {
1227
+            throw new \InvalidArgumentException('Share does not have a full id');
1228
+        }
1229
+
1230
+        $event = new GenericEvent($share);
1231
+        $this->legacyDispatcher->dispatch('OCP\Share::preUnshare', $event);
1232
+
1233
+        // Get all children and delete them as well
1234
+        $deletedShares = $this->deleteChildren($share);
1235
+
1236
+        // Do the actual delete
1237
+        $provider = $this->factory->getProviderForType($share->getShareType());
1238
+        $provider->delete($share);
1239
+
1240
+        $this->dispatcher->dispatchTyped(new Share\Events\ShareDeletedEvent($share));
1241
+
1242
+        // All the deleted shares caused by this delete
1243
+        $deletedShares[] = $share;
1244
+
1245
+        // Emit post hook
1246
+        $event->setArgument('deletedShares', $deletedShares);
1247
+        $this->legacyDispatcher->dispatch('OCP\Share::postUnshare', $event);
1248
+    }
1249
+
1250
+
1251
+    /**
1252
+     * Unshare a file as the recipient.
1253
+     * This can be different from a regular delete for example when one of
1254
+     * the users in a groups deletes that share. But the provider should
1255
+     * handle this.
1256
+     *
1257
+     * @param IShare $share
1258
+     * @param string $recipientId
1259
+     */
1260
+    public function deleteFromSelf(IShare $share, $recipientId) {
1261
+        [$providerId,] = $this->splitFullId($share->getFullId());
1262
+        $provider = $this->factory->getProvider($providerId);
1263
+
1264
+        $provider->deleteFromSelf($share, $recipientId);
1265
+        $event = new GenericEvent($share);
1266
+        $this->legacyDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
1267
+    }
1268
+
1269
+    public function restoreShare(IShare $share, string $recipientId): IShare {
1270
+        [$providerId,] = $this->splitFullId($share->getFullId());
1271
+        $provider = $this->factory->getProvider($providerId);
1272
+
1273
+        return $provider->restore($share, $recipientId);
1274
+    }
1275
+
1276
+    /**
1277
+     * @inheritdoc
1278
+     */
1279
+    public function moveShare(IShare $share, $recipientId) {
1280
+        if ($share->getShareType() === IShare::TYPE_LINK
1281
+            || $share->getShareType() === IShare::TYPE_EMAIL) {
1282
+            throw new \InvalidArgumentException('Cannot change target of link share');
1283
+        }
1284
+
1285
+        if ($share->getShareType() === IShare::TYPE_USER && $share->getSharedWith() !== $recipientId) {
1286
+            throw new \InvalidArgumentException('Invalid recipient');
1287
+        }
1288
+
1289
+        if ($share->getShareType() === IShare::TYPE_GROUP) {
1290
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
1291
+            if (is_null($sharedWith)) {
1292
+                throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
1293
+            }
1294
+            $recipient = $this->userManager->get($recipientId);
1295
+            if (!$sharedWith->inGroup($recipient)) {
1296
+                throw new \InvalidArgumentException('Invalid recipient');
1297
+            }
1298
+        }
1299
+
1300
+        [$providerId,] = $this->splitFullId($share->getFullId());
1301
+        $provider = $this->factory->getProvider($providerId);
1302
+
1303
+        return $provider->move($share, $recipientId);
1304
+    }
1305
+
1306
+    public function getSharesInFolder($userId, Folder $node, $reshares = false, $shallow = true) {
1307
+        $providers = $this->factory->getAllProviders();
1308
+
1309
+        return array_reduce($providers, function ($shares, IShareProvider $provider) use ($userId, $node, $reshares, $shallow) {
1310
+            $newShares = $provider->getSharesInFolder($userId, $node, $reshares, $shallow);
1311
+            foreach ($newShares as $fid => $data) {
1312
+                if (!isset($shares[$fid])) {
1313
+                    $shares[$fid] = [];
1314
+                }
1315
+
1316
+                $shares[$fid] = array_merge($shares[$fid], $data);
1317
+            }
1318
+            return $shares;
1319
+        }, []);
1320
+    }
1321
+
1322
+    /**
1323
+     * @inheritdoc
1324
+     */
1325
+    public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
1326
+        if ($path !== null &&
1327
+            !($path instanceof \OCP\Files\File) &&
1328
+            !($path instanceof \OCP\Files\Folder)) {
1329
+            throw new \InvalidArgumentException('invalid path');
1330
+        }
1331
+
1332
+        try {
1333
+            $provider = $this->factory->getProviderForType($shareType);
1334
+        } catch (ProviderException $e) {
1335
+            return [];
1336
+        }
1337
+
1338
+        $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1339
+
1340
+        /*
1341 1341
 		 * Work around so we don't return expired shares but still follow
1342 1342
 		 * proper pagination.
1343 1343
 		 */
1344 1344
 
1345
-		$shares2 = [];
1346
-
1347
-		while (true) {
1348
-			$added = 0;
1349
-			foreach ($shares as $share) {
1350
-				try {
1351
-					$this->checkExpireDate($share);
1352
-				} catch (ShareNotFound $e) {
1353
-					//Ignore since this basically means the share is deleted
1354
-					continue;
1355
-				}
1356
-
1357
-				$added++;
1358
-				$shares2[] = $share;
1359
-
1360
-				if (count($shares2) === $limit) {
1361
-					break;
1362
-				}
1363
-			}
1364
-
1365
-			// If we did not fetch more shares than the limit then there are no more shares
1366
-			if (count($shares) < $limit) {
1367
-				break;
1368
-			}
1369
-
1370
-			if (count($shares2) === $limit) {
1371
-				break;
1372
-			}
1373
-
1374
-			// If there was no limit on the select we are done
1375
-			if ($limit === -1) {
1376
-				break;
1377
-			}
1378
-
1379
-			$offset += $added;
1380
-
1381
-			// Fetch again $limit shares
1382
-			$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1383
-
1384
-			// No more shares means we are done
1385
-			if (empty($shares)) {
1386
-				break;
1387
-			}
1388
-		}
1389
-
1390
-		$shares = $shares2;
1391
-
1392
-		return $shares;
1393
-	}
1394
-
1395
-	/**
1396
-	 * @inheritdoc
1397
-	 */
1398
-	public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1399
-		try {
1400
-			$provider = $this->factory->getProviderForType($shareType);
1401
-		} catch (ProviderException $e) {
1402
-			return [];
1403
-		}
1404
-
1405
-		$shares = $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
1406
-
1407
-		// remove all shares which are already expired
1408
-		foreach ($shares as $key => $share) {
1409
-			try {
1410
-				$this->checkExpireDate($share);
1411
-			} catch (ShareNotFound $e) {
1412
-				unset($shares[$key]);
1413
-			}
1414
-		}
1415
-
1416
-		return $shares;
1417
-	}
1418
-
1419
-	/**
1420
-	 * @inheritdoc
1421
-	 */
1422
-	public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1423
-		$shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);
1424
-
1425
-		// Only get deleted shares
1426
-		$shares = array_filter($shares, function (IShare $share) {
1427
-			return $share->getPermissions() === 0;
1428
-		});
1429
-
1430
-		// Only get shares where the owner still exists
1431
-		$shares = array_filter($shares, function (IShare $share) {
1432
-			return $this->userManager->userExists($share->getShareOwner());
1433
-		});
1434
-
1435
-		return $shares;
1436
-	}
1437
-
1438
-	/**
1439
-	 * @inheritdoc
1440
-	 */
1441
-	public function getShareById($id, $recipient = null) {
1442
-		if ($id === null) {
1443
-			throw new ShareNotFound();
1444
-		}
1445
-
1446
-		[$providerId, $id] = $this->splitFullId($id);
1447
-
1448
-		try {
1449
-			$provider = $this->factory->getProvider($providerId);
1450
-		} catch (ProviderException $e) {
1451
-			throw new ShareNotFound();
1452
-		}
1453
-
1454
-		$share = $provider->getShareById($id, $recipient);
1455
-
1456
-		$this->checkExpireDate($share);
1457
-
1458
-		return $share;
1459
-	}
1460
-
1461
-	/**
1462
-	 * Get all the shares for a given path
1463
-	 *
1464
-	 * @param \OCP\Files\Node $path
1465
-	 * @param int $page
1466
-	 * @param int $perPage
1467
-	 *
1468
-	 * @return Share[]
1469
-	 */
1470
-	public function getSharesByPath(\OCP\Files\Node $path, $page = 0, $perPage = 50) {
1471
-		return [];
1472
-	}
1473
-
1474
-	/**
1475
-	 * Get the share by token possible with password
1476
-	 *
1477
-	 * @param string $token
1478
-	 * @return IShare
1479
-	 *
1480
-	 * @throws ShareNotFound
1481
-	 */
1482
-	public function getShareByToken($token) {
1483
-		// tokens cannot be valid local user names
1484
-		if ($this->userManager->userExists($token)) {
1485
-			throw new ShareNotFound();
1486
-		}
1487
-		$share = null;
1488
-		try {
1489
-			if ($this->shareApiAllowLinks()) {
1490
-				$provider = $this->factory->getProviderForType(IShare::TYPE_LINK);
1491
-				$share = $provider->getShareByToken($token);
1492
-			}
1493
-		} catch (ProviderException $e) {
1494
-		} catch (ShareNotFound $e) {
1495
-		}
1496
-
1497
-
1498
-		// If it is not a link share try to fetch a federated share by token
1499
-		if ($share === null) {
1500
-			try {
1501
-				$provider = $this->factory->getProviderForType(IShare::TYPE_REMOTE);
1502
-				$share = $provider->getShareByToken($token);
1503
-			} catch (ProviderException $e) {
1504
-			} catch (ShareNotFound $e) {
1505
-			}
1506
-		}
1507
-
1508
-		// If it is not a link share try to fetch a mail share by token
1509
-		if ($share === null && $this->shareProviderExists(IShare::TYPE_EMAIL)) {
1510
-			try {
1511
-				$provider = $this->factory->getProviderForType(IShare::TYPE_EMAIL);
1512
-				$share = $provider->getShareByToken($token);
1513
-			} catch (ProviderException $e) {
1514
-			} catch (ShareNotFound $e) {
1515
-			}
1516
-		}
1517
-
1518
-		if ($share === null && $this->shareProviderExists(IShare::TYPE_CIRCLE)) {
1519
-			try {
1520
-				$provider = $this->factory->getProviderForType(IShare::TYPE_CIRCLE);
1521
-				$share = $provider->getShareByToken($token);
1522
-			} catch (ProviderException $e) {
1523
-			} catch (ShareNotFound $e) {
1524
-			}
1525
-		}
1526
-
1527
-		if ($share === null && $this->shareProviderExists(IShare::TYPE_ROOM)) {
1528
-			try {
1529
-				$provider = $this->factory->getProviderForType(IShare::TYPE_ROOM);
1530
-				$share = $provider->getShareByToken($token);
1531
-			} catch (ProviderException $e) {
1532
-			} catch (ShareNotFound $e) {
1533
-			}
1534
-		}
1535
-
1536
-		if ($share === null) {
1537
-			throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1538
-		}
1539
-
1540
-		$this->checkExpireDate($share);
1541
-
1542
-		/*
1345
+        $shares2 = [];
1346
+
1347
+        while (true) {
1348
+            $added = 0;
1349
+            foreach ($shares as $share) {
1350
+                try {
1351
+                    $this->checkExpireDate($share);
1352
+                } catch (ShareNotFound $e) {
1353
+                    //Ignore since this basically means the share is deleted
1354
+                    continue;
1355
+                }
1356
+
1357
+                $added++;
1358
+                $shares2[] = $share;
1359
+
1360
+                if (count($shares2) === $limit) {
1361
+                    break;
1362
+                }
1363
+            }
1364
+
1365
+            // If we did not fetch more shares than the limit then there are no more shares
1366
+            if (count($shares) < $limit) {
1367
+                break;
1368
+            }
1369
+
1370
+            if (count($shares2) === $limit) {
1371
+                break;
1372
+            }
1373
+
1374
+            // If there was no limit on the select we are done
1375
+            if ($limit === -1) {
1376
+                break;
1377
+            }
1378
+
1379
+            $offset += $added;
1380
+
1381
+            // Fetch again $limit shares
1382
+            $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1383
+
1384
+            // No more shares means we are done
1385
+            if (empty($shares)) {
1386
+                break;
1387
+            }
1388
+        }
1389
+
1390
+        $shares = $shares2;
1391
+
1392
+        return $shares;
1393
+    }
1394
+
1395
+    /**
1396
+     * @inheritdoc
1397
+     */
1398
+    public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1399
+        try {
1400
+            $provider = $this->factory->getProviderForType($shareType);
1401
+        } catch (ProviderException $e) {
1402
+            return [];
1403
+        }
1404
+
1405
+        $shares = $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
1406
+
1407
+        // remove all shares which are already expired
1408
+        foreach ($shares as $key => $share) {
1409
+            try {
1410
+                $this->checkExpireDate($share);
1411
+            } catch (ShareNotFound $e) {
1412
+                unset($shares[$key]);
1413
+            }
1414
+        }
1415
+
1416
+        return $shares;
1417
+    }
1418
+
1419
+    /**
1420
+     * @inheritdoc
1421
+     */
1422
+    public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1423
+        $shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);
1424
+
1425
+        // Only get deleted shares
1426
+        $shares = array_filter($shares, function (IShare $share) {
1427
+            return $share->getPermissions() === 0;
1428
+        });
1429
+
1430
+        // Only get shares where the owner still exists
1431
+        $shares = array_filter($shares, function (IShare $share) {
1432
+            return $this->userManager->userExists($share->getShareOwner());
1433
+        });
1434
+
1435
+        return $shares;
1436
+    }
1437
+
1438
+    /**
1439
+     * @inheritdoc
1440
+     */
1441
+    public function getShareById($id, $recipient = null) {
1442
+        if ($id === null) {
1443
+            throw new ShareNotFound();
1444
+        }
1445
+
1446
+        [$providerId, $id] = $this->splitFullId($id);
1447
+
1448
+        try {
1449
+            $provider = $this->factory->getProvider($providerId);
1450
+        } catch (ProviderException $e) {
1451
+            throw new ShareNotFound();
1452
+        }
1453
+
1454
+        $share = $provider->getShareById($id, $recipient);
1455
+
1456
+        $this->checkExpireDate($share);
1457
+
1458
+        return $share;
1459
+    }
1460
+
1461
+    /**
1462
+     * Get all the shares for a given path
1463
+     *
1464
+     * @param \OCP\Files\Node $path
1465
+     * @param int $page
1466
+     * @param int $perPage
1467
+     *
1468
+     * @return Share[]
1469
+     */
1470
+    public function getSharesByPath(\OCP\Files\Node $path, $page = 0, $perPage = 50) {
1471
+        return [];
1472
+    }
1473
+
1474
+    /**
1475
+     * Get the share by token possible with password
1476
+     *
1477
+     * @param string $token
1478
+     * @return IShare
1479
+     *
1480
+     * @throws ShareNotFound
1481
+     */
1482
+    public function getShareByToken($token) {
1483
+        // tokens cannot be valid local user names
1484
+        if ($this->userManager->userExists($token)) {
1485
+            throw new ShareNotFound();
1486
+        }
1487
+        $share = null;
1488
+        try {
1489
+            if ($this->shareApiAllowLinks()) {
1490
+                $provider = $this->factory->getProviderForType(IShare::TYPE_LINK);
1491
+                $share = $provider->getShareByToken($token);
1492
+            }
1493
+        } catch (ProviderException $e) {
1494
+        } catch (ShareNotFound $e) {
1495
+        }
1496
+
1497
+
1498
+        // If it is not a link share try to fetch a federated share by token
1499
+        if ($share === null) {
1500
+            try {
1501
+                $provider = $this->factory->getProviderForType(IShare::TYPE_REMOTE);
1502
+                $share = $provider->getShareByToken($token);
1503
+            } catch (ProviderException $e) {
1504
+            } catch (ShareNotFound $e) {
1505
+            }
1506
+        }
1507
+
1508
+        // If it is not a link share try to fetch a mail share by token
1509
+        if ($share === null && $this->shareProviderExists(IShare::TYPE_EMAIL)) {
1510
+            try {
1511
+                $provider = $this->factory->getProviderForType(IShare::TYPE_EMAIL);
1512
+                $share = $provider->getShareByToken($token);
1513
+            } catch (ProviderException $e) {
1514
+            } catch (ShareNotFound $e) {
1515
+            }
1516
+        }
1517
+
1518
+        if ($share === null && $this->shareProviderExists(IShare::TYPE_CIRCLE)) {
1519
+            try {
1520
+                $provider = $this->factory->getProviderForType(IShare::TYPE_CIRCLE);
1521
+                $share = $provider->getShareByToken($token);
1522
+            } catch (ProviderException $e) {
1523
+            } catch (ShareNotFound $e) {
1524
+            }
1525
+        }
1526
+
1527
+        if ($share === null && $this->shareProviderExists(IShare::TYPE_ROOM)) {
1528
+            try {
1529
+                $provider = $this->factory->getProviderForType(IShare::TYPE_ROOM);
1530
+                $share = $provider->getShareByToken($token);
1531
+            } catch (ProviderException $e) {
1532
+            } catch (ShareNotFound $e) {
1533
+            }
1534
+        }
1535
+
1536
+        if ($share === null) {
1537
+            throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1538
+        }
1539
+
1540
+        $this->checkExpireDate($share);
1541
+
1542
+        /*
1543 1543
 		 * Reduce the permissions for link or email shares if public upload is not enabled
1544 1544
 		 */
1545
-		if (($share->getShareType() === IShare::TYPE_LINK || $share->getShareType() === IShare::TYPE_EMAIL)
1546
-			&& $share->getNodeType() === 'folder' && !$this->shareApiLinkAllowPublicUpload()) {
1547
-			$share->setPermissions($share->getPermissions() & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE));
1548
-		}
1549
-
1550
-		return $share;
1551
-	}
1552
-
1553
-	protected function checkExpireDate($share) {
1554
-		if ($share->isExpired()) {
1555
-			$this->deleteShare($share);
1556
-			throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1557
-		}
1558
-	}
1559
-
1560
-	/**
1561
-	 * Verify the password of a public share
1562
-	 *
1563
-	 * @param IShare $share
1564
-	 * @param ?string $password
1565
-	 * @return bool
1566
-	 */
1567
-	public function checkPassword(IShare $share, $password) {
1568
-		$passwordProtected = $share->getShareType() !== IShare::TYPE_LINK
1569
-			|| $share->getShareType() !== IShare::TYPE_EMAIL
1570
-			|| $share->getShareType() !== IShare::TYPE_CIRCLE;
1571
-		if (!$passwordProtected) {
1572
-			//TODO maybe exception?
1573
-			return false;
1574
-		}
1575
-
1576
-		if ($password === null || $share->getPassword() === null) {
1577
-			return false;
1578
-		}
1579
-
1580
-		// Makes sure password hasn't expired
1581
-		$expirationTime = $share->getPasswordExpirationTime();
1582
-		if ($expirationTime !== null && $expirationTime < new \DateTime()) {
1583
-			return false;
1584
-		}
1585
-
1586
-		$newHash = '';
1587
-		if (!$this->hasher->verify($password, $share->getPassword(), $newHash)) {
1588
-			return false;
1589
-		}
1590
-
1591
-		if (!empty($newHash)) {
1592
-			$share->setPassword($newHash);
1593
-			$provider = $this->factory->getProviderForType($share->getShareType());
1594
-			$provider->update($share);
1595
-		}
1596
-
1597
-		return true;
1598
-	}
1599
-
1600
-	/**
1601
-	 * @inheritdoc
1602
-	 */
1603
-	public function userDeleted($uid) {
1604
-		$types = [IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_LINK, IShare::TYPE_REMOTE, IShare::TYPE_EMAIL];
1605
-
1606
-		foreach ($types as $type) {
1607
-			try {
1608
-				$provider = $this->factory->getProviderForType($type);
1609
-			} catch (ProviderException $e) {
1610
-				continue;
1611
-			}
1612
-			$provider->userDeleted($uid, $type);
1613
-		}
1614
-	}
1615
-
1616
-	/**
1617
-	 * @inheritdoc
1618
-	 */
1619
-	public function groupDeleted($gid) {
1620
-		$provider = $this->factory->getProviderForType(IShare::TYPE_GROUP);
1621
-		$provider->groupDeleted($gid);
1622
-
1623
-		$excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
1624
-		if ($excludedGroups === '') {
1625
-			return;
1626
-		}
1627
-
1628
-		$excludedGroups = json_decode($excludedGroups, true);
1629
-		if (json_last_error() !== JSON_ERROR_NONE) {
1630
-			return;
1631
-		}
1632
-
1633
-		$excludedGroups = array_diff($excludedGroups, [$gid]);
1634
-		$this->config->setAppValue('core', 'shareapi_exclude_groups_list', json_encode($excludedGroups));
1635
-	}
1636
-
1637
-	/**
1638
-	 * @inheritdoc
1639
-	 */
1640
-	public function userDeletedFromGroup($uid, $gid) {
1641
-		$provider = $this->factory->getProviderForType(IShare::TYPE_GROUP);
1642
-		$provider->userDeletedFromGroup($uid, $gid);
1643
-	}
1644
-
1645
-	/**
1646
-	 * Get access list to a path. This means
1647
-	 * all the users that can access a given path.
1648
-	 *
1649
-	 * Consider:
1650
-	 * -root
1651
-	 * |-folder1 (23)
1652
-	 *  |-folder2 (32)
1653
-	 *   |-fileA (42)
1654
-	 *
1655
-	 * fileA is shared with user1 and user1@server1
1656
-	 * folder2 is shared with group2 (user4 is a member of group2)
1657
-	 * folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
1658
-	 *
1659
-	 * Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
1660
-	 * [
1661
-	 *  users  => [
1662
-	 *      'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
1663
-	 *      'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
1664
-	 *      'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
1665
-	 *  ],
1666
-	 *  remote => [
1667
-	 *      'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
1668
-	 *      'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
1669
-	 *  ],
1670
-	 *  public => bool
1671
-	 *  mail => bool
1672
-	 * ]
1673
-	 *
1674
-	 * The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
1675
-	 * [
1676
-	 *  users  => ['user1', 'user2', 'user4'],
1677
-	 *  remote => bool,
1678
-	 *  public => bool
1679
-	 *  mail => bool
1680
-	 * ]
1681
-	 *
1682
-	 * This is required for encryption/activity
1683
-	 *
1684
-	 * @param \OCP\Files\Node $path
1685
-	 * @param bool $recursive Should we check all parent folders as well
1686
-	 * @param bool $currentAccess Ensure the recipient has access to the file (e.g. did not unshare it)
1687
-	 * @return array
1688
-	 */
1689
-	public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
1690
-		$owner = $path->getOwner();
1691
-
1692
-		if ($owner === null) {
1693
-			return [];
1694
-		}
1695
-
1696
-		$owner = $owner->getUID();
1697
-
1698
-		if ($currentAccess) {
1699
-			$al = ['users' => [], 'remote' => [], 'public' => false];
1700
-		} else {
1701
-			$al = ['users' => [], 'remote' => false, 'public' => false];
1702
-		}
1703
-		if (!$this->userManager->userExists($owner)) {
1704
-			return $al;
1705
-		}
1706
-
1707
-		//Get node for the owner and correct the owner in case of external storage
1708
-		$userFolder = $this->rootFolder->getUserFolder($owner);
1709
-		if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) {
1710
-			$nodes = $userFolder->getById($path->getId());
1711
-			$path = array_shift($nodes);
1712
-			if ($path === null || $path->getOwner() === null) {
1713
-				return [];
1714
-			}
1715
-			$owner = $path->getOwner()->getUID();
1716
-		}
1717
-
1718
-		$providers = $this->factory->getAllProviders();
1719
-
1720
-		/** @var Node[] $nodes */
1721
-		$nodes = [];
1722
-
1723
-
1724
-		if ($currentAccess) {
1725
-			$ownerPath = $path->getPath();
1726
-			$ownerPath = explode('/', $ownerPath, 4);
1727
-			if (count($ownerPath) < 4) {
1728
-				$ownerPath = '';
1729
-			} else {
1730
-				$ownerPath = $ownerPath[3];
1731
-			}
1732
-			$al['users'][$owner] = [
1733
-				'node_id' => $path->getId(),
1734
-				'node_path' => '/' . $ownerPath,
1735
-			];
1736
-		} else {
1737
-			$al['users'][] = $owner;
1738
-		}
1739
-
1740
-		// Collect all the shares
1741
-		while ($path->getPath() !== $userFolder->getPath()) {
1742
-			$nodes[] = $path;
1743
-			if (!$recursive) {
1744
-				break;
1745
-			}
1746
-			$path = $path->getParent();
1747
-		}
1748
-
1749
-		foreach ($providers as $provider) {
1750
-			$tmp = $provider->getAccessList($nodes, $currentAccess);
1751
-
1752
-			foreach ($tmp as $k => $v) {
1753
-				if (isset($al[$k])) {
1754
-					if (is_array($al[$k])) {
1755
-						if ($currentAccess) {
1756
-							$al[$k] += $v;
1757
-						} else {
1758
-							$al[$k] = array_merge($al[$k], $v);
1759
-							$al[$k] = array_unique($al[$k]);
1760
-							$al[$k] = array_values($al[$k]);
1761
-						}
1762
-					} else {
1763
-						$al[$k] = $al[$k] || $v;
1764
-					}
1765
-				} else {
1766
-					$al[$k] = $v;
1767
-				}
1768
-			}
1769
-		}
1770
-
1771
-		return $al;
1772
-	}
1773
-
1774
-	/**
1775
-	 * Create a new share
1776
-	 *
1777
-	 * @return IShare
1778
-	 */
1779
-	public function newShare() {
1780
-		return new \OC\Share20\Share($this->rootFolder, $this->userManager);
1781
-	}
1782
-
1783
-	/**
1784
-	 * Is the share API enabled
1785
-	 *
1786
-	 * @return bool
1787
-	 */
1788
-	public function shareApiEnabled() {
1789
-		return $this->config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes';
1790
-	}
1791
-
1792
-	/**
1793
-	 * Is public link sharing enabled
1794
-	 *
1795
-	 * @return bool
1796
-	 */
1797
-	public function shareApiAllowLinks() {
1798
-		if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
1799
-			return false;
1800
-		}
1801
-
1802
-		$user = $this->userSession->getUser();
1803
-		if ($user) {
1804
-			$excludedGroups = json_decode($this->config->getAppValue('core', 'shareapi_allow_links_exclude_groups', '[]'));
1805
-			if ($excludedGroups) {
1806
-				$userGroups = $this->groupManager->getUserGroupIds($user);
1807
-				return !(bool)array_intersect($excludedGroups, $userGroups);
1808
-			}
1809
-		}
1810
-
1811
-		return true;
1812
-	}
1813
-
1814
-	/**
1815
-	 * Is password on public link requires
1816
-	 *
1817
-	 * @param bool Check group membership exclusion
1818
-	 * @return bool
1819
-	 */
1820
-	public function shareApiLinkEnforcePassword(bool $checkGroupMembership = true) {
1821
-		$excludedGroups = $this->config->getAppValue('core', 'shareapi_enforce_links_password_excluded_groups', '');
1822
-		if ($excludedGroups !== '' && $checkGroupMembership) {
1823
-			$excludedGroups = json_decode($excludedGroups);
1824
-			$user = $this->userSession->getUser();
1825
-			if ($user) {
1826
-				$userGroups = $this->groupManager->getUserGroupIds($user);
1827
-				if ((bool)array_intersect($excludedGroups, $userGroups)) {
1828
-					return false;
1829
-				}
1830
-			}
1831
-		}
1832
-		return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes';
1833
-	}
1834
-
1835
-	/**
1836
-	 * Is default link expire date enabled
1837
-	 *
1838
-	 * @return bool
1839
-	 */
1840
-	public function shareApiLinkDefaultExpireDate() {
1841
-		return $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
1842
-	}
1843
-
1844
-	/**
1845
-	 * Is default link expire date enforced
1846
-	 *`
1847
-	 *
1848
-	 * @return bool
1849
-	 */
1850
-	public function shareApiLinkDefaultExpireDateEnforced() {
1851
-		return $this->shareApiLinkDefaultExpireDate() &&
1852
-			$this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
1853
-	}
1854
-
1855
-
1856
-	/**
1857
-	 * Number of default link expire days
1858
-	 *
1859
-	 * @return int
1860
-	 */
1861
-	public function shareApiLinkDefaultExpireDays() {
1862
-		return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1863
-	}
1864
-
1865
-	/**
1866
-	 * Is default internal expire date enabled
1867
-	 *
1868
-	 * @return bool
1869
-	 */
1870
-	public function shareApiInternalDefaultExpireDate(): bool {
1871
-		return $this->config->getAppValue('core', 'shareapi_default_internal_expire_date', 'no') === 'yes';
1872
-	}
1873
-
1874
-	/**
1875
-	 * Is default remote expire date enabled
1876
-	 *
1877
-	 * @return bool
1878
-	 */
1879
-	public function shareApiRemoteDefaultExpireDate(): bool {
1880
-		return $this->config->getAppValue('core', 'shareapi_default_remote_expire_date', 'no') === 'yes';
1881
-	}
1882
-
1883
-	/**
1884
-	 * Is default expire date enforced
1885
-	 *
1886
-	 * @return bool
1887
-	 */
1888
-	public function shareApiInternalDefaultExpireDateEnforced(): bool {
1889
-		return $this->shareApiInternalDefaultExpireDate() &&
1890
-			$this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no') === 'yes';
1891
-	}
1892
-
1893
-	/**
1894
-	 * Is default expire date enforced for remote shares
1895
-	 *
1896
-	 * @return bool
1897
-	 */
1898
-	public function shareApiRemoteDefaultExpireDateEnforced(): bool {
1899
-		return $this->shareApiRemoteDefaultExpireDate() &&
1900
-			$this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no') === 'yes';
1901
-	}
1902
-
1903
-	/**
1904
-	 * Number of default expire days
1905
-	 *
1906
-	 * @return int
1907
-	 */
1908
-	public function shareApiInternalDefaultExpireDays(): int {
1909
-		return (int)$this->config->getAppValue('core', 'shareapi_internal_expire_after_n_days', '7');
1910
-	}
1911
-
1912
-	/**
1913
-	 * Number of default expire days for remote shares
1914
-	 *
1915
-	 * @return int
1916
-	 */
1917
-	public function shareApiRemoteDefaultExpireDays(): int {
1918
-		return (int)$this->config->getAppValue('core', 'shareapi_remote_expire_after_n_days', '7');
1919
-	}
1920
-
1921
-	/**
1922
-	 * Allow public upload on link shares
1923
-	 *
1924
-	 * @return bool
1925
-	 */
1926
-	public function shareApiLinkAllowPublicUpload() {
1927
-		return $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
1928
-	}
1929
-
1930
-	/**
1931
-	 * check if user can only share with group members
1932
-	 *
1933
-	 * @return bool
1934
-	 */
1935
-	public function shareWithGroupMembersOnly() {
1936
-		return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
1937
-	}
1938
-
1939
-	/**
1940
-	 * Check if users can share with groups
1941
-	 *
1942
-	 * @return bool
1943
-	 */
1944
-	public function allowGroupSharing() {
1945
-		return $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes';
1946
-	}
1947
-
1948
-	public function allowEnumeration(): bool {
1949
-		return $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
1950
-	}
1951
-
1952
-	public function limitEnumerationToGroups(): bool {
1953
-		return $this->allowEnumeration() &&
1954
-			$this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
1955
-	}
1956
-
1957
-	public function limitEnumerationToPhone(): bool {
1958
-		return $this->allowEnumeration() &&
1959
-			$this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
1960
-	}
1961
-
1962
-	public function allowEnumerationFullMatch(): bool {
1963
-		return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes';
1964
-	}
1965
-
1966
-	public function matchEmail(): bool {
1967
-		return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes';
1968
-	}
1969
-
1970
-	public function ignoreSecondDisplayName(): bool {
1971
-		return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no') === 'yes';
1972
-	}
1973
-
1974
-	public function currentUserCanEnumerateTargetUser(?IUser $currentUser, IUser $targetUser): bool {
1975
-		if ($this->allowEnumerationFullMatch()) {
1976
-			return true;
1977
-		}
1978
-
1979
-		if (!$this->allowEnumeration()) {
1980
-			return false;
1981
-		}
1982
-
1983
-		if (!$this->limitEnumerationToPhone() && !$this->limitEnumerationToGroups()) {
1984
-			// Enumeration is enabled and not restricted: OK
1985
-			return true;
1986
-		}
1987
-
1988
-		if (!$currentUser instanceof IUser) {
1989
-			// Enumeration restrictions require an account
1990
-			return false;
1991
-		}
1992
-
1993
-		// Enumeration is limited to phone match
1994
-		if ($this->limitEnumerationToPhone() && $this->knownUserService->isKnownToUser($currentUser->getUID(), $targetUser->getUID())) {
1995
-			return true;
1996
-		}
1997
-
1998
-		// Enumeration is limited to groups
1999
-		if ($this->limitEnumerationToGroups()) {
2000
-			$currentUserGroupIds = $this->groupManager->getUserGroupIds($currentUser);
2001
-			$targetUserGroupIds = $this->groupManager->getUserGroupIds($targetUser);
2002
-			if (!empty(array_intersect($currentUserGroupIds, $targetUserGroupIds))) {
2003
-				return true;
2004
-			}
2005
-		}
2006
-
2007
-		return false;
2008
-	}
2009
-
2010
-	/**
2011
-	 * Copied from \OC_Util::isSharingDisabledForUser
2012
-	 *
2013
-	 * TODO: Deprecate function from OC_Util
2014
-	 *
2015
-	 * @param string $userId
2016
-	 * @return bool
2017
-	 */
2018
-	public function sharingDisabledForUser($userId) {
2019
-		if ($userId === null) {
2020
-			return false;
2021
-		}
2022
-
2023
-		if (isset($this->sharingDisabledForUsersCache[$userId])) {
2024
-			return $this->sharingDisabledForUsersCache[$userId];
2025
-		}
2026
-
2027
-		if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
2028
-			$groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
2029
-			$excludedGroups = json_decode($groupsList);
2030
-			if (is_null($excludedGroups)) {
2031
-				$excludedGroups = explode(',', $groupsList);
2032
-				$newValue = json_encode($excludedGroups);
2033
-				$this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
2034
-			}
2035
-			$user = $this->userManager->get($userId);
2036
-			$usersGroups = $this->groupManager->getUserGroupIds($user);
2037
-			if (!empty($usersGroups)) {
2038
-				$remainingGroups = array_diff($usersGroups, $excludedGroups);
2039
-				// if the user is only in groups which are disabled for sharing then
2040
-				// sharing is also disabled for the user
2041
-				if (empty($remainingGroups)) {
2042
-					$this->sharingDisabledForUsersCache[$userId] = true;
2043
-					return true;
2044
-				}
2045
-			}
2046
-		}
2047
-
2048
-		$this->sharingDisabledForUsersCache[$userId] = false;
2049
-		return false;
2050
-	}
2051
-
2052
-	/**
2053
-	 * @inheritdoc
2054
-	 */
2055
-	public function outgoingServer2ServerSharesAllowed() {
2056
-		return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
2057
-	}
2058
-
2059
-	/**
2060
-	 * @inheritdoc
2061
-	 */
2062
-	public function outgoingServer2ServerGroupSharesAllowed() {
2063
-		return $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no') === 'yes';
2064
-	}
2065
-
2066
-	/**
2067
-	 * @inheritdoc
2068
-	 */
2069
-	public function shareProviderExists($shareType) {
2070
-		try {
2071
-			$this->factory->getProviderForType($shareType);
2072
-		} catch (ProviderException $e) {
2073
-			return false;
2074
-		}
2075
-
2076
-		return true;
2077
-	}
2078
-
2079
-	public function registerShareProvider(string $shareProviderClass): void {
2080
-		$this->factory->registerProvider($shareProviderClass);
2081
-	}
2082
-
2083
-	public function getAllShares(): iterable {
2084
-		$providers = $this->factory->getAllProviders();
2085
-
2086
-		foreach ($providers as $provider) {
2087
-			yield from $provider->getAllShares();
2088
-		}
2089
-	}
1545
+        if (($share->getShareType() === IShare::TYPE_LINK || $share->getShareType() === IShare::TYPE_EMAIL)
1546
+            && $share->getNodeType() === 'folder' && !$this->shareApiLinkAllowPublicUpload()) {
1547
+            $share->setPermissions($share->getPermissions() & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE));
1548
+        }
1549
+
1550
+        return $share;
1551
+    }
1552
+
1553
+    protected function checkExpireDate($share) {
1554
+        if ($share->isExpired()) {
1555
+            $this->deleteShare($share);
1556
+            throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1557
+        }
1558
+    }
1559
+
1560
+    /**
1561
+     * Verify the password of a public share
1562
+     *
1563
+     * @param IShare $share
1564
+     * @param ?string $password
1565
+     * @return bool
1566
+     */
1567
+    public function checkPassword(IShare $share, $password) {
1568
+        $passwordProtected = $share->getShareType() !== IShare::TYPE_LINK
1569
+            || $share->getShareType() !== IShare::TYPE_EMAIL
1570
+            || $share->getShareType() !== IShare::TYPE_CIRCLE;
1571
+        if (!$passwordProtected) {
1572
+            //TODO maybe exception?
1573
+            return false;
1574
+        }
1575
+
1576
+        if ($password === null || $share->getPassword() === null) {
1577
+            return false;
1578
+        }
1579
+
1580
+        // Makes sure password hasn't expired
1581
+        $expirationTime = $share->getPasswordExpirationTime();
1582
+        if ($expirationTime !== null && $expirationTime < new \DateTime()) {
1583
+            return false;
1584
+        }
1585
+
1586
+        $newHash = '';
1587
+        if (!$this->hasher->verify($password, $share->getPassword(), $newHash)) {
1588
+            return false;
1589
+        }
1590
+
1591
+        if (!empty($newHash)) {
1592
+            $share->setPassword($newHash);
1593
+            $provider = $this->factory->getProviderForType($share->getShareType());
1594
+            $provider->update($share);
1595
+        }
1596
+
1597
+        return true;
1598
+    }
1599
+
1600
+    /**
1601
+     * @inheritdoc
1602
+     */
1603
+    public function userDeleted($uid) {
1604
+        $types = [IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_LINK, IShare::TYPE_REMOTE, IShare::TYPE_EMAIL];
1605
+
1606
+        foreach ($types as $type) {
1607
+            try {
1608
+                $provider = $this->factory->getProviderForType($type);
1609
+            } catch (ProviderException $e) {
1610
+                continue;
1611
+            }
1612
+            $provider->userDeleted($uid, $type);
1613
+        }
1614
+    }
1615
+
1616
+    /**
1617
+     * @inheritdoc
1618
+     */
1619
+    public function groupDeleted($gid) {
1620
+        $provider = $this->factory->getProviderForType(IShare::TYPE_GROUP);
1621
+        $provider->groupDeleted($gid);
1622
+
1623
+        $excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
1624
+        if ($excludedGroups === '') {
1625
+            return;
1626
+        }
1627
+
1628
+        $excludedGroups = json_decode($excludedGroups, true);
1629
+        if (json_last_error() !== JSON_ERROR_NONE) {
1630
+            return;
1631
+        }
1632
+
1633
+        $excludedGroups = array_diff($excludedGroups, [$gid]);
1634
+        $this->config->setAppValue('core', 'shareapi_exclude_groups_list', json_encode($excludedGroups));
1635
+    }
1636
+
1637
+    /**
1638
+     * @inheritdoc
1639
+     */
1640
+    public function userDeletedFromGroup($uid, $gid) {
1641
+        $provider = $this->factory->getProviderForType(IShare::TYPE_GROUP);
1642
+        $provider->userDeletedFromGroup($uid, $gid);
1643
+    }
1644
+
1645
+    /**
1646
+     * Get access list to a path. This means
1647
+     * all the users that can access a given path.
1648
+     *
1649
+     * Consider:
1650
+     * -root
1651
+     * |-folder1 (23)
1652
+     *  |-folder2 (32)
1653
+     *   |-fileA (42)
1654
+     *
1655
+     * fileA is shared with user1 and user1@server1
1656
+     * folder2 is shared with group2 (user4 is a member of group2)
1657
+     * folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
1658
+     *
1659
+     * Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
1660
+     * [
1661
+     *  users  => [
1662
+     *      'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
1663
+     *      'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
1664
+     *      'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
1665
+     *  ],
1666
+     *  remote => [
1667
+     *      'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
1668
+     *      'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
1669
+     *  ],
1670
+     *  public => bool
1671
+     *  mail => bool
1672
+     * ]
1673
+     *
1674
+     * The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
1675
+     * [
1676
+     *  users  => ['user1', 'user2', 'user4'],
1677
+     *  remote => bool,
1678
+     *  public => bool
1679
+     *  mail => bool
1680
+     * ]
1681
+     *
1682
+     * This is required for encryption/activity
1683
+     *
1684
+     * @param \OCP\Files\Node $path
1685
+     * @param bool $recursive Should we check all parent folders as well
1686
+     * @param bool $currentAccess Ensure the recipient has access to the file (e.g. did not unshare it)
1687
+     * @return array
1688
+     */
1689
+    public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
1690
+        $owner = $path->getOwner();
1691
+
1692
+        if ($owner === null) {
1693
+            return [];
1694
+        }
1695
+
1696
+        $owner = $owner->getUID();
1697
+
1698
+        if ($currentAccess) {
1699
+            $al = ['users' => [], 'remote' => [], 'public' => false];
1700
+        } else {
1701
+            $al = ['users' => [], 'remote' => false, 'public' => false];
1702
+        }
1703
+        if (!$this->userManager->userExists($owner)) {
1704
+            return $al;
1705
+        }
1706
+
1707
+        //Get node for the owner and correct the owner in case of external storage
1708
+        $userFolder = $this->rootFolder->getUserFolder($owner);
1709
+        if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) {
1710
+            $nodes = $userFolder->getById($path->getId());
1711
+            $path = array_shift($nodes);
1712
+            if ($path === null || $path->getOwner() === null) {
1713
+                return [];
1714
+            }
1715
+            $owner = $path->getOwner()->getUID();
1716
+        }
1717
+
1718
+        $providers = $this->factory->getAllProviders();
1719
+
1720
+        /** @var Node[] $nodes */
1721
+        $nodes = [];
1722
+
1723
+
1724
+        if ($currentAccess) {
1725
+            $ownerPath = $path->getPath();
1726
+            $ownerPath = explode('/', $ownerPath, 4);
1727
+            if (count($ownerPath) < 4) {
1728
+                $ownerPath = '';
1729
+            } else {
1730
+                $ownerPath = $ownerPath[3];
1731
+            }
1732
+            $al['users'][$owner] = [
1733
+                'node_id' => $path->getId(),
1734
+                'node_path' => '/' . $ownerPath,
1735
+            ];
1736
+        } else {
1737
+            $al['users'][] = $owner;
1738
+        }
1739
+
1740
+        // Collect all the shares
1741
+        while ($path->getPath() !== $userFolder->getPath()) {
1742
+            $nodes[] = $path;
1743
+            if (!$recursive) {
1744
+                break;
1745
+            }
1746
+            $path = $path->getParent();
1747
+        }
1748
+
1749
+        foreach ($providers as $provider) {
1750
+            $tmp = $provider->getAccessList($nodes, $currentAccess);
1751
+
1752
+            foreach ($tmp as $k => $v) {
1753
+                if (isset($al[$k])) {
1754
+                    if (is_array($al[$k])) {
1755
+                        if ($currentAccess) {
1756
+                            $al[$k] += $v;
1757
+                        } else {
1758
+                            $al[$k] = array_merge($al[$k], $v);
1759
+                            $al[$k] = array_unique($al[$k]);
1760
+                            $al[$k] = array_values($al[$k]);
1761
+                        }
1762
+                    } else {
1763
+                        $al[$k] = $al[$k] || $v;
1764
+                    }
1765
+                } else {
1766
+                    $al[$k] = $v;
1767
+                }
1768
+            }
1769
+        }
1770
+
1771
+        return $al;
1772
+    }
1773
+
1774
+    /**
1775
+     * Create a new share
1776
+     *
1777
+     * @return IShare
1778
+     */
1779
+    public function newShare() {
1780
+        return new \OC\Share20\Share($this->rootFolder, $this->userManager);
1781
+    }
1782
+
1783
+    /**
1784
+     * Is the share API enabled
1785
+     *
1786
+     * @return bool
1787
+     */
1788
+    public function shareApiEnabled() {
1789
+        return $this->config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes';
1790
+    }
1791
+
1792
+    /**
1793
+     * Is public link sharing enabled
1794
+     *
1795
+     * @return bool
1796
+     */
1797
+    public function shareApiAllowLinks() {
1798
+        if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
1799
+            return false;
1800
+        }
1801
+
1802
+        $user = $this->userSession->getUser();
1803
+        if ($user) {
1804
+            $excludedGroups = json_decode($this->config->getAppValue('core', 'shareapi_allow_links_exclude_groups', '[]'));
1805
+            if ($excludedGroups) {
1806
+                $userGroups = $this->groupManager->getUserGroupIds($user);
1807
+                return !(bool)array_intersect($excludedGroups, $userGroups);
1808
+            }
1809
+        }
1810
+
1811
+        return true;
1812
+    }
1813
+
1814
+    /**
1815
+     * Is password on public link requires
1816
+     *
1817
+     * @param bool Check group membership exclusion
1818
+     * @return bool
1819
+     */
1820
+    public function shareApiLinkEnforcePassword(bool $checkGroupMembership = true) {
1821
+        $excludedGroups = $this->config->getAppValue('core', 'shareapi_enforce_links_password_excluded_groups', '');
1822
+        if ($excludedGroups !== '' && $checkGroupMembership) {
1823
+            $excludedGroups = json_decode($excludedGroups);
1824
+            $user = $this->userSession->getUser();
1825
+            if ($user) {
1826
+                $userGroups = $this->groupManager->getUserGroupIds($user);
1827
+                if ((bool)array_intersect($excludedGroups, $userGroups)) {
1828
+                    return false;
1829
+                }
1830
+            }
1831
+        }
1832
+        return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes';
1833
+    }
1834
+
1835
+    /**
1836
+     * Is default link expire date enabled
1837
+     *
1838
+     * @return bool
1839
+     */
1840
+    public function shareApiLinkDefaultExpireDate() {
1841
+        return $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
1842
+    }
1843
+
1844
+    /**
1845
+     * Is default link expire date enforced
1846
+     *`
1847
+     *
1848
+     * @return bool
1849
+     */
1850
+    public function shareApiLinkDefaultExpireDateEnforced() {
1851
+        return $this->shareApiLinkDefaultExpireDate() &&
1852
+            $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
1853
+    }
1854
+
1855
+
1856
+    /**
1857
+     * Number of default link expire days
1858
+     *
1859
+     * @return int
1860
+     */
1861
+    public function shareApiLinkDefaultExpireDays() {
1862
+        return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1863
+    }
1864
+
1865
+    /**
1866
+     * Is default internal expire date enabled
1867
+     *
1868
+     * @return bool
1869
+     */
1870
+    public function shareApiInternalDefaultExpireDate(): bool {
1871
+        return $this->config->getAppValue('core', 'shareapi_default_internal_expire_date', 'no') === 'yes';
1872
+    }
1873
+
1874
+    /**
1875
+     * Is default remote expire date enabled
1876
+     *
1877
+     * @return bool
1878
+     */
1879
+    public function shareApiRemoteDefaultExpireDate(): bool {
1880
+        return $this->config->getAppValue('core', 'shareapi_default_remote_expire_date', 'no') === 'yes';
1881
+    }
1882
+
1883
+    /**
1884
+     * Is default expire date enforced
1885
+     *
1886
+     * @return bool
1887
+     */
1888
+    public function shareApiInternalDefaultExpireDateEnforced(): bool {
1889
+        return $this->shareApiInternalDefaultExpireDate() &&
1890
+            $this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no') === 'yes';
1891
+    }
1892
+
1893
+    /**
1894
+     * Is default expire date enforced for remote shares
1895
+     *
1896
+     * @return bool
1897
+     */
1898
+    public function shareApiRemoteDefaultExpireDateEnforced(): bool {
1899
+        return $this->shareApiRemoteDefaultExpireDate() &&
1900
+            $this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no') === 'yes';
1901
+    }
1902
+
1903
+    /**
1904
+     * Number of default expire days
1905
+     *
1906
+     * @return int
1907
+     */
1908
+    public function shareApiInternalDefaultExpireDays(): int {
1909
+        return (int)$this->config->getAppValue('core', 'shareapi_internal_expire_after_n_days', '7');
1910
+    }
1911
+
1912
+    /**
1913
+     * Number of default expire days for remote shares
1914
+     *
1915
+     * @return int
1916
+     */
1917
+    public function shareApiRemoteDefaultExpireDays(): int {
1918
+        return (int)$this->config->getAppValue('core', 'shareapi_remote_expire_after_n_days', '7');
1919
+    }
1920
+
1921
+    /**
1922
+     * Allow public upload on link shares
1923
+     *
1924
+     * @return bool
1925
+     */
1926
+    public function shareApiLinkAllowPublicUpload() {
1927
+        return $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
1928
+    }
1929
+
1930
+    /**
1931
+     * check if user can only share with group members
1932
+     *
1933
+     * @return bool
1934
+     */
1935
+    public function shareWithGroupMembersOnly() {
1936
+        return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
1937
+    }
1938
+
1939
+    /**
1940
+     * Check if users can share with groups
1941
+     *
1942
+     * @return bool
1943
+     */
1944
+    public function allowGroupSharing() {
1945
+        return $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes';
1946
+    }
1947
+
1948
+    public function allowEnumeration(): bool {
1949
+        return $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
1950
+    }
1951
+
1952
+    public function limitEnumerationToGroups(): bool {
1953
+        return $this->allowEnumeration() &&
1954
+            $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
1955
+    }
1956
+
1957
+    public function limitEnumerationToPhone(): bool {
1958
+        return $this->allowEnumeration() &&
1959
+            $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
1960
+    }
1961
+
1962
+    public function allowEnumerationFullMatch(): bool {
1963
+        return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes';
1964
+    }
1965
+
1966
+    public function matchEmail(): bool {
1967
+        return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_email', 'yes') === 'yes';
1968
+    }
1969
+
1970
+    public function ignoreSecondDisplayName(): bool {
1971
+        return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no') === 'yes';
1972
+    }
1973
+
1974
+    public function currentUserCanEnumerateTargetUser(?IUser $currentUser, IUser $targetUser): bool {
1975
+        if ($this->allowEnumerationFullMatch()) {
1976
+            return true;
1977
+        }
1978
+
1979
+        if (!$this->allowEnumeration()) {
1980
+            return false;
1981
+        }
1982
+
1983
+        if (!$this->limitEnumerationToPhone() && !$this->limitEnumerationToGroups()) {
1984
+            // Enumeration is enabled and not restricted: OK
1985
+            return true;
1986
+        }
1987
+
1988
+        if (!$currentUser instanceof IUser) {
1989
+            // Enumeration restrictions require an account
1990
+            return false;
1991
+        }
1992
+
1993
+        // Enumeration is limited to phone match
1994
+        if ($this->limitEnumerationToPhone() && $this->knownUserService->isKnownToUser($currentUser->getUID(), $targetUser->getUID())) {
1995
+            return true;
1996
+        }
1997
+
1998
+        // Enumeration is limited to groups
1999
+        if ($this->limitEnumerationToGroups()) {
2000
+            $currentUserGroupIds = $this->groupManager->getUserGroupIds($currentUser);
2001
+            $targetUserGroupIds = $this->groupManager->getUserGroupIds($targetUser);
2002
+            if (!empty(array_intersect($currentUserGroupIds, $targetUserGroupIds))) {
2003
+                return true;
2004
+            }
2005
+        }
2006
+
2007
+        return false;
2008
+    }
2009
+
2010
+    /**
2011
+     * Copied from \OC_Util::isSharingDisabledForUser
2012
+     *
2013
+     * TODO: Deprecate function from OC_Util
2014
+     *
2015
+     * @param string $userId
2016
+     * @return bool
2017
+     */
2018
+    public function sharingDisabledForUser($userId) {
2019
+        if ($userId === null) {
2020
+            return false;
2021
+        }
2022
+
2023
+        if (isset($this->sharingDisabledForUsersCache[$userId])) {
2024
+            return $this->sharingDisabledForUsersCache[$userId];
2025
+        }
2026
+
2027
+        if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
2028
+            $groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
2029
+            $excludedGroups = json_decode($groupsList);
2030
+            if (is_null($excludedGroups)) {
2031
+                $excludedGroups = explode(',', $groupsList);
2032
+                $newValue = json_encode($excludedGroups);
2033
+                $this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
2034
+            }
2035
+            $user = $this->userManager->get($userId);
2036
+            $usersGroups = $this->groupManager->getUserGroupIds($user);
2037
+            if (!empty($usersGroups)) {
2038
+                $remainingGroups = array_diff($usersGroups, $excludedGroups);
2039
+                // if the user is only in groups which are disabled for sharing then
2040
+                // sharing is also disabled for the user
2041
+                if (empty($remainingGroups)) {
2042
+                    $this->sharingDisabledForUsersCache[$userId] = true;
2043
+                    return true;
2044
+                }
2045
+            }
2046
+        }
2047
+
2048
+        $this->sharingDisabledForUsersCache[$userId] = false;
2049
+        return false;
2050
+    }
2051
+
2052
+    /**
2053
+     * @inheritdoc
2054
+     */
2055
+    public function outgoingServer2ServerSharesAllowed() {
2056
+        return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
2057
+    }
2058
+
2059
+    /**
2060
+     * @inheritdoc
2061
+     */
2062
+    public function outgoingServer2ServerGroupSharesAllowed() {
2063
+        return $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no') === 'yes';
2064
+    }
2065
+
2066
+    /**
2067
+     * @inheritdoc
2068
+     */
2069
+    public function shareProviderExists($shareType) {
2070
+        try {
2071
+            $this->factory->getProviderForType($shareType);
2072
+        } catch (ProviderException $e) {
2073
+            return false;
2074
+        }
2075
+
2076
+        return true;
2077
+    }
2078
+
2079
+    public function registerShareProvider(string $shareProviderClass): void {
2080
+        $this->factory->registerProvider($shareProviderClass);
2081
+    }
2082
+
2083
+    public function getAllShares(): iterable {
2084
+        $providers = $this->factory->getAllProviders();
2085
+
2086
+        foreach ($providers as $provider) {
2087
+            yield from $provider->getAllShares();
2088
+        }
2089
+    }
2090 2090
 }
Please login to merge, or discard this patch.
lib/private/Share20/ProviderFactory.php 1 patch
Indentation   +324 added lines, -324 removed lines patch added patch discarded remove patch
@@ -56,337 +56,337 @@
 block discarded – undo
56 56
  * @package OC\Share20
57 57
  */
58 58
 class ProviderFactory implements IProviderFactory {
59
-	/** @var IServerContainer */
60
-	private $serverContainer;
61
-	/** @var DefaultShareProvider */
62
-	private $defaultProvider = null;
63
-	/** @var FederatedShareProvider */
64
-	private $federatedProvider = null;
65
-	/** @var  ShareByMailProvider */
66
-	private $shareByMailProvider;
67
-	/** @var  \OCA\Circles\ShareByCircleProvider */
68
-	private $shareByCircleProvider = null;
69
-	/** @var bool */
70
-	private $circlesAreNotAvailable = false;
71
-	/** @var \OCA\Talk\Share\RoomShareProvider */
72
-	private $roomShareProvider = null;
73
-
74
-	private $registeredShareProviders = [];
75
-
76
-	private $shareProviders = [];
77
-
78
-	/**
79
-	 * IProviderFactory constructor.
80
-	 *
81
-	 * @param IServerContainer $serverContainer
82
-	 */
83
-	public function __construct(IServerContainer $serverContainer) {
84
-		$this->serverContainer = $serverContainer;
85
-	}
86
-
87
-	public function registerProvider(string $shareProviderClass): void {
88
-		$this->registeredShareProviders[] = $shareProviderClass;
89
-	}
90
-
91
-	/**
92
-	 * Create the default share provider.
93
-	 *
94
-	 * @return DefaultShareProvider
95
-	 */
96
-	protected function defaultShareProvider() {
97
-		if ($this->defaultProvider === null) {
98
-			$this->defaultProvider = new DefaultShareProvider(
99
-				$this->serverContainer->getDatabaseConnection(),
100
-				$this->serverContainer->getUserManager(),
101
-				$this->serverContainer->getGroupManager(),
102
-				$this->serverContainer->getLazyRootFolder(),
103
-				$this->serverContainer->getMailer(),
104
-				$this->serverContainer->query(Defaults::class),
105
-				$this->serverContainer->getL10NFactory(),
106
-				$this->serverContainer->getURLGenerator(),
107
-				$this->serverContainer->getConfig()
108
-			);
109
-		}
110
-
111
-		return $this->defaultProvider;
112
-	}
113
-
114
-	/**
115
-	 * Create the federated share provider
116
-	 *
117
-	 * @return FederatedShareProvider
118
-	 */
119
-	protected function federatedShareProvider() {
120
-		if ($this->federatedProvider === null) {
121
-			/*
59
+    /** @var IServerContainer */
60
+    private $serverContainer;
61
+    /** @var DefaultShareProvider */
62
+    private $defaultProvider = null;
63
+    /** @var FederatedShareProvider */
64
+    private $federatedProvider = null;
65
+    /** @var  ShareByMailProvider */
66
+    private $shareByMailProvider;
67
+    /** @var  \OCA\Circles\ShareByCircleProvider */
68
+    private $shareByCircleProvider = null;
69
+    /** @var bool */
70
+    private $circlesAreNotAvailable = false;
71
+    /** @var \OCA\Talk\Share\RoomShareProvider */
72
+    private $roomShareProvider = null;
73
+
74
+    private $registeredShareProviders = [];
75
+
76
+    private $shareProviders = [];
77
+
78
+    /**
79
+     * IProviderFactory constructor.
80
+     *
81
+     * @param IServerContainer $serverContainer
82
+     */
83
+    public function __construct(IServerContainer $serverContainer) {
84
+        $this->serverContainer = $serverContainer;
85
+    }
86
+
87
+    public function registerProvider(string $shareProviderClass): void {
88
+        $this->registeredShareProviders[] = $shareProviderClass;
89
+    }
90
+
91
+    /**
92
+     * Create the default share provider.
93
+     *
94
+     * @return DefaultShareProvider
95
+     */
96
+    protected function defaultShareProvider() {
97
+        if ($this->defaultProvider === null) {
98
+            $this->defaultProvider = new DefaultShareProvider(
99
+                $this->serverContainer->getDatabaseConnection(),
100
+                $this->serverContainer->getUserManager(),
101
+                $this->serverContainer->getGroupManager(),
102
+                $this->serverContainer->getLazyRootFolder(),
103
+                $this->serverContainer->getMailer(),
104
+                $this->serverContainer->query(Defaults::class),
105
+                $this->serverContainer->getL10NFactory(),
106
+                $this->serverContainer->getURLGenerator(),
107
+                $this->serverContainer->getConfig()
108
+            );
109
+        }
110
+
111
+        return $this->defaultProvider;
112
+    }
113
+
114
+    /**
115
+     * Create the federated share provider
116
+     *
117
+     * @return FederatedShareProvider
118
+     */
119
+    protected function federatedShareProvider() {
120
+        if ($this->federatedProvider === null) {
121
+            /*
122 122
 			 * Check if the app is enabled
123 123
 			 */
124
-			$appManager = $this->serverContainer->getAppManager();
125
-			if (!$appManager->isEnabledForUser('federatedfilesharing')) {
126
-				return null;
127
-			}
124
+            $appManager = $this->serverContainer->getAppManager();
125
+            if (!$appManager->isEnabledForUser('federatedfilesharing')) {
126
+                return null;
127
+            }
128 128
 
129
-			/*
129
+            /*
130 130
 			 * TODO: add factory to federated sharing app
131 131
 			 */
132
-			$l = $this->serverContainer->getL10N('federatedfilesharing');
133
-			$addressHandler = new AddressHandler(
134
-				$this->serverContainer->getURLGenerator(),
135
-				$l,
136
-				$this->serverContainer->getCloudIdManager()
137
-			);
138
-			$notifications = new Notifications(
139
-				$addressHandler,
140
-				$this->serverContainer->getHTTPClientService(),
141
-				$this->serverContainer->query(\OCP\OCS\IDiscoveryService::class),
142
-				$this->serverContainer->getLogger(),
143
-				$this->serverContainer->getJobList(),
144
-				\OC::$server->getCloudFederationProviderManager(),
145
-				\OC::$server->getCloudFederationFactory(),
146
-				$this->serverContainer->query(IEventDispatcher::class)
147
-			);
148
-			$tokenHandler = new TokenHandler(
149
-				$this->serverContainer->getSecureRandom()
150
-			);
151
-
152
-			$this->federatedProvider = new FederatedShareProvider(
153
-				$this->serverContainer->getDatabaseConnection(),
154
-				$addressHandler,
155
-				$notifications,
156
-				$tokenHandler,
157
-				$l,
158
-				$this->serverContainer->getLogger(),
159
-				$this->serverContainer->getLazyRootFolder(),
160
-				$this->serverContainer->getConfig(),
161
-				$this->serverContainer->getUserManager(),
162
-				$this->serverContainer->getCloudIdManager(),
163
-				$this->serverContainer->getGlobalScaleConfig(),
164
-				$this->serverContainer->getCloudFederationProviderManager()
165
-			);
166
-		}
167
-
168
-		return $this->federatedProvider;
169
-	}
170
-
171
-	/**
172
-	 * Create the federated share provider
173
-	 *
174
-	 * @return ShareByMailProvider
175
-	 */
176
-	protected function getShareByMailProvider() {
177
-		if ($this->shareByMailProvider === null) {
178
-			/*
132
+            $l = $this->serverContainer->getL10N('federatedfilesharing');
133
+            $addressHandler = new AddressHandler(
134
+                $this->serverContainer->getURLGenerator(),
135
+                $l,
136
+                $this->serverContainer->getCloudIdManager()
137
+            );
138
+            $notifications = new Notifications(
139
+                $addressHandler,
140
+                $this->serverContainer->getHTTPClientService(),
141
+                $this->serverContainer->query(\OCP\OCS\IDiscoveryService::class),
142
+                $this->serverContainer->getLogger(),
143
+                $this->serverContainer->getJobList(),
144
+                \OC::$server->getCloudFederationProviderManager(),
145
+                \OC::$server->getCloudFederationFactory(),
146
+                $this->serverContainer->query(IEventDispatcher::class)
147
+            );
148
+            $tokenHandler = new TokenHandler(
149
+                $this->serverContainer->getSecureRandom()
150
+            );
151
+
152
+            $this->federatedProvider = new FederatedShareProvider(
153
+                $this->serverContainer->getDatabaseConnection(),
154
+                $addressHandler,
155
+                $notifications,
156
+                $tokenHandler,
157
+                $l,
158
+                $this->serverContainer->getLogger(),
159
+                $this->serverContainer->getLazyRootFolder(),
160
+                $this->serverContainer->getConfig(),
161
+                $this->serverContainer->getUserManager(),
162
+                $this->serverContainer->getCloudIdManager(),
163
+                $this->serverContainer->getGlobalScaleConfig(),
164
+                $this->serverContainer->getCloudFederationProviderManager()
165
+            );
166
+        }
167
+
168
+        return $this->federatedProvider;
169
+    }
170
+
171
+    /**
172
+     * Create the federated share provider
173
+     *
174
+     * @return ShareByMailProvider
175
+     */
176
+    protected function getShareByMailProvider() {
177
+        if ($this->shareByMailProvider === null) {
178
+            /*
179 179
 			 * Check if the app is enabled
180 180
 			 */
181
-			$appManager = $this->serverContainer->getAppManager();
182
-			if (!$appManager->isEnabledForUser('sharebymail')) {
183
-				return null;
184
-			}
185
-
186
-			$settingsManager = new SettingsManager($this->serverContainer->getConfig());
187
-
188
-			$this->shareByMailProvider = new ShareByMailProvider(
189
-				$this->serverContainer->getConfig(),
190
-				$this->serverContainer->getDatabaseConnection(),
191
-				$this->serverContainer->getSecureRandom(),
192
-				$this->serverContainer->getUserManager(),
193
-				$this->serverContainer->getLazyRootFolder(),
194
-				$this->serverContainer->getL10N('sharebymail'),
195
-				$this->serverContainer->getLogger(),
196
-				$this->serverContainer->getMailer(),
197
-				$this->serverContainer->getURLGenerator(),
198
-				$this->serverContainer->getActivityManager(),
199
-				$settingsManager,
200
-				$this->serverContainer->query(Defaults::class),
201
-				$this->serverContainer->getHasher(),
202
-				$this->serverContainer->get(IEventDispatcher::class),
203
-				$this->serverContainer->get(IManager::class)
204
-			);
205
-		}
206
-
207
-		return $this->shareByMailProvider;
208
-	}
209
-
210
-
211
-	/**
212
-	 * Create the circle share provider
213
-	 *
214
-	 * @return FederatedShareProvider
215
-	 *
216
-	 * @suppress PhanUndeclaredClassMethod
217
-	 */
218
-	protected function getShareByCircleProvider() {
219
-		if ($this->circlesAreNotAvailable) {
220
-			return null;
221
-		}
222
-
223
-		if (!$this->serverContainer->getAppManager()->isEnabledForUser('circles') ||
224
-			!class_exists('\OCA\Circles\ShareByCircleProvider')
225
-		) {
226
-			$this->circlesAreNotAvailable = true;
227
-			return null;
228
-		}
229
-
230
-		if ($this->shareByCircleProvider === null) {
231
-			$this->shareByCircleProvider = new \OCA\Circles\ShareByCircleProvider(
232
-				$this->serverContainer->getDatabaseConnection(),
233
-				$this->serverContainer->getSecureRandom(),
234
-				$this->serverContainer->getUserManager(),
235
-				$this->serverContainer->getLazyRootFolder(),
236
-				$this->serverContainer->getL10N('circles'),
237
-				$this->serverContainer->getLogger(),
238
-				$this->serverContainer->getURLGenerator()
239
-			);
240
-		}
241
-
242
-		return $this->shareByCircleProvider;
243
-	}
244
-
245
-	/**
246
-	 * Create the room share provider
247
-	 *
248
-	 * @return RoomShareProvider
249
-	 */
250
-	protected function getRoomShareProvider() {
251
-		if ($this->roomShareProvider === null) {
252
-			/*
181
+            $appManager = $this->serverContainer->getAppManager();
182
+            if (!$appManager->isEnabledForUser('sharebymail')) {
183
+                return null;
184
+            }
185
+
186
+            $settingsManager = new SettingsManager($this->serverContainer->getConfig());
187
+
188
+            $this->shareByMailProvider = new ShareByMailProvider(
189
+                $this->serverContainer->getConfig(),
190
+                $this->serverContainer->getDatabaseConnection(),
191
+                $this->serverContainer->getSecureRandom(),
192
+                $this->serverContainer->getUserManager(),
193
+                $this->serverContainer->getLazyRootFolder(),
194
+                $this->serverContainer->getL10N('sharebymail'),
195
+                $this->serverContainer->getLogger(),
196
+                $this->serverContainer->getMailer(),
197
+                $this->serverContainer->getURLGenerator(),
198
+                $this->serverContainer->getActivityManager(),
199
+                $settingsManager,
200
+                $this->serverContainer->query(Defaults::class),
201
+                $this->serverContainer->getHasher(),
202
+                $this->serverContainer->get(IEventDispatcher::class),
203
+                $this->serverContainer->get(IManager::class)
204
+            );
205
+        }
206
+
207
+        return $this->shareByMailProvider;
208
+    }
209
+
210
+
211
+    /**
212
+     * Create the circle share provider
213
+     *
214
+     * @return FederatedShareProvider
215
+     *
216
+     * @suppress PhanUndeclaredClassMethod
217
+     */
218
+    protected function getShareByCircleProvider() {
219
+        if ($this->circlesAreNotAvailable) {
220
+            return null;
221
+        }
222
+
223
+        if (!$this->serverContainer->getAppManager()->isEnabledForUser('circles') ||
224
+            !class_exists('\OCA\Circles\ShareByCircleProvider')
225
+        ) {
226
+            $this->circlesAreNotAvailable = true;
227
+            return null;
228
+        }
229
+
230
+        if ($this->shareByCircleProvider === null) {
231
+            $this->shareByCircleProvider = new \OCA\Circles\ShareByCircleProvider(
232
+                $this->serverContainer->getDatabaseConnection(),
233
+                $this->serverContainer->getSecureRandom(),
234
+                $this->serverContainer->getUserManager(),
235
+                $this->serverContainer->getLazyRootFolder(),
236
+                $this->serverContainer->getL10N('circles'),
237
+                $this->serverContainer->getLogger(),
238
+                $this->serverContainer->getURLGenerator()
239
+            );
240
+        }
241
+
242
+        return $this->shareByCircleProvider;
243
+    }
244
+
245
+    /**
246
+     * Create the room share provider
247
+     *
248
+     * @return RoomShareProvider
249
+     */
250
+    protected function getRoomShareProvider() {
251
+        if ($this->roomShareProvider === null) {
252
+            /*
253 253
 			 * Check if the app is enabled
254 254
 			 */
255
-			$appManager = $this->serverContainer->getAppManager();
256
-			if (!$appManager->isEnabledForUser('spreed')) {
257
-				return null;
258
-			}
259
-
260
-			try {
261
-				/**
262
-				 * @psalm-suppress UndefinedClass
263
-				 */
264
-				$this->roomShareProvider = $this->serverContainer->get(RoomShareProvider::class);
265
-			} catch (\Throwable $e) {
266
-				$this->serverContainer->get(LoggerInterface::class)->error(
267
-					$e->getMessage(),
268
-					['exception' => $e]
269
-				);
270
-				return null;
271
-			}
272
-		}
273
-
274
-		return $this->roomShareProvider;
275
-	}
276
-
277
-	/**
278
-	 * @inheritdoc
279
-	 */
280
-	public function getProvider($id) {
281
-		$provider = null;
282
-		if (isset($this->shareProviders[$id])) {
283
-			return $this->shareProviders[$id];
284
-		}
285
-
286
-		if ($id === 'ocinternal') {
287
-			$provider = $this->defaultShareProvider();
288
-		} elseif ($id === 'ocFederatedSharing') {
289
-			$provider = $this->federatedShareProvider();
290
-		} elseif ($id === 'ocMailShare') {
291
-			$provider = $this->getShareByMailProvider();
292
-		} elseif ($id === 'ocCircleShare') {
293
-			$provider = $this->getShareByCircleProvider();
294
-		} elseif ($id === 'ocRoomShare') {
295
-			$provider = $this->getRoomShareProvider();
296
-		}
297
-
298
-		foreach ($this->registeredShareProviders as $shareProvider) {
299
-			try {
300
-				/** @var IShareProvider $instance */
301
-				$instance = $this->serverContainer->get($shareProvider);
302
-				$this->shareProviders[$instance->identifier()] = $instance;
303
-			} catch (\Throwable $e) {
304
-				$this->serverContainer->get(LoggerInterface::class)->error(
305
-					$e->getMessage(),
306
-					['exception' => $e]
307
-				);
308
-			}
309
-		}
310
-
311
-		if (isset($this->shareProviders[$id])) {
312
-			$provider = $this->shareProviders[$id];
313
-		}
314
-
315
-		if ($provider === null) {
316
-			throw new ProviderException('No provider with id .' . $id . ' found.');
317
-		}
318
-
319
-		return $provider;
320
-	}
321
-
322
-	/**
323
-	 * @inheritdoc
324
-	 */
325
-	public function getProviderForType($shareType) {
326
-		$provider = null;
327
-
328
-		if ($shareType === IShare::TYPE_USER ||
329
-			$shareType === IShare::TYPE_GROUP ||
330
-			$shareType === IShare::TYPE_LINK
331
-		) {
332
-			$provider = $this->defaultShareProvider();
333
-		} elseif ($shareType === IShare::TYPE_REMOTE || $shareType === IShare::TYPE_REMOTE_GROUP) {
334
-			$provider = $this->federatedShareProvider();
335
-		} elseif ($shareType === IShare::TYPE_EMAIL) {
336
-			$provider = $this->getShareByMailProvider();
337
-		} elseif ($shareType === IShare::TYPE_CIRCLE) {
338
-			$provider = $this->getShareByCircleProvider();
339
-		} elseif ($shareType === IShare::TYPE_ROOM) {
340
-			$provider = $this->getRoomShareProvider();
341
-		} elseif ($shareType === IShare::TYPE_DECK) {
342
-			$provider = $this->getProvider('deck');
343
-		} elseif ($shareType === IShare::TYPE_SCIENCEMESH) {
344
-			$provider = $this->getProvider('sciencemesh');
345
-		}
346
-
347
-
348
-		if ($provider === null) {
349
-			throw new ProviderException('No share provider for share type ' . $shareType);
350
-		}
351
-
352
-		return $provider;
353
-	}
354
-
355
-	public function getAllProviders() {
356
-		$shares = [$this->defaultShareProvider(), $this->federatedShareProvider()];
357
-		$shareByMail = $this->getShareByMailProvider();
358
-		if ($shareByMail !== null) {
359
-			$shares[] = $shareByMail;
360
-		}
361
-		$shareByCircle = $this->getShareByCircleProvider();
362
-		if ($shareByCircle !== null) {
363
-			$shares[] = $shareByCircle;
364
-		}
365
-		$roomShare = $this->getRoomShareProvider();
366
-		if ($roomShare !== null) {
367
-			$shares[] = $roomShare;
368
-		}
369
-
370
-		foreach ($this->registeredShareProviders as $shareProvider) {
371
-			try {
372
-				/** @var IShareProvider $instance */
373
-				$instance = $this->serverContainer->get($shareProvider);
374
-			} catch (\Throwable $e) {
375
-				$this->serverContainer->get(LoggerInterface::class)->error(
376
-					$e->getMessage(),
377
-					['exception' => $e]
378
-				);
379
-				continue;
380
-			}
381
-
382
-			if (!isset($this->shareProviders[$instance->identifier()])) {
383
-				$this->shareProviders[$instance->identifier()] = $instance;
384
-			}
385
-			$shares[] = $this->shareProviders[$instance->identifier()];
386
-		}
387
-
388
-
389
-
390
-		return $shares;
391
-	}
255
+            $appManager = $this->serverContainer->getAppManager();
256
+            if (!$appManager->isEnabledForUser('spreed')) {
257
+                return null;
258
+            }
259
+
260
+            try {
261
+                /**
262
+                 * @psalm-suppress UndefinedClass
263
+                 */
264
+                $this->roomShareProvider = $this->serverContainer->get(RoomShareProvider::class);
265
+            } catch (\Throwable $e) {
266
+                $this->serverContainer->get(LoggerInterface::class)->error(
267
+                    $e->getMessage(),
268
+                    ['exception' => $e]
269
+                );
270
+                return null;
271
+            }
272
+        }
273
+
274
+        return $this->roomShareProvider;
275
+    }
276
+
277
+    /**
278
+     * @inheritdoc
279
+     */
280
+    public function getProvider($id) {
281
+        $provider = null;
282
+        if (isset($this->shareProviders[$id])) {
283
+            return $this->shareProviders[$id];
284
+        }
285
+
286
+        if ($id === 'ocinternal') {
287
+            $provider = $this->defaultShareProvider();
288
+        } elseif ($id === 'ocFederatedSharing') {
289
+            $provider = $this->federatedShareProvider();
290
+        } elseif ($id === 'ocMailShare') {
291
+            $provider = $this->getShareByMailProvider();
292
+        } elseif ($id === 'ocCircleShare') {
293
+            $provider = $this->getShareByCircleProvider();
294
+        } elseif ($id === 'ocRoomShare') {
295
+            $provider = $this->getRoomShareProvider();
296
+        }
297
+
298
+        foreach ($this->registeredShareProviders as $shareProvider) {
299
+            try {
300
+                /** @var IShareProvider $instance */
301
+                $instance = $this->serverContainer->get($shareProvider);
302
+                $this->shareProviders[$instance->identifier()] = $instance;
303
+            } catch (\Throwable $e) {
304
+                $this->serverContainer->get(LoggerInterface::class)->error(
305
+                    $e->getMessage(),
306
+                    ['exception' => $e]
307
+                );
308
+            }
309
+        }
310
+
311
+        if (isset($this->shareProviders[$id])) {
312
+            $provider = $this->shareProviders[$id];
313
+        }
314
+
315
+        if ($provider === null) {
316
+            throw new ProviderException('No provider with id .' . $id . ' found.');
317
+        }
318
+
319
+        return $provider;
320
+    }
321
+
322
+    /**
323
+     * @inheritdoc
324
+     */
325
+    public function getProviderForType($shareType) {
326
+        $provider = null;
327
+
328
+        if ($shareType === IShare::TYPE_USER ||
329
+            $shareType === IShare::TYPE_GROUP ||
330
+            $shareType === IShare::TYPE_LINK
331
+        ) {
332
+            $provider = $this->defaultShareProvider();
333
+        } elseif ($shareType === IShare::TYPE_REMOTE || $shareType === IShare::TYPE_REMOTE_GROUP) {
334
+            $provider = $this->federatedShareProvider();
335
+        } elseif ($shareType === IShare::TYPE_EMAIL) {
336
+            $provider = $this->getShareByMailProvider();
337
+        } elseif ($shareType === IShare::TYPE_CIRCLE) {
338
+            $provider = $this->getShareByCircleProvider();
339
+        } elseif ($shareType === IShare::TYPE_ROOM) {
340
+            $provider = $this->getRoomShareProvider();
341
+        } elseif ($shareType === IShare::TYPE_DECK) {
342
+            $provider = $this->getProvider('deck');
343
+        } elseif ($shareType === IShare::TYPE_SCIENCEMESH) {
344
+            $provider = $this->getProvider('sciencemesh');
345
+        }
346
+
347
+
348
+        if ($provider === null) {
349
+            throw new ProviderException('No share provider for share type ' . $shareType);
350
+        }
351
+
352
+        return $provider;
353
+    }
354
+
355
+    public function getAllProviders() {
356
+        $shares = [$this->defaultShareProvider(), $this->federatedShareProvider()];
357
+        $shareByMail = $this->getShareByMailProvider();
358
+        if ($shareByMail !== null) {
359
+            $shares[] = $shareByMail;
360
+        }
361
+        $shareByCircle = $this->getShareByCircleProvider();
362
+        if ($shareByCircle !== null) {
363
+            $shares[] = $shareByCircle;
364
+        }
365
+        $roomShare = $this->getRoomShareProvider();
366
+        if ($roomShare !== null) {
367
+            $shares[] = $roomShare;
368
+        }
369
+
370
+        foreach ($this->registeredShareProviders as $shareProvider) {
371
+            try {
372
+                /** @var IShareProvider $instance */
373
+                $instance = $this->serverContainer->get($shareProvider);
374
+            } catch (\Throwable $e) {
375
+                $this->serverContainer->get(LoggerInterface::class)->error(
376
+                    $e->getMessage(),
377
+                    ['exception' => $e]
378
+                );
379
+                continue;
380
+            }
381
+
382
+            if (!isset($this->shareProviders[$instance->identifier()])) {
383
+                $this->shareProviders[$instance->identifier()] = $instance;
384
+            }
385
+            $shares[] = $this->shareProviders[$instance->identifier()];
386
+        }
387
+
388
+
389
+
390
+        return $shares;
391
+    }
392 392
 }
Please login to merge, or discard this patch.
lib/private/Share/Constants.php 1 patch
Indentation   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -29,64 +29,64 @@
 block discarded – undo
29 29
 use OCP\Share\IShare;
30 30
 
31 31
 class Constants {
32
-	/**
33
-	 * @deprecated 17.0.0 - use IShare::TYPE_USER instead
34
-	 */
35
-	public const SHARE_TYPE_USER = 0;
36
-	/**
37
-	 * @deprecated 17.0.0 - use IShare::TYPE_GROUP instead
38
-	 */
39
-	public const SHARE_TYPE_GROUP = 1;
40
-	// const SHARE_TYPE_USERGROUP = 2; // Internal type used by DefaultShareProvider
41
-	/**
42
-	 * @deprecated 17.0.0 - use IShare::TYPE_LINK instead
43
-	 */
44
-	public const SHARE_TYPE_LINK = 3;
45
-	/**
46
-	 * @deprecated 17.0.0 - use IShare::TYPE_EMAIL instead
47
-	 */
48
-	public const SHARE_TYPE_EMAIL = 4;
49
-	public const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it
50
-	/**
51
-	 * @deprecated 17.0.0 - use IShare::TYPE_REMOTE instead
52
-	 */
53
-	public const SHARE_TYPE_REMOTE = 6;
54
-	/**
55
-	 * @deprecated 17.0.0 - use IShare::TYPE_CIRCLE instead
56
-	 */
57
-	public const SHARE_TYPE_CIRCLE = 7;
58
-	/**
59
-	 * @deprecated 17.0.0 - use IShare::TYPE_GUEST instead
60
-	 */
61
-	public const SHARE_TYPE_GUEST = 8;
62
-	/**
63
-	 * @deprecated 17.0.0 - use IShare::REMOTE_GROUP instead
64
-	 */
65
-	public const SHARE_TYPE_REMOTE_GROUP = 9;
66
-	/**
67
-	 * @deprecated 17.0.0 - use IShare::TYPE_ROOM instead
68
-	 */
69
-	public const SHARE_TYPE_ROOM = 10;
70
-	// const SHARE_TYPE_USERROOM = 11; // Internal type used by RoomShareProvider
71
-	/**
72
-	 * @deprecated 21.0.0 - use IShare::TYPE_DECK instead
73
-	 */
74
-	public const SHARE_TYPE_DECK = 12;
75
-	// const SHARE_TYPE_DECK_USER = 13; // Internal type used by DeckShareProvider
32
+    /**
33
+     * @deprecated 17.0.0 - use IShare::TYPE_USER instead
34
+     */
35
+    public const SHARE_TYPE_USER = 0;
36
+    /**
37
+     * @deprecated 17.0.0 - use IShare::TYPE_GROUP instead
38
+     */
39
+    public const SHARE_TYPE_GROUP = 1;
40
+    // const SHARE_TYPE_USERGROUP = 2; // Internal type used by DefaultShareProvider
41
+    /**
42
+     * @deprecated 17.0.0 - use IShare::TYPE_LINK instead
43
+     */
44
+    public const SHARE_TYPE_LINK = 3;
45
+    /**
46
+     * @deprecated 17.0.0 - use IShare::TYPE_EMAIL instead
47
+     */
48
+    public const SHARE_TYPE_EMAIL = 4;
49
+    public const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it
50
+    /**
51
+     * @deprecated 17.0.0 - use IShare::TYPE_REMOTE instead
52
+     */
53
+    public const SHARE_TYPE_REMOTE = 6;
54
+    /**
55
+     * @deprecated 17.0.0 - use IShare::TYPE_CIRCLE instead
56
+     */
57
+    public const SHARE_TYPE_CIRCLE = 7;
58
+    /**
59
+     * @deprecated 17.0.0 - use IShare::TYPE_GUEST instead
60
+     */
61
+    public const SHARE_TYPE_GUEST = 8;
62
+    /**
63
+     * @deprecated 17.0.0 - use IShare::REMOTE_GROUP instead
64
+     */
65
+    public const SHARE_TYPE_REMOTE_GROUP = 9;
66
+    /**
67
+     * @deprecated 17.0.0 - use IShare::TYPE_ROOM instead
68
+     */
69
+    public const SHARE_TYPE_ROOM = 10;
70
+    // const SHARE_TYPE_USERROOM = 11; // Internal type used by RoomShareProvider
71
+    /**
72
+     * @deprecated 21.0.0 - use IShare::TYPE_DECK instead
73
+     */
74
+    public const SHARE_TYPE_DECK = 12;
75
+    // const SHARE_TYPE_DECK_USER = 13; // Internal type used by DeckShareProvider
76 76
 
77
-	// Note to developers: Do not add new share types here
77
+    // Note to developers: Do not add new share types here
78 78
 
79
-	public const FORMAT_NONE = -1;
80
-	public const FORMAT_STATUSES = -2;
81
-	public const FORMAT_SOURCES = -3;  // ToDo Check if it is still in use otherwise remove it
79
+    public const FORMAT_NONE = -1;
80
+    public const FORMAT_STATUSES = -2;
81
+    public const FORMAT_SOURCES = -3;  // ToDo Check if it is still in use otherwise remove it
82 82
 
83
-	public const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
83
+    public const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
84 84
 
85
-	public const TOKEN_LENGTH = 15; // old (oc7) length is 32, keep token length in db at least that for compatibility
85
+    public const TOKEN_LENGTH = 15; // old (oc7) length is 32, keep token length in db at least that for compatibility
86 86
 
87
-	protected static $shareTypeUserAndGroups = -1;
88
-	protected static $shareTypeGroupUserUnique = 2;
89
-	protected static $backends = [];
90
-	protected static $backendTypes = [];
91
-	protected static $isResharingAllowed;
87
+    protected static $shareTypeUserAndGroups = -1;
88
+    protected static $shareTypeGroupUserUnique = 2;
89
+    protected static $backends = [];
90
+    protected static $backendTypes = [];
91
+    protected static $isResharingAllowed;
92 92
 }
Please login to merge, or discard this patch.
lib/public/Share/IShare.php 1 patch
Indentation   +576 added lines, -576 removed lines patch added patch discarded remove patch
@@ -43,580 +43,580 @@
 block discarded – undo
43 43
  * @since 9.0.0
44 44
  */
45 45
 interface IShare {
46
-	/**
47
-	 * @since 17.0.0
48
-	 */
49
-	public const TYPE_USER = 0;
50
-
51
-	/**
52
-	 * @since 17.0.0
53
-	 */
54
-	public const TYPE_GROUP = 1;
55
-
56
-	/**
57
-	 * @internal
58
-	 * @since 18.0.0
59
-	 */
60
-	public const TYPE_USERGROUP = 2;
61
-
62
-	/**
63
-	 * @since 17.0.0
64
-	 */
65
-	public const TYPE_LINK = 3;
66
-
67
-	/**
68
-	 * @since 17.0.0
69
-	 */
70
-	public const TYPE_EMAIL = 4;
71
-
72
-	/**
73
-	 * ToDo Check if it is still in use otherwise remove it
74
-	 * @since 17.0.0
75
-	 */
76
-	// public const TYPE_CONTACT = 5;
77
-
78
-	/**
79
-	 * @since 17.0.0
80
-	 */
81
-	public const TYPE_REMOTE = 6;
82
-
83
-	/**
84
-	 * @since 17.0.0
85
-	 */
86
-	public const TYPE_CIRCLE = 7;
87
-
88
-	/**
89
-	 * @since 17.0.0
90
-	 */
91
-	public const TYPE_GUEST = 8;
92
-
93
-	/**
94
-	 * @since 17.0.0
95
-	 */
96
-	public const TYPE_REMOTE_GROUP = 9;
97
-
98
-	/**
99
-	 * @since 17.0.0
100
-	 */
101
-	public const TYPE_ROOM = 10;
102
-
103
-	/**
104
-	 * Internal type used by RoomShareProvider
105
-	 * @since 17.0.0
106
-	 */
107
-	// const TYPE_USERROOM = 11;
108
-
109
-	/**
110
-	 * @since 21.0.0
111
-	 */
112
-	public const TYPE_DECK = 12;
113
-
114
-	/**
115
-	 * @internal
116
-	 * @since 21.0.0
117
-	 */
118
-	public const TYPE_DECK_USER = 13;
119
-
120
-	/**
121
-	 * @since 26.0.0
122
-	 */
123
-	public const TYPE_SCIENCEMESH = 15;
124
-
125
-	/**
126
-	 * @since 18.0.0
127
-	 */
128
-	public const STATUS_PENDING = 0;
129
-
130
-	/**
131
-	 * @since 18.0.0
132
-	 */
133
-	public const STATUS_ACCEPTED = 1;
134
-
135
-	/**
136
-	 * @since 18.0.0
137
-	 */
138
-	public const STATUS_REJECTED = 2;
139
-
140
-	/**
141
-	 * Set the internal id of the share
142
-	 * It is only allowed to set the internal id of a share once.
143
-	 * Attempts to override the internal id will result in an IllegalIDChangeException
144
-	 *
145
-	 * @param string $id
146
-	 * @return \OCP\Share\IShare
147
-	 * @throws IllegalIDChangeException
148
-	 * @throws \InvalidArgumentException
149
-	 * @since 9.1.0
150
-	 */
151
-	public function setId($id);
152
-
153
-	/**
154
-	 * Get the internal id of the share.
155
-	 *
156
-	 * @return string
157
-	 * @since 9.0.0
158
-	 */
159
-	public function getId();
160
-
161
-	/**
162
-	 * Get the full share id. This is the <providerid>:<internalid>.
163
-	 * The full id is unique in the system.
164
-	 *
165
-	 * @return string
166
-	 * @since 9.0.0
167
-	 * @throws \UnexpectedValueException If the fullId could not be constructed
168
-	 */
169
-	public function getFullId();
170
-
171
-	/**
172
-	 * Set the provider id of the share
173
-	 * It is only allowed to set the provider id of a share once.
174
-	 * Attempts to override the provider id will result in an IllegalIDChangeException
175
-	 *
176
-	 * @param string $id
177
-	 * @return \OCP\Share\IShare
178
-	 * @throws IllegalIDChangeException
179
-	 * @throws \InvalidArgumentException
180
-	 * @since 9.1.0
181
-	 */
182
-	public function setProviderId($id);
183
-
184
-	/**
185
-	 * Set the node of the file/folder that is shared
186
-	 *
187
-	 * @param Node $node
188
-	 * @return \OCP\Share\IShare The modified object
189
-	 * @since 9.0.0
190
-	 */
191
-	public function setNode(Node $node);
192
-
193
-	/**
194
-	 * Get the node of the file/folder that is shared
195
-	 *
196
-	 * @return File|Folder
197
-	 * @since 9.0.0
198
-	 * @throws NotFoundException
199
-	 */
200
-	public function getNode();
201
-
202
-	/**
203
-	 * Set file id for lazy evaluation of the node
204
-	 * @param int $fileId
205
-	 * @return \OCP\Share\IShare The modified object
206
-	 * @since 9.0.0
207
-	 */
208
-	public function setNodeId($fileId);
209
-
210
-	/**
211
-	 * Get the fileid of the node of this share
212
-	 * @return int
213
-	 * @since 9.0.0
214
-	 * @throws NotFoundException
215
-	 */
216
-	public function getNodeId();
217
-
218
-	/**
219
-	 * Set the type of node (file/folder)
220
-	 *
221
-	 * @param string $type
222
-	 * @return \OCP\Share\IShare The modified object
223
-	 * @since 9.0.0
224
-	 */
225
-	public function setNodeType($type);
226
-
227
-	/**
228
-	 * Get the type of node (file/folder)
229
-	 *
230
-	 * @return string
231
-	 * @since 9.0.0
232
-	 * @throws NotFoundException
233
-	 */
234
-	public function getNodeType();
235
-
236
-	/**
237
-	 * Set the shareType
238
-	 *
239
-	 * @param int $shareType
240
-	 * @return \OCP\Share\IShare The modified object
241
-	 * @since 9.0.0
242
-	 */
243
-	public function setShareType($shareType);
244
-
245
-	/**
246
-	 * Get the shareType
247
-	 *
248
-	 * @return int
249
-	 * @since 9.0.0
250
-	 */
251
-	public function getShareType();
252
-
253
-	/**
254
-	 * Set the receiver of this share.
255
-	 *
256
-	 * @param string $sharedWith
257
-	 * @return \OCP\Share\IShare The modified object
258
-	 * @since 9.0.0
259
-	 */
260
-	public function setSharedWith($sharedWith);
261
-
262
-	/**
263
-	 * Get the receiver of this share.
264
-	 *
265
-	 * @return string
266
-	 * @since 9.0.0
267
-	 */
268
-	public function getSharedWith();
269
-
270
-	/**
271
-	 * Set the display name of the receiver of this share.
272
-	 *
273
-	 * @param string $displayName
274
-	 * @return \OCP\Share\IShare The modified object
275
-	 * @since 14.0.0
276
-	 */
277
-	public function setSharedWithDisplayName($displayName);
278
-
279
-	/**
280
-	 * Get the display name of the receiver of this share.
281
-	 *
282
-	 * @return string
283
-	 * @since 14.0.0
284
-	 */
285
-	public function getSharedWithDisplayName();
286
-
287
-	/**
288
-	 * Set the avatar of the receiver of this share.
289
-	 *
290
-	 * @param string $src
291
-	 * @return \OCP\Share\IShare The modified object
292
-	 * @since 14.0.0
293
-	 */
294
-	public function setSharedWithAvatar($src);
295
-
296
-	/**
297
-	 * Get the avatar of the receiver of this share.
298
-	 *
299
-	 * @return string
300
-	 * @since 14.0.0
301
-	 */
302
-	public function getSharedWithAvatar();
303
-
304
-	/**
305
-	 * Set the permissions.
306
-	 * See \OCP\Constants::PERMISSION_*
307
-	 *
308
-	 * @param int $permissions
309
-	 * @return IShare The modified object
310
-	 * @since 9.0.0
311
-	 */
312
-	public function setPermissions($permissions);
313
-
314
-	/**
315
-	 * Get the share permissions
316
-	 * See \OCP\Constants::PERMISSION_*
317
-	 *
318
-	 * @return int
319
-	 * @since 9.0.0
320
-	 */
321
-	public function getPermissions();
322
-
323
-	/**
324
-	 * Create share attributes object
325
-	 *
326
-	 * @since 25.0.0
327
-	 * @return IAttributes
328
-	 */
329
-	public function newAttributes(): IAttributes;
330
-
331
-	/**
332
-	 * Set share attributes
333
-	 *
334
-	 * @param ?IAttributes $attributes
335
-	 * @since 25.0.0
336
-	 * @return IShare The modified object
337
-	 */
338
-	public function setAttributes(?IAttributes $attributes);
339
-
340
-	/**
341
-	 * Get share attributes
342
-	 *
343
-	 * @since 25.0.0
344
-	 * @return ?IAttributes
345
-	 */
346
-	public function getAttributes(): ?IAttributes;
347
-
348
-	/**
349
-	 * Set the accepted status
350
-	 * See self::STATUS_*
351
-	 *
352
-	 * @param int $status
353
-	 * @return IShare The modified object
354
-	 * @since 18.0.0
355
-	 */
356
-	public function setStatus(int $status): IShare;
357
-
358
-	/**
359
-	 * Get the accepted status
360
-	 * See self::STATUS_*
361
-	 *
362
-	 * @return int
363
-	 * @since 18.0.0
364
-	 */
365
-	public function getStatus(): int;
366
-
367
-	/**
368
-	 * Attach a note to a share
369
-	 *
370
-	 * @param string $note
371
-	 * @return \OCP\Share\IShare The modified object
372
-	 * @since 14.0.0
373
-	 */
374
-	public function setNote($note);
375
-
376
-	/**
377
-	 * Get note attached to a share
378
-	 *
379
-	 * @return string
380
-	 * @since 14.0.0
381
-	 */
382
-	public function getNote();
383
-
384
-
385
-	/**
386
-	 * Set the expiration date
387
-	 *
388
-	 * @param null|\DateTime $expireDate
389
-	 * @return \OCP\Share\IShare The modified object
390
-	 * @since 9.0.0
391
-	 */
392
-	public function setExpirationDate($expireDate);
393
-
394
-	/**
395
-	 * Get the expiration date
396
-	 *
397
-	 * @return \DateTime
398
-	 * @since 9.0.0
399
-	 */
400
-	public function getExpirationDate();
401
-
402
-	/**
403
-	 * Is the share expired ?
404
-	 *
405
-	 * @return boolean
406
-	 * @since 18.0.0
407
-	 */
408
-	public function isExpired();
409
-
410
-	/**
411
-	 * set a label for a share, some shares, e.g. public links can have a label
412
-	 *
413
-	 * @param string $label
414
-	 * @return \OCP\Share\IShare The modified object
415
-	 * @since 15.0.0
416
-	 */
417
-	public function setLabel($label);
418
-
419
-	/**
420
-	 * get label for the share, some shares, e.g. public links can have a label
421
-	 *
422
-	 * @return string
423
-	 * @since 15.0.0
424
-	 */
425
-	public function getLabel();
426
-
427
-	/**
428
-	 * Set the sharer of the path.
429
-	 *
430
-	 * @param string $sharedBy
431
-	 * @return \OCP\Share\IShare The modified object
432
-	 * @since 9.0.0
433
-	 */
434
-	public function setSharedBy($sharedBy);
435
-
436
-	/**
437
-	 * Get share sharer
438
-	 *
439
-	 * @return string
440
-	 * @since 9.0.0
441
-	 */
442
-	public function getSharedBy();
443
-
444
-	/**
445
-	 * Set the original share owner (who owns the path that is shared)
446
-	 *
447
-	 * @param string $shareOwner
448
-	 * @return \OCP\Share\IShare The modified object
449
-	 * @since 9.0.0
450
-	 */
451
-	public function setShareOwner($shareOwner);
452
-
453
-	/**
454
-	 * Get the original share owner (who owns the path that is shared)
455
-	 *
456
-	 * @return string
457
-	 * @since 9.0.0
458
-	 */
459
-	public function getShareOwner();
460
-
461
-	/**
462
-	 * Set the password for this share.
463
-	 * When the share is passed to the share manager to be created
464
-	 * or updated the password will be hashed.
465
-	 *
466
-	 * @param string|null $password
467
-	 * @return \OCP\Share\IShare The modified object
468
-	 * @since 9.0.0
469
-	 */
470
-	public function setPassword($password);
471
-
472
-	/**
473
-	 * Get the password of this share.
474
-	 * If this share is obtained via a shareprovider the password is
475
-	 * hashed.
476
-	 *
477
-	 * @return string
478
-	 * @since 9.0.0
479
-	 */
480
-	public function getPassword();
481
-
482
-	/**
483
-	 * Set the password's expiration time of this share.
484
-	 *
485
-	 * @return self The modified object
486
-	 * @since 24.0.0
487
-	 */
488
-	public function setPasswordExpirationTime(?\DateTimeInterface $passwordExpirationTime = null): IShare;
489
-
490
-	/**
491
-	 * Get the password's expiration time of this share.
492
-	 * @since 24.0.0
493
-	 */
494
-	public function getPasswordExpirationTime(): ?\DateTimeInterface;
495
-
496
-	/**
497
-	 * Set if the recipient can start a conversation with the owner to get the
498
-	 * password using Nextcloud Talk.
499
-	 *
500
-	 * @param bool $sendPasswordByTalk
501
-	 * @return \OCP\Share\IShare The modified object
502
-	 * @since 14.0.0
503
-	 */
504
-	public function setSendPasswordByTalk(bool $sendPasswordByTalk);
505
-
506
-	/**
507
-	 * Get if the recipient can start a conversation with the owner to get the
508
-	 * password using Nextcloud Talk.
509
-	 * The returned value does not take into account other factors, like Talk
510
-	 * being enabled for the owner of the share or not; it just cover whether
511
-	 * the option is enabled for the share itself or not.
512
-	 *
513
-	 * @return bool
514
-	 * @since 14.0.0
515
-	 */
516
-	public function getSendPasswordByTalk(): bool;
517
-
518
-	/**
519
-	 * Set the public link token.
520
-	 *
521
-	 * @param string $token
522
-	 * @return \OCP\Share\IShare The modified object
523
-	 * @since 9.0.0
524
-	 */
525
-	public function setToken($token);
526
-
527
-	/**
528
-	 * Get the public link token.
529
-	 *
530
-	 * @return string
531
-	 * @since 9.0.0
532
-	 */
533
-	public function getToken();
534
-
535
-	/**
536
-	 * Set the target path of this share relative to the recipients user folder.
537
-	 *
538
-	 * @param string $target
539
-	 * @return \OCP\Share\IShare The modified object
540
-	 * @since 9.0.0
541
-	 */
542
-	public function setTarget($target);
543
-
544
-	/**
545
-	 * Get the target path of this share relative to the recipients user folder.
546
-	 *
547
-	 * @return string
548
-	 * @since 9.0.0
549
-	 */
550
-	public function getTarget();
551
-
552
-	/**
553
-	 * Set the time this share was created
554
-	 *
555
-	 * @param \DateTime $shareTime
556
-	 * @return \OCP\Share\IShare The modified object
557
-	 * @since 9.0.0
558
-	 */
559
-	public function setShareTime(\DateTime $shareTime);
560
-
561
-	/**
562
-	 * Get the timestamp this share was created
563
-	 *
564
-	 * @return \DateTime
565
-	 * @since 9.0.0
566
-	 */
567
-	public function getShareTime();
568
-
569
-	/**
570
-	 * Set if the recipient is informed by mail about the share.
571
-	 *
572
-	 * @param bool $mailSend
573
-	 * @return \OCP\Share\IShare The modified object
574
-	 * @since 9.0.0
575
-	 */
576
-	public function setMailSend($mailSend);
577
-
578
-	/**
579
-	 * Get if the recipient informed by mail about the share.
580
-	 *
581
-	 * @return bool
582
-	 * @since 9.0.0
583
-	 */
584
-	public function getMailSend();
585
-
586
-	/**
587
-	 * Set the cache entry for the shared node
588
-	 *
589
-	 * @param ICacheEntry $entry
590
-	 * @since 11.0.0
591
-	 */
592
-	public function setNodeCacheEntry(ICacheEntry $entry);
593
-
594
-	/**
595
-	 * Get the cache entry for the shared node
596
-	 *
597
-	 * @return null|ICacheEntry
598
-	 * @since 11.0.0
599
-	 */
600
-	public function getNodeCacheEntry();
601
-
602
-	/**
603
-	 * Sets a shares hide download state
604
-	 * This is mainly for public shares. It will signal that the share page should
605
-	 * hide download buttons etc.
606
-	 *
607
-	 * @param bool $hide
608
-	 * @return IShare
609
-	 * @since 15.0.0
610
-	 */
611
-	public function setHideDownload(bool $hide): IShare;
612
-
613
-	/**
614
-	 * Gets a shares hide download state
615
-	 * This is mainly for public shares. It will signal that the share page should
616
-	 * hide download buttons etc.
617
-	 *
618
-	 * @return bool
619
-	 * @since 15.0.0
620
-	 */
621
-	public function getHideDownload(): bool;
46
+    /**
47
+     * @since 17.0.0
48
+     */
49
+    public const TYPE_USER = 0;
50
+
51
+    /**
52
+     * @since 17.0.0
53
+     */
54
+    public const TYPE_GROUP = 1;
55
+
56
+    /**
57
+     * @internal
58
+     * @since 18.0.0
59
+     */
60
+    public const TYPE_USERGROUP = 2;
61
+
62
+    /**
63
+     * @since 17.0.0
64
+     */
65
+    public const TYPE_LINK = 3;
66
+
67
+    /**
68
+     * @since 17.0.0
69
+     */
70
+    public const TYPE_EMAIL = 4;
71
+
72
+    /**
73
+     * ToDo Check if it is still in use otherwise remove it
74
+     * @since 17.0.0
75
+     */
76
+    // public const TYPE_CONTACT = 5;
77
+
78
+    /**
79
+     * @since 17.0.0
80
+     */
81
+    public const TYPE_REMOTE = 6;
82
+
83
+    /**
84
+     * @since 17.0.0
85
+     */
86
+    public const TYPE_CIRCLE = 7;
87
+
88
+    /**
89
+     * @since 17.0.0
90
+     */
91
+    public const TYPE_GUEST = 8;
92
+
93
+    /**
94
+     * @since 17.0.0
95
+     */
96
+    public const TYPE_REMOTE_GROUP = 9;
97
+
98
+    /**
99
+     * @since 17.0.0
100
+     */
101
+    public const TYPE_ROOM = 10;
102
+
103
+    /**
104
+     * Internal type used by RoomShareProvider
105
+     * @since 17.0.0
106
+     */
107
+    // const TYPE_USERROOM = 11;
108
+
109
+    /**
110
+     * @since 21.0.0
111
+     */
112
+    public const TYPE_DECK = 12;
113
+
114
+    /**
115
+     * @internal
116
+     * @since 21.0.0
117
+     */
118
+    public const TYPE_DECK_USER = 13;
119
+
120
+    /**
121
+     * @since 26.0.0
122
+     */
123
+    public const TYPE_SCIENCEMESH = 15;
124
+
125
+    /**
126
+     * @since 18.0.0
127
+     */
128
+    public const STATUS_PENDING = 0;
129
+
130
+    /**
131
+     * @since 18.0.0
132
+     */
133
+    public const STATUS_ACCEPTED = 1;
134
+
135
+    /**
136
+     * @since 18.0.0
137
+     */
138
+    public const STATUS_REJECTED = 2;
139
+
140
+    /**
141
+     * Set the internal id of the share
142
+     * It is only allowed to set the internal id of a share once.
143
+     * Attempts to override the internal id will result in an IllegalIDChangeException
144
+     *
145
+     * @param string $id
146
+     * @return \OCP\Share\IShare
147
+     * @throws IllegalIDChangeException
148
+     * @throws \InvalidArgumentException
149
+     * @since 9.1.0
150
+     */
151
+    public function setId($id);
152
+
153
+    /**
154
+     * Get the internal id of the share.
155
+     *
156
+     * @return string
157
+     * @since 9.0.0
158
+     */
159
+    public function getId();
160
+
161
+    /**
162
+     * Get the full share id. This is the <providerid>:<internalid>.
163
+     * The full id is unique in the system.
164
+     *
165
+     * @return string
166
+     * @since 9.0.0
167
+     * @throws \UnexpectedValueException If the fullId could not be constructed
168
+     */
169
+    public function getFullId();
170
+
171
+    /**
172
+     * Set the provider id of the share
173
+     * It is only allowed to set the provider id of a share once.
174
+     * Attempts to override the provider id will result in an IllegalIDChangeException
175
+     *
176
+     * @param string $id
177
+     * @return \OCP\Share\IShare
178
+     * @throws IllegalIDChangeException
179
+     * @throws \InvalidArgumentException
180
+     * @since 9.1.0
181
+     */
182
+    public function setProviderId($id);
183
+
184
+    /**
185
+     * Set the node of the file/folder that is shared
186
+     *
187
+     * @param Node $node
188
+     * @return \OCP\Share\IShare The modified object
189
+     * @since 9.0.0
190
+     */
191
+    public function setNode(Node $node);
192
+
193
+    /**
194
+     * Get the node of the file/folder that is shared
195
+     *
196
+     * @return File|Folder
197
+     * @since 9.0.0
198
+     * @throws NotFoundException
199
+     */
200
+    public function getNode();
201
+
202
+    /**
203
+     * Set file id for lazy evaluation of the node
204
+     * @param int $fileId
205
+     * @return \OCP\Share\IShare The modified object
206
+     * @since 9.0.0
207
+     */
208
+    public function setNodeId($fileId);
209
+
210
+    /**
211
+     * Get the fileid of the node of this share
212
+     * @return int
213
+     * @since 9.0.0
214
+     * @throws NotFoundException
215
+     */
216
+    public function getNodeId();
217
+
218
+    /**
219
+     * Set the type of node (file/folder)
220
+     *
221
+     * @param string $type
222
+     * @return \OCP\Share\IShare The modified object
223
+     * @since 9.0.0
224
+     */
225
+    public function setNodeType($type);
226
+
227
+    /**
228
+     * Get the type of node (file/folder)
229
+     *
230
+     * @return string
231
+     * @since 9.0.0
232
+     * @throws NotFoundException
233
+     */
234
+    public function getNodeType();
235
+
236
+    /**
237
+     * Set the shareType
238
+     *
239
+     * @param int $shareType
240
+     * @return \OCP\Share\IShare The modified object
241
+     * @since 9.0.0
242
+     */
243
+    public function setShareType($shareType);
244
+
245
+    /**
246
+     * Get the shareType
247
+     *
248
+     * @return int
249
+     * @since 9.0.0
250
+     */
251
+    public function getShareType();
252
+
253
+    /**
254
+     * Set the receiver of this share.
255
+     *
256
+     * @param string $sharedWith
257
+     * @return \OCP\Share\IShare The modified object
258
+     * @since 9.0.0
259
+     */
260
+    public function setSharedWith($sharedWith);
261
+
262
+    /**
263
+     * Get the receiver of this share.
264
+     *
265
+     * @return string
266
+     * @since 9.0.0
267
+     */
268
+    public function getSharedWith();
269
+
270
+    /**
271
+     * Set the display name of the receiver of this share.
272
+     *
273
+     * @param string $displayName
274
+     * @return \OCP\Share\IShare The modified object
275
+     * @since 14.0.0
276
+     */
277
+    public function setSharedWithDisplayName($displayName);
278
+
279
+    /**
280
+     * Get the display name of the receiver of this share.
281
+     *
282
+     * @return string
283
+     * @since 14.0.0
284
+     */
285
+    public function getSharedWithDisplayName();
286
+
287
+    /**
288
+     * Set the avatar of the receiver of this share.
289
+     *
290
+     * @param string $src
291
+     * @return \OCP\Share\IShare The modified object
292
+     * @since 14.0.0
293
+     */
294
+    public function setSharedWithAvatar($src);
295
+
296
+    /**
297
+     * Get the avatar of the receiver of this share.
298
+     *
299
+     * @return string
300
+     * @since 14.0.0
301
+     */
302
+    public function getSharedWithAvatar();
303
+
304
+    /**
305
+     * Set the permissions.
306
+     * See \OCP\Constants::PERMISSION_*
307
+     *
308
+     * @param int $permissions
309
+     * @return IShare The modified object
310
+     * @since 9.0.0
311
+     */
312
+    public function setPermissions($permissions);
313
+
314
+    /**
315
+     * Get the share permissions
316
+     * See \OCP\Constants::PERMISSION_*
317
+     *
318
+     * @return int
319
+     * @since 9.0.0
320
+     */
321
+    public function getPermissions();
322
+
323
+    /**
324
+     * Create share attributes object
325
+     *
326
+     * @since 25.0.0
327
+     * @return IAttributes
328
+     */
329
+    public function newAttributes(): IAttributes;
330
+
331
+    /**
332
+     * Set share attributes
333
+     *
334
+     * @param ?IAttributes $attributes
335
+     * @since 25.0.0
336
+     * @return IShare The modified object
337
+     */
338
+    public function setAttributes(?IAttributes $attributes);
339
+
340
+    /**
341
+     * Get share attributes
342
+     *
343
+     * @since 25.0.0
344
+     * @return ?IAttributes
345
+     */
346
+    public function getAttributes(): ?IAttributes;
347
+
348
+    /**
349
+     * Set the accepted status
350
+     * See self::STATUS_*
351
+     *
352
+     * @param int $status
353
+     * @return IShare The modified object
354
+     * @since 18.0.0
355
+     */
356
+    public function setStatus(int $status): IShare;
357
+
358
+    /**
359
+     * Get the accepted status
360
+     * See self::STATUS_*
361
+     *
362
+     * @return int
363
+     * @since 18.0.0
364
+     */
365
+    public function getStatus(): int;
366
+
367
+    /**
368
+     * Attach a note to a share
369
+     *
370
+     * @param string $note
371
+     * @return \OCP\Share\IShare The modified object
372
+     * @since 14.0.0
373
+     */
374
+    public function setNote($note);
375
+
376
+    /**
377
+     * Get note attached to a share
378
+     *
379
+     * @return string
380
+     * @since 14.0.0
381
+     */
382
+    public function getNote();
383
+
384
+
385
+    /**
386
+     * Set the expiration date
387
+     *
388
+     * @param null|\DateTime $expireDate
389
+     * @return \OCP\Share\IShare The modified object
390
+     * @since 9.0.0
391
+     */
392
+    public function setExpirationDate($expireDate);
393
+
394
+    /**
395
+     * Get the expiration date
396
+     *
397
+     * @return \DateTime
398
+     * @since 9.0.0
399
+     */
400
+    public function getExpirationDate();
401
+
402
+    /**
403
+     * Is the share expired ?
404
+     *
405
+     * @return boolean
406
+     * @since 18.0.0
407
+     */
408
+    public function isExpired();
409
+
410
+    /**
411
+     * set a label for a share, some shares, e.g. public links can have a label
412
+     *
413
+     * @param string $label
414
+     * @return \OCP\Share\IShare The modified object
415
+     * @since 15.0.0
416
+     */
417
+    public function setLabel($label);
418
+
419
+    /**
420
+     * get label for the share, some shares, e.g. public links can have a label
421
+     *
422
+     * @return string
423
+     * @since 15.0.0
424
+     */
425
+    public function getLabel();
426
+
427
+    /**
428
+     * Set the sharer of the path.
429
+     *
430
+     * @param string $sharedBy
431
+     * @return \OCP\Share\IShare The modified object
432
+     * @since 9.0.0
433
+     */
434
+    public function setSharedBy($sharedBy);
435
+
436
+    /**
437
+     * Get share sharer
438
+     *
439
+     * @return string
440
+     * @since 9.0.0
441
+     */
442
+    public function getSharedBy();
443
+
444
+    /**
445
+     * Set the original share owner (who owns the path that is shared)
446
+     *
447
+     * @param string $shareOwner
448
+     * @return \OCP\Share\IShare The modified object
449
+     * @since 9.0.0
450
+     */
451
+    public function setShareOwner($shareOwner);
452
+
453
+    /**
454
+     * Get the original share owner (who owns the path that is shared)
455
+     *
456
+     * @return string
457
+     * @since 9.0.0
458
+     */
459
+    public function getShareOwner();
460
+
461
+    /**
462
+     * Set the password for this share.
463
+     * When the share is passed to the share manager to be created
464
+     * or updated the password will be hashed.
465
+     *
466
+     * @param string|null $password
467
+     * @return \OCP\Share\IShare The modified object
468
+     * @since 9.0.0
469
+     */
470
+    public function setPassword($password);
471
+
472
+    /**
473
+     * Get the password of this share.
474
+     * If this share is obtained via a shareprovider the password is
475
+     * hashed.
476
+     *
477
+     * @return string
478
+     * @since 9.0.0
479
+     */
480
+    public function getPassword();
481
+
482
+    /**
483
+     * Set the password's expiration time of this share.
484
+     *
485
+     * @return self The modified object
486
+     * @since 24.0.0
487
+     */
488
+    public function setPasswordExpirationTime(?\DateTimeInterface $passwordExpirationTime = null): IShare;
489
+
490
+    /**
491
+     * Get the password's expiration time of this share.
492
+     * @since 24.0.0
493
+     */
494
+    public function getPasswordExpirationTime(): ?\DateTimeInterface;
495
+
496
+    /**
497
+     * Set if the recipient can start a conversation with the owner to get the
498
+     * password using Nextcloud Talk.
499
+     *
500
+     * @param bool $sendPasswordByTalk
501
+     * @return \OCP\Share\IShare The modified object
502
+     * @since 14.0.0
503
+     */
504
+    public function setSendPasswordByTalk(bool $sendPasswordByTalk);
505
+
506
+    /**
507
+     * Get if the recipient can start a conversation with the owner to get the
508
+     * password using Nextcloud Talk.
509
+     * The returned value does not take into account other factors, like Talk
510
+     * being enabled for the owner of the share or not; it just cover whether
511
+     * the option is enabled for the share itself or not.
512
+     *
513
+     * @return bool
514
+     * @since 14.0.0
515
+     */
516
+    public function getSendPasswordByTalk(): bool;
517
+
518
+    /**
519
+     * Set the public link token.
520
+     *
521
+     * @param string $token
522
+     * @return \OCP\Share\IShare The modified object
523
+     * @since 9.0.0
524
+     */
525
+    public function setToken($token);
526
+
527
+    /**
528
+     * Get the public link token.
529
+     *
530
+     * @return string
531
+     * @since 9.0.0
532
+     */
533
+    public function getToken();
534
+
535
+    /**
536
+     * Set the target path of this share relative to the recipients user folder.
537
+     *
538
+     * @param string $target
539
+     * @return \OCP\Share\IShare The modified object
540
+     * @since 9.0.0
541
+     */
542
+    public function setTarget($target);
543
+
544
+    /**
545
+     * Get the target path of this share relative to the recipients user folder.
546
+     *
547
+     * @return string
548
+     * @since 9.0.0
549
+     */
550
+    public function getTarget();
551
+
552
+    /**
553
+     * Set the time this share was created
554
+     *
555
+     * @param \DateTime $shareTime
556
+     * @return \OCP\Share\IShare The modified object
557
+     * @since 9.0.0
558
+     */
559
+    public function setShareTime(\DateTime $shareTime);
560
+
561
+    /**
562
+     * Get the timestamp this share was created
563
+     *
564
+     * @return \DateTime
565
+     * @since 9.0.0
566
+     */
567
+    public function getShareTime();
568
+
569
+    /**
570
+     * Set if the recipient is informed by mail about the share.
571
+     *
572
+     * @param bool $mailSend
573
+     * @return \OCP\Share\IShare The modified object
574
+     * @since 9.0.0
575
+     */
576
+    public function setMailSend($mailSend);
577
+
578
+    /**
579
+     * Get if the recipient informed by mail about the share.
580
+     *
581
+     * @return bool
582
+     * @since 9.0.0
583
+     */
584
+    public function getMailSend();
585
+
586
+    /**
587
+     * Set the cache entry for the shared node
588
+     *
589
+     * @param ICacheEntry $entry
590
+     * @since 11.0.0
591
+     */
592
+    public function setNodeCacheEntry(ICacheEntry $entry);
593
+
594
+    /**
595
+     * Get the cache entry for the shared node
596
+     *
597
+     * @return null|ICacheEntry
598
+     * @since 11.0.0
599
+     */
600
+    public function getNodeCacheEntry();
601
+
602
+    /**
603
+     * Sets a shares hide download state
604
+     * This is mainly for public shares. It will signal that the share page should
605
+     * hide download buttons etc.
606
+     *
607
+     * @param bool $hide
608
+     * @return IShare
609
+     * @since 15.0.0
610
+     */
611
+    public function setHideDownload(bool $hide): IShare;
612
+
613
+    /**
614
+     * Gets a shares hide download state
615
+     * This is mainly for public shares. It will signal that the share page should
616
+     * hide download buttons etc.
617
+     *
618
+     * @return bool
619
+     * @since 15.0.0
620
+     */
621
+    public function getHideDownload(): bool;
622 622
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/SharesPlugin.php 1 patch
Indentation   +171 added lines, -171 removed lines patch added patch discarded remove patch
@@ -43,175 +43,175 @@
 block discarded – undo
43 43
  * Sabre Plugin to provide share-related properties
44 44
  */
45 45
 class SharesPlugin extends \Sabre\DAV\ServerPlugin {
46
-	public const NS_OWNCLOUD = 'http://owncloud.org/ns';
47
-	public const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
48
-	public const SHARETYPES_PROPERTYNAME = '{http://owncloud.org/ns}share-types';
49
-	public const SHAREES_PROPERTYNAME = '{http://nextcloud.org/ns}sharees';
50
-
51
-	/**
52
-	 * Reference to main server object
53
-	 *
54
-	 * @var \Sabre\DAV\Server
55
-	 */
56
-	private $server;
57
-	private IManager $shareManager;
58
-	private Tree $tree;
59
-	private string $userId;
60
-	private Folder $userFolder;
61
-	/** @var IShare[][] */
62
-	private array $cachedShares = [];
63
-	/** @var string[] */
64
-	private array $cachedFolders = [];
65
-
66
-	public function __construct(
67
-		Tree $tree,
68
-		IUserSession $userSession,
69
-		Folder $userFolder,
70
-		IManager $shareManager
71
-	) {
72
-		$this->tree = $tree;
73
-		$this->shareManager = $shareManager;
74
-		$this->userFolder = $userFolder;
75
-		$this->userId = $userSession->getUser()->getUID();
76
-	}
77
-
78
-	/**
79
-	 * This initializes the plugin.
80
-	 *
81
-	 * This function is called by \Sabre\DAV\Server, after
82
-	 * addPlugin is called.
83
-	 *
84
-	 * This method should set up the required event subscriptions.
85
-	 *
86
-	 * @return void
87
-	 */
88
-	public function initialize(Server $server) {
89
-		$server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
90
-		$server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = ShareTypeList::class;
91
-		$server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME;
92
-		$server->protectedProperties[] = self::SHAREES_PROPERTYNAME;
93
-
94
-		$this->server = $server;
95
-		$this->server->on('propFind', [$this, 'handleGetProperties']);
96
-	}
97
-
98
-	/**
99
-	 * @param Node $node
100
-	 * @return IShare[]
101
-	 */
102
-	private function getShare(Node $node): array {
103
-		$result = [];
104
-		$requestedShareTypes = [
105
-			IShare::TYPE_USER,
106
-			IShare::TYPE_GROUP,
107
-			IShare::TYPE_LINK,
108
-			IShare::TYPE_REMOTE,
109
-			IShare::TYPE_EMAIL,
110
-			IShare::TYPE_ROOM,
111
-			IShare::TYPE_CIRCLE,
112
-			IShare::TYPE_DECK,
113
-			IShare::TYPE_SCIENCEMESH,
114
-		];
115
-		foreach ($requestedShareTypes as $requestedShareType) {
116
-			$shares = $this->shareManager->getSharesBy(
117
-				$this->userId,
118
-				$requestedShareType,
119
-				$node,
120
-				false,
121
-				-1
122
-			);
123
-			foreach ($shares as $share) {
124
-				$result[] = $share;
125
-			}
126
-		}
127
-		return $result;
128
-	}
129
-
130
-	/**
131
-	 * @param Folder $node
132
-	 * @return IShare[][]
133
-	 */
134
-	private function getSharesFolder(Folder $node): array {
135
-		return $this->shareManager->getSharesInFolder(
136
-			$this->userId,
137
-			$node,
138
-			true
139
-		);
140
-	}
141
-
142
-	/**
143
-	 * @param DavNode $sabreNode
144
-	 * @return IShare[]
145
-	 */
146
-	private function getShares(DavNode $sabreNode): array {
147
-		if (isset($this->cachedShares[$sabreNode->getId()])) {
148
-			$shares = $this->cachedShares[$sabreNode->getId()];
149
-		} else {
150
-			[$parentPath,] = \Sabre\Uri\split($sabreNode->getPath());
151
-			if ($parentPath === '') {
152
-				$parentPath = '/';
153
-			}
154
-			// if we already cached the folder this file is in we know there are no shares for this file
155
-			if (array_search($parentPath, $this->cachedFolders) === false) {
156
-				try {
157
-					$node = $sabreNode->getNode();
158
-				} catch (NotFoundException $e) {
159
-					return [];
160
-				}
161
-				$shares = $this->getShare($node);
162
-				$this->cachedShares[$sabreNode->getId()] = $shares;
163
-			} else {
164
-				return [];
165
-			}
166
-		}
167
-
168
-		return $shares;
169
-	}
170
-
171
-	/**
172
-	 * Adds shares to propfind response
173
-	 *
174
-	 * @param PropFind $propFind propfind object
175
-	 * @param \Sabre\DAV\INode $sabreNode sabre node
176
-	 */
177
-	public function handleGetProperties(
178
-		PropFind $propFind,
179
-		\Sabre\DAV\INode $sabreNode
180
-	) {
181
-		if (!($sabreNode instanceof DavNode)) {
182
-			return;
183
-		}
184
-
185
-		// need prefetch ?
186
-		if ($sabreNode instanceof Directory
187
-			&& $propFind->getDepth() !== 0
188
-			&& (
189
-				!is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) ||
190
-				!is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
191
-			)
192
-		) {
193
-			$folderNode = $sabreNode->getNode();
194
-			$this->cachedFolders[] = $sabreNode->getPath();
195
-			$childShares = $this->getSharesFolder($folderNode);
196
-			foreach ($childShares as $id => $shares) {
197
-				$this->cachedShares[$id] = $shares;
198
-			}
199
-		}
200
-
201
-		$propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode): ShareTypeList {
202
-			$shares = $this->getShares($sabreNode);
203
-
204
-			$shareTypes = array_unique(array_map(function (IShare $share) {
205
-				return $share->getShareType();
206
-			}, $shares));
207
-
208
-			return new ShareTypeList($shareTypes);
209
-		});
210
-
211
-		$propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode): ShareeList {
212
-			$shares = $this->getShares($sabreNode);
213
-
214
-			return new ShareeList($shares);
215
-		});
216
-	}
46
+    public const NS_OWNCLOUD = 'http://owncloud.org/ns';
47
+    public const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
48
+    public const SHARETYPES_PROPERTYNAME = '{http://owncloud.org/ns}share-types';
49
+    public const SHAREES_PROPERTYNAME = '{http://nextcloud.org/ns}sharees';
50
+
51
+    /**
52
+     * Reference to main server object
53
+     *
54
+     * @var \Sabre\DAV\Server
55
+     */
56
+    private $server;
57
+    private IManager $shareManager;
58
+    private Tree $tree;
59
+    private string $userId;
60
+    private Folder $userFolder;
61
+    /** @var IShare[][] */
62
+    private array $cachedShares = [];
63
+    /** @var string[] */
64
+    private array $cachedFolders = [];
65
+
66
+    public function __construct(
67
+        Tree $tree,
68
+        IUserSession $userSession,
69
+        Folder $userFolder,
70
+        IManager $shareManager
71
+    ) {
72
+        $this->tree = $tree;
73
+        $this->shareManager = $shareManager;
74
+        $this->userFolder = $userFolder;
75
+        $this->userId = $userSession->getUser()->getUID();
76
+    }
77
+
78
+    /**
79
+     * This initializes the plugin.
80
+     *
81
+     * This function is called by \Sabre\DAV\Server, after
82
+     * addPlugin is called.
83
+     *
84
+     * This method should set up the required event subscriptions.
85
+     *
86
+     * @return void
87
+     */
88
+    public function initialize(Server $server) {
89
+        $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
90
+        $server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = ShareTypeList::class;
91
+        $server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME;
92
+        $server->protectedProperties[] = self::SHAREES_PROPERTYNAME;
93
+
94
+        $this->server = $server;
95
+        $this->server->on('propFind', [$this, 'handleGetProperties']);
96
+    }
97
+
98
+    /**
99
+     * @param Node $node
100
+     * @return IShare[]
101
+     */
102
+    private function getShare(Node $node): array {
103
+        $result = [];
104
+        $requestedShareTypes = [
105
+            IShare::TYPE_USER,
106
+            IShare::TYPE_GROUP,
107
+            IShare::TYPE_LINK,
108
+            IShare::TYPE_REMOTE,
109
+            IShare::TYPE_EMAIL,
110
+            IShare::TYPE_ROOM,
111
+            IShare::TYPE_CIRCLE,
112
+            IShare::TYPE_DECK,
113
+            IShare::TYPE_SCIENCEMESH,
114
+        ];
115
+        foreach ($requestedShareTypes as $requestedShareType) {
116
+            $shares = $this->shareManager->getSharesBy(
117
+                $this->userId,
118
+                $requestedShareType,
119
+                $node,
120
+                false,
121
+                -1
122
+            );
123
+            foreach ($shares as $share) {
124
+                $result[] = $share;
125
+            }
126
+        }
127
+        return $result;
128
+    }
129
+
130
+    /**
131
+     * @param Folder $node
132
+     * @return IShare[][]
133
+     */
134
+    private function getSharesFolder(Folder $node): array {
135
+        return $this->shareManager->getSharesInFolder(
136
+            $this->userId,
137
+            $node,
138
+            true
139
+        );
140
+    }
141
+
142
+    /**
143
+     * @param DavNode $sabreNode
144
+     * @return IShare[]
145
+     */
146
+    private function getShares(DavNode $sabreNode): array {
147
+        if (isset($this->cachedShares[$sabreNode->getId()])) {
148
+            $shares = $this->cachedShares[$sabreNode->getId()];
149
+        } else {
150
+            [$parentPath,] = \Sabre\Uri\split($sabreNode->getPath());
151
+            if ($parentPath === '') {
152
+                $parentPath = '/';
153
+            }
154
+            // if we already cached the folder this file is in we know there are no shares for this file
155
+            if (array_search($parentPath, $this->cachedFolders) === false) {
156
+                try {
157
+                    $node = $sabreNode->getNode();
158
+                } catch (NotFoundException $e) {
159
+                    return [];
160
+                }
161
+                $shares = $this->getShare($node);
162
+                $this->cachedShares[$sabreNode->getId()] = $shares;
163
+            } else {
164
+                return [];
165
+            }
166
+        }
167
+
168
+        return $shares;
169
+    }
170
+
171
+    /**
172
+     * Adds shares to propfind response
173
+     *
174
+     * @param PropFind $propFind propfind object
175
+     * @param \Sabre\DAV\INode $sabreNode sabre node
176
+     */
177
+    public function handleGetProperties(
178
+        PropFind $propFind,
179
+        \Sabre\DAV\INode $sabreNode
180
+    ) {
181
+        if (!($sabreNode instanceof DavNode)) {
182
+            return;
183
+        }
184
+
185
+        // need prefetch ?
186
+        if ($sabreNode instanceof Directory
187
+            && $propFind->getDepth() !== 0
188
+            && (
189
+                !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) ||
190
+                !is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
191
+            )
192
+        ) {
193
+            $folderNode = $sabreNode->getNode();
194
+            $this->cachedFolders[] = $sabreNode->getPath();
195
+            $childShares = $this->getSharesFolder($folderNode);
196
+            foreach ($childShares as $id => $shares) {
197
+                $this->cachedShares[$id] = $shares;
198
+            }
199
+        }
200
+
201
+        $propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode): ShareTypeList {
202
+            $shares = $this->getShares($sabreNode);
203
+
204
+            $shareTypes = array_unique(array_map(function (IShare $share) {
205
+                return $share->getShareType();
206
+            }, $shares));
207
+
208
+            return new ShareTypeList($shareTypes);
209
+        });
210
+
211
+        $propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode): ShareeList {
212
+            $shares = $this->getShares($sabreNode);
213
+
214
+            return new ShareeList($shares);
215
+        });
216
+    }
217 217
 }
Please login to merge, or discard this patch.
apps/files/lib/Service/OwnershipTransferService.php 1 patch
Indentation   +453 added lines, -453 removed lines patch added patch discarded remove patch
@@ -58,457 +58,457 @@
 block discarded – undo
58 58
 
59 59
 class OwnershipTransferService {
60 60
 
61
-	/** @var IEncryptionManager */
62
-	private $encryptionManager;
63
-
64
-	/** @var IShareManager */
65
-	private $shareManager;
66
-
67
-	/** @var IMountManager */
68
-	private $mountManager;
69
-
70
-	/** @var IUserMountCache */
71
-	private $userMountCache;
72
-
73
-	/** @var IUserManager */
74
-	private $userManager;
75
-
76
-	public function __construct(IEncryptionManager $manager,
77
-								IShareManager $shareManager,
78
-								IMountManager $mountManager,
79
-								IUserMountCache $userMountCache,
80
-								IUserManager $userManager) {
81
-		$this->encryptionManager = $manager;
82
-		$this->shareManager = $shareManager;
83
-		$this->mountManager = $mountManager;
84
-		$this->userMountCache = $userMountCache;
85
-		$this->userManager = $userManager;
86
-	}
87
-
88
-	/**
89
-	 * @param IUser $sourceUser
90
-	 * @param IUser $destinationUser
91
-	 * @param string $path
92
-	 *
93
-	 * @param OutputInterface|null $output
94
-	 * @param bool $move
95
-	 * @throws TransferOwnershipException
96
-	 * @throws \OC\User\NoUserException
97
-	 */
98
-	public function transfer(IUser $sourceUser,
99
-							 IUser $destinationUser,
100
-							 string $path,
101
-							 ?OutputInterface $output = null,
102
-							 bool $move = false,
103
-							 bool $firstLogin = false,
104
-							 bool $transferIncomingShares = false): void {
105
-		$output = $output ?? new NullOutput();
106
-		$sourceUid = $sourceUser->getUID();
107
-		$destinationUid = $destinationUser->getUID();
108
-		$sourcePath = rtrim($sourceUid . '/files/' . $path, '/');
109
-
110
-		// If encryption is on we have to ensure the user has logged in before and that all encryption modules are ready
111
-		if (($this->encryptionManager->isEnabled() && $destinationUser->getLastLogin() === 0)
112
-			|| !$this->encryptionManager->isReadyForUser($destinationUid)) {
113
-			throw new TransferOwnershipException("The target user is not ready to accept files. The user has at least to have logged in once.", 2);
114
-		}
115
-
116
-		// setup filesystem
117
-		// Requesting the user folder will set it up if the user hasn't logged in before
118
-		\OC::$server->getUserFolder($destinationUser->getUID());
119
-		Filesystem::initMountPoints($sourceUid);
120
-		Filesystem::initMountPoints($destinationUid);
121
-
122
-		$view = new View();
123
-
124
-		if ($move) {
125
-			$finalTarget = "$destinationUid/files/";
126
-		} else {
127
-			$date = date('Y-m-d H-i-s');
128
-
129
-			// Remove some characters which are prone to cause errors
130
-			$cleanUserName = str_replace(['\\', '/', ':', '.', '?', '#', '\'', '"'], '-', $sourceUser->getDisplayName());
131
-			// Replace multiple dashes with one dash
132
-			$cleanUserName = preg_replace('/-{2,}/s', '-', $cleanUserName);
133
-			$cleanUserName = $cleanUserName ?: $sourceUid;
134
-
135
-			$finalTarget = "$destinationUid/files/transferred from $cleanUserName on $date";
136
-			try {
137
-				$view->verifyPath(dirname($finalTarget), basename($finalTarget));
138
-			} catch (InvalidPathException $e) {
139
-				$finalTarget = "$destinationUid/files/transferred from $sourceUid on $date";
140
-			}
141
-		}
142
-
143
-		if (!($view->is_dir($sourcePath) || $view->is_file($sourcePath))) {
144
-			throw new TransferOwnershipException("Unknown path provided: $path", 1);
145
-		}
146
-
147
-		if ($move && !$view->is_dir($finalTarget)) {
148
-			// Initialize storage
149
-			\OC_Util::setupFS($destinationUser->getUID());
150
-		}
151
-
152
-		if ($move && !$firstLogin && count($view->getDirectoryContent($finalTarget)) > 0) {
153
-			throw new TransferOwnershipException("Destination path does not exists or is not empty", 1);
154
-		}
155
-
156
-
157
-		// analyse source folder
158
-		$this->analyse(
159
-			$sourceUid,
160
-			$destinationUid,
161
-			$sourcePath,
162
-			$view,
163
-			$output
164
-		);
165
-
166
-		// collect all the shares
167
-		$shares = $this->collectUsersShares(
168
-			$sourceUid,
169
-			$output,
170
-			$view,
171
-			$sourcePath
172
-		);
173
-
174
-		// transfer the files
175
-		$this->transferFiles(
176
-			$sourceUid,
177
-			$sourcePath,
178
-			$finalTarget,
179
-			$view,
180
-			$output
181
-		);
182
-
183
-		// restore the shares
184
-		$this->restoreShares(
185
-			$sourceUid,
186
-			$destinationUid,
187
-			$shares,
188
-			$output
189
-		);
190
-
191
-		// transfer the incoming shares
192
-		if ($transferIncomingShares === true) {
193
-			$sourceShares = $this->collectIncomingShares(
194
-				$sourceUid,
195
-				$output,
196
-				$view
197
-			);
198
-			$destinationShares = $this->collectIncomingShares(
199
-				$destinationUid,
200
-				$output,
201
-				$view,
202
-				true
203
-			);
204
-			$this->transferIncomingShares(
205
-				$sourceUid,
206
-				$destinationUid,
207
-				$sourceShares,
208
-				$destinationShares,
209
-				$output,
210
-				$path,
211
-				$finalTarget,
212
-				$move
213
-			);
214
-		}
215
-	}
216
-
217
-	private function walkFiles(View $view, $path, Closure $callBack) {
218
-		foreach ($view->getDirectoryContent($path) as $fileInfo) {
219
-			if (!$callBack($fileInfo)) {
220
-				return;
221
-			}
222
-			if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
223
-				$this->walkFiles($view, $fileInfo->getPath(), $callBack);
224
-			}
225
-		}
226
-	}
227
-
228
-	/**
229
-	 * @param OutputInterface $output
230
-	 *
231
-	 * @throws \Exception
232
-	 */
233
-	protected function analyse(string $sourceUid,
234
-							   string $destinationUid,
235
-							   string $sourcePath,
236
-							   View $view,
237
-							   OutputInterface $output): void {
238
-		$output->writeln('Validating quota');
239
-		$size = $view->getFileInfo($sourcePath, false)->getSize(false);
240
-		$freeSpace = $view->free_space($destinationUid . '/files/');
241
-		if ($size > $freeSpace && $freeSpace !== FileInfo::SPACE_UNKNOWN) {
242
-			$output->writeln('<error>Target user does not have enough free space available.</error>');
243
-			throw new \Exception('Execution terminated.');
244
-		}
245
-
246
-		$output->writeln("Analysing files of $sourceUid ...");
247
-		$progress = new ProgressBar($output);
248
-		$progress->start();
249
-
250
-		$encryptedFiles = [];
251
-		$this->walkFiles($view, $sourcePath,
252
-			function (FileInfo $fileInfo) use ($progress) {
253
-				if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
254
-					// only analyze into folders from main storage,
255
-					if (!$fileInfo->getStorage()->instanceOfStorage(IHomeStorage::class)) {
256
-						return false;
257
-					}
258
-					return true;
259
-				}
260
-				$progress->advance();
261
-				if ($fileInfo->isEncrypted()) {
262
-					$encryptedFiles[] = $fileInfo;
263
-				}
264
-				return true;
265
-			});
266
-		$progress->finish();
267
-		$output->writeln('');
268
-
269
-		// no file is allowed to be encrypted
270
-		if (!empty($encryptedFiles)) {
271
-			$output->writeln("<error>Some files are encrypted - please decrypt them first.</error>");
272
-			foreach ($encryptedFiles as $encryptedFile) {
273
-				/** @var FileInfo $encryptedFile */
274
-				$output->writeln("  " . $encryptedFile->getPath());
275
-			}
276
-			throw new \Exception('Execution terminated.');
277
-		}
278
-	}
279
-
280
-	private function collectUsersShares(string $sourceUid,
281
-										OutputInterface $output,
282
-										View $view,
283
-										string $path): array {
284
-		$output->writeln("Collecting all share information for files and folders of $sourceUid ...");
285
-
286
-		$shares = [];
287
-		$progress = new ProgressBar($output);
288
-
289
-		foreach ([IShare::TYPE_GROUP, IShare::TYPE_USER, IShare::TYPE_LINK, IShare::TYPE_REMOTE, IShare::TYPE_ROOM, IShare::TYPE_EMAIL, IShare::TYPE_CIRCLE, IShare::TYPE_DECK, IShare::TYPE_SCIENCEMESH] as $shareType) {
290
-			$offset = 0;
291
-			while (true) {
292
-				$sharePage = $this->shareManager->getSharesBy($sourceUid, $shareType, null, true, 50, $offset);
293
-				$progress->advance(count($sharePage));
294
-				if (empty($sharePage)) {
295
-					break;
296
-				}
297
-				if ($path !== "$sourceUid/files") {
298
-					$sharePage = array_filter($sharePage, function (IShare $share) use ($view, $path) {
299
-						try {
300
-							$relativePath = $view->getPath($share->getNodeId());
301
-							$singleFileTranfer = $view->is_file($path);
302
-							if ($singleFileTranfer) {
303
-								return Filesystem::normalizePath($relativePath) === Filesystem::normalizePath($path);
304
-							}
305
-
306
-							return mb_strpos(
307
-								Filesystem::normalizePath($relativePath . '/', false),
308
-								Filesystem::normalizePath($path . '/', false)) === 0;
309
-						} catch (\Exception $e) {
310
-							return false;
311
-						}
312
-					});
313
-				}
314
-				$shares = array_merge($shares, $sharePage);
315
-				$offset += 50;
316
-			}
317
-		}
318
-
319
-		$progress->finish();
320
-		$output->writeln('');
321
-		return $shares;
322
-	}
323
-
324
-	private function collectIncomingShares(string $sourceUid,
325
-										OutputInterface $output,
326
-										View $view,
327
-										bool $addKeys = false): array {
328
-		$output->writeln("Collecting all incoming share information for files and folders of $sourceUid ...");
329
-
330
-		$shares = [];
331
-		$progress = new ProgressBar($output);
332
-
333
-		$offset = 0;
334
-		while (true) {
335
-			$sharePage = $this->shareManager->getSharedWith($sourceUid, IShare::TYPE_USER, null, 50, $offset);
336
-			$progress->advance(count($sharePage));
337
-			if (empty($sharePage)) {
338
-				break;
339
-			}
340
-			if ($addKeys) {
341
-				foreach ($sharePage as $singleShare) {
342
-					$shares[$singleShare->getNodeId()] = $singleShare;
343
-				}
344
-			} else {
345
-				foreach ($sharePage as $singleShare) {
346
-					$shares[] = $singleShare;
347
-				}
348
-			}
349
-
350
-			$offset += 50;
351
-		}
352
-
353
-
354
-		$progress->finish();
355
-		$output->writeln('');
356
-		return $shares;
357
-	}
358
-
359
-	/**
360
-	 * @throws TransferOwnershipException
361
-	 */
362
-	protected function transferFiles(string $sourceUid,
363
-									 string $sourcePath,
364
-									 string $finalTarget,
365
-									 View $view,
366
-									 OutputInterface $output): void {
367
-		$output->writeln("Transferring files to $finalTarget ...");
368
-
369
-		// This change will help user to transfer the folder specified using --path option.
370
-		// Else only the content inside folder is transferred which is not correct.
371
-		if ($sourcePath !== "$sourceUid/files") {
372
-			$view->mkdir($finalTarget);
373
-			$finalTarget = $finalTarget . '/' . basename($sourcePath);
374
-		}
375
-		if ($view->rename($sourcePath, $finalTarget) === false) {
376
-			throw new TransferOwnershipException("Could not transfer files.", 1);
377
-		}
378
-		if (!is_dir("$sourceUid/files")) {
379
-			// because the files folder is moved away we need to recreate it
380
-			$view->mkdir("$sourceUid/files");
381
-		}
382
-	}
383
-
384
-	private function restoreShares(string $sourceUid,
385
-								   string $destinationUid,
386
-								   array $shares,
387
-								   OutputInterface $output) {
388
-		$output->writeln("Restoring shares ...");
389
-		$progress = new ProgressBar($output, count($shares));
390
-
391
-		foreach ($shares as $share) {
392
-			try {
393
-				if ($share->getShareType() === IShare::TYPE_USER &&
394
-					$share->getSharedWith() === $destinationUid) {
395
-					// Unmount the shares before deleting, so we don't try to get the storage later on.
396
-					$shareMountPoint = $this->mountManager->find('/' . $destinationUid . '/files' . $share->getTarget());
397
-					if ($shareMountPoint) {
398
-						$this->mountManager->removeMount($shareMountPoint->getMountPoint());
399
-					}
400
-					$this->shareManager->deleteShare($share);
401
-				} else {
402
-					if ($share->getShareOwner() === $sourceUid) {
403
-						$share->setShareOwner($destinationUid);
404
-					}
405
-					if ($share->getSharedBy() === $sourceUid) {
406
-						$share->setSharedBy($destinationUid);
407
-					}
408
-
409
-					if ($share->getShareType() === IShare::TYPE_USER &&
410
-						!$this->userManager->userExists($share->getSharedWith())) {
411
-						// stray share with deleted user
412
-						$output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted user "' . $share->getSharedWith() . '", deleting</error>');
413
-						$this->shareManager->deleteShare($share);
414
-						continue;
415
-					} else {
416
-						// trigger refetching of the node so that the new owner and mountpoint are taken into account
417
-						// otherwise the checks on the share update will fail due to the original node not being available in the new user scope
418
-						$this->userMountCache->clear();
419
-						$share->setNodeId($share->getNode()->getId());
420
-
421
-						$this->shareManager->updateShare($share);
422
-					}
423
-				}
424
-			} catch (\OCP\Files\NotFoundException $e) {
425
-				$output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted file, skipping</error>');
426
-			} catch (\Throwable $e) {
427
-				$output->writeln('<error>Could not restore share with id ' . $share->getId() . ':' . $e->getMessage() . ' : ' . $e->getTraceAsString() . '</error>');
428
-			}
429
-			$progress->advance();
430
-		}
431
-		$progress->finish();
432
-		$output->writeln('');
433
-	}
434
-
435
-	private function transferIncomingShares(string $sourceUid,
436
-								   string $destinationUid,
437
-								   array $sourceShares,
438
-								   array $destinationShares,
439
-								   OutputInterface $output,
440
-								   string $path,
441
-								   string $finalTarget,
442
-								   bool $move): void {
443
-		$output->writeln("Restoring incoming shares ...");
444
-		$progress = new ProgressBar($output, count($sourceShares));
445
-		$prefix = "$destinationUid/files";
446
-		$finalShareTarget = '';
447
-		if (substr($finalTarget, 0, strlen($prefix)) === $prefix) {
448
-			$finalShareTarget = substr($finalTarget, strlen($prefix));
449
-		}
450
-		foreach ($sourceShares as $share) {
451
-			try {
452
-				// Only restore if share is in given path.
453
-				$pathToCheck = '/';
454
-				if (trim($path, '/') !== '') {
455
-					$pathToCheck = '/' . trim($path) . '/';
456
-				}
457
-				if (substr($share->getTarget(), 0, strlen($pathToCheck)) !== $pathToCheck) {
458
-					continue;
459
-				}
460
-				$shareTarget = $share->getTarget();
461
-				$shareTarget = $finalShareTarget . $shareTarget;
462
-				if ($share->getShareType() === IShare::TYPE_USER &&
463
-					$share->getSharedBy() === $destinationUid) {
464
-					$this->shareManager->deleteShare($share);
465
-				} elseif (isset($destinationShares[$share->getNodeId()])) {
466
-					$destinationShare = $destinationShares[$share->getNodeId()];
467
-					// Keep the share which has the most permissions and discard the other one.
468
-					if ($destinationShare->getPermissions() < $share->getPermissions()) {
469
-						$this->shareManager->deleteShare($destinationShare);
470
-						$share->setSharedWith($destinationUid);
471
-						// trigger refetching of the node so that the new owner and mountpoint are taken into account
472
-						// otherwise the checks on the share update will fail due to the original node not being available in the new user scope
473
-						$this->userMountCache->clear();
474
-						$share->setNodeId($share->getNode()->getId());
475
-						$this->shareManager->updateShare($share);
476
-						// The share is already transferred.
477
-						$progress->advance();
478
-						if ($move) {
479
-							continue;
480
-						}
481
-						$share->setTarget($shareTarget);
482
-						$this->shareManager->moveShare($share, $destinationUid);
483
-						continue;
484
-					}
485
-					$this->shareManager->deleteShare($share);
486
-				} elseif ($share->getShareOwner() === $destinationUid) {
487
-					$this->shareManager->deleteShare($share);
488
-				} else {
489
-					$share->setSharedWith($destinationUid);
490
-					$share->setNodeId($share->getNode()->getId());
491
-					$this->shareManager->updateShare($share);
492
-					// trigger refetching of the node so that the new owner and mountpoint are taken into account
493
-					// otherwise the checks on the share update will fail due to the original node not being available in the new user scope
494
-					$this->userMountCache->clear();
495
-					// The share is already transferred.
496
-					$progress->advance();
497
-					if ($move) {
498
-						continue;
499
-					}
500
-					$share->setTarget($shareTarget);
501
-					$this->shareManager->moveShare($share, $destinationUid);
502
-					continue;
503
-				}
504
-			} catch (\OCP\Files\NotFoundException $e) {
505
-				$output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted file, skipping</error>');
506
-			} catch (\Throwable $e) {
507
-				$output->writeln('<error>Could not restore share with id ' . $share->getId() . ':' . $e->getTraceAsString() . '</error>');
508
-			}
509
-			$progress->advance();
510
-		}
511
-		$progress->finish();
512
-		$output->writeln('');
513
-	}
61
+    /** @var IEncryptionManager */
62
+    private $encryptionManager;
63
+
64
+    /** @var IShareManager */
65
+    private $shareManager;
66
+
67
+    /** @var IMountManager */
68
+    private $mountManager;
69
+
70
+    /** @var IUserMountCache */
71
+    private $userMountCache;
72
+
73
+    /** @var IUserManager */
74
+    private $userManager;
75
+
76
+    public function __construct(IEncryptionManager $manager,
77
+                                IShareManager $shareManager,
78
+                                IMountManager $mountManager,
79
+                                IUserMountCache $userMountCache,
80
+                                IUserManager $userManager) {
81
+        $this->encryptionManager = $manager;
82
+        $this->shareManager = $shareManager;
83
+        $this->mountManager = $mountManager;
84
+        $this->userMountCache = $userMountCache;
85
+        $this->userManager = $userManager;
86
+    }
87
+
88
+    /**
89
+     * @param IUser $sourceUser
90
+     * @param IUser $destinationUser
91
+     * @param string $path
92
+     *
93
+     * @param OutputInterface|null $output
94
+     * @param bool $move
95
+     * @throws TransferOwnershipException
96
+     * @throws \OC\User\NoUserException
97
+     */
98
+    public function transfer(IUser $sourceUser,
99
+                                IUser $destinationUser,
100
+                                string $path,
101
+                             ?OutputInterface $output = null,
102
+                                bool $move = false,
103
+                                bool $firstLogin = false,
104
+                                bool $transferIncomingShares = false): void {
105
+        $output = $output ?? new NullOutput();
106
+        $sourceUid = $sourceUser->getUID();
107
+        $destinationUid = $destinationUser->getUID();
108
+        $sourcePath = rtrim($sourceUid . '/files/' . $path, '/');
109
+
110
+        // If encryption is on we have to ensure the user has logged in before and that all encryption modules are ready
111
+        if (($this->encryptionManager->isEnabled() && $destinationUser->getLastLogin() === 0)
112
+            || !$this->encryptionManager->isReadyForUser($destinationUid)) {
113
+            throw new TransferOwnershipException("The target user is not ready to accept files. The user has at least to have logged in once.", 2);
114
+        }
115
+
116
+        // setup filesystem
117
+        // Requesting the user folder will set it up if the user hasn't logged in before
118
+        \OC::$server->getUserFolder($destinationUser->getUID());
119
+        Filesystem::initMountPoints($sourceUid);
120
+        Filesystem::initMountPoints($destinationUid);
121
+
122
+        $view = new View();
123
+
124
+        if ($move) {
125
+            $finalTarget = "$destinationUid/files/";
126
+        } else {
127
+            $date = date('Y-m-d H-i-s');
128
+
129
+            // Remove some characters which are prone to cause errors
130
+            $cleanUserName = str_replace(['\\', '/', ':', '.', '?', '#', '\'', '"'], '-', $sourceUser->getDisplayName());
131
+            // Replace multiple dashes with one dash
132
+            $cleanUserName = preg_replace('/-{2,}/s', '-', $cleanUserName);
133
+            $cleanUserName = $cleanUserName ?: $sourceUid;
134
+
135
+            $finalTarget = "$destinationUid/files/transferred from $cleanUserName on $date";
136
+            try {
137
+                $view->verifyPath(dirname($finalTarget), basename($finalTarget));
138
+            } catch (InvalidPathException $e) {
139
+                $finalTarget = "$destinationUid/files/transferred from $sourceUid on $date";
140
+            }
141
+        }
142
+
143
+        if (!($view->is_dir($sourcePath) || $view->is_file($sourcePath))) {
144
+            throw new TransferOwnershipException("Unknown path provided: $path", 1);
145
+        }
146
+
147
+        if ($move && !$view->is_dir($finalTarget)) {
148
+            // Initialize storage
149
+            \OC_Util::setupFS($destinationUser->getUID());
150
+        }
151
+
152
+        if ($move && !$firstLogin && count($view->getDirectoryContent($finalTarget)) > 0) {
153
+            throw new TransferOwnershipException("Destination path does not exists or is not empty", 1);
154
+        }
155
+
156
+
157
+        // analyse source folder
158
+        $this->analyse(
159
+            $sourceUid,
160
+            $destinationUid,
161
+            $sourcePath,
162
+            $view,
163
+            $output
164
+        );
165
+
166
+        // collect all the shares
167
+        $shares = $this->collectUsersShares(
168
+            $sourceUid,
169
+            $output,
170
+            $view,
171
+            $sourcePath
172
+        );
173
+
174
+        // transfer the files
175
+        $this->transferFiles(
176
+            $sourceUid,
177
+            $sourcePath,
178
+            $finalTarget,
179
+            $view,
180
+            $output
181
+        );
182
+
183
+        // restore the shares
184
+        $this->restoreShares(
185
+            $sourceUid,
186
+            $destinationUid,
187
+            $shares,
188
+            $output
189
+        );
190
+
191
+        // transfer the incoming shares
192
+        if ($transferIncomingShares === true) {
193
+            $sourceShares = $this->collectIncomingShares(
194
+                $sourceUid,
195
+                $output,
196
+                $view
197
+            );
198
+            $destinationShares = $this->collectIncomingShares(
199
+                $destinationUid,
200
+                $output,
201
+                $view,
202
+                true
203
+            );
204
+            $this->transferIncomingShares(
205
+                $sourceUid,
206
+                $destinationUid,
207
+                $sourceShares,
208
+                $destinationShares,
209
+                $output,
210
+                $path,
211
+                $finalTarget,
212
+                $move
213
+            );
214
+        }
215
+    }
216
+
217
+    private function walkFiles(View $view, $path, Closure $callBack) {
218
+        foreach ($view->getDirectoryContent($path) as $fileInfo) {
219
+            if (!$callBack($fileInfo)) {
220
+                return;
221
+            }
222
+            if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
223
+                $this->walkFiles($view, $fileInfo->getPath(), $callBack);
224
+            }
225
+        }
226
+    }
227
+
228
+    /**
229
+     * @param OutputInterface $output
230
+     *
231
+     * @throws \Exception
232
+     */
233
+    protected function analyse(string $sourceUid,
234
+                                string $destinationUid,
235
+                                string $sourcePath,
236
+                                View $view,
237
+                                OutputInterface $output): void {
238
+        $output->writeln('Validating quota');
239
+        $size = $view->getFileInfo($sourcePath, false)->getSize(false);
240
+        $freeSpace = $view->free_space($destinationUid . '/files/');
241
+        if ($size > $freeSpace && $freeSpace !== FileInfo::SPACE_UNKNOWN) {
242
+            $output->writeln('<error>Target user does not have enough free space available.</error>');
243
+            throw new \Exception('Execution terminated.');
244
+        }
245
+
246
+        $output->writeln("Analysing files of $sourceUid ...");
247
+        $progress = new ProgressBar($output);
248
+        $progress->start();
249
+
250
+        $encryptedFiles = [];
251
+        $this->walkFiles($view, $sourcePath,
252
+            function (FileInfo $fileInfo) use ($progress) {
253
+                if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
254
+                    // only analyze into folders from main storage,
255
+                    if (!$fileInfo->getStorage()->instanceOfStorage(IHomeStorage::class)) {
256
+                        return false;
257
+                    }
258
+                    return true;
259
+                }
260
+                $progress->advance();
261
+                if ($fileInfo->isEncrypted()) {
262
+                    $encryptedFiles[] = $fileInfo;
263
+                }
264
+                return true;
265
+            });
266
+        $progress->finish();
267
+        $output->writeln('');
268
+
269
+        // no file is allowed to be encrypted
270
+        if (!empty($encryptedFiles)) {
271
+            $output->writeln("<error>Some files are encrypted - please decrypt them first.</error>");
272
+            foreach ($encryptedFiles as $encryptedFile) {
273
+                /** @var FileInfo $encryptedFile */
274
+                $output->writeln("  " . $encryptedFile->getPath());
275
+            }
276
+            throw new \Exception('Execution terminated.');
277
+        }
278
+    }
279
+
280
+    private function collectUsersShares(string $sourceUid,
281
+                                        OutputInterface $output,
282
+                                        View $view,
283
+                                        string $path): array {
284
+        $output->writeln("Collecting all share information for files and folders of $sourceUid ...");
285
+
286
+        $shares = [];
287
+        $progress = new ProgressBar($output);
288
+
289
+        foreach ([IShare::TYPE_GROUP, IShare::TYPE_USER, IShare::TYPE_LINK, IShare::TYPE_REMOTE, IShare::TYPE_ROOM, IShare::TYPE_EMAIL, IShare::TYPE_CIRCLE, IShare::TYPE_DECK, IShare::TYPE_SCIENCEMESH] as $shareType) {
290
+            $offset = 0;
291
+            while (true) {
292
+                $sharePage = $this->shareManager->getSharesBy($sourceUid, $shareType, null, true, 50, $offset);
293
+                $progress->advance(count($sharePage));
294
+                if (empty($sharePage)) {
295
+                    break;
296
+                }
297
+                if ($path !== "$sourceUid/files") {
298
+                    $sharePage = array_filter($sharePage, function (IShare $share) use ($view, $path) {
299
+                        try {
300
+                            $relativePath = $view->getPath($share->getNodeId());
301
+                            $singleFileTranfer = $view->is_file($path);
302
+                            if ($singleFileTranfer) {
303
+                                return Filesystem::normalizePath($relativePath) === Filesystem::normalizePath($path);
304
+                            }
305
+
306
+                            return mb_strpos(
307
+                                Filesystem::normalizePath($relativePath . '/', false),
308
+                                Filesystem::normalizePath($path . '/', false)) === 0;
309
+                        } catch (\Exception $e) {
310
+                            return false;
311
+                        }
312
+                    });
313
+                }
314
+                $shares = array_merge($shares, $sharePage);
315
+                $offset += 50;
316
+            }
317
+        }
318
+
319
+        $progress->finish();
320
+        $output->writeln('');
321
+        return $shares;
322
+    }
323
+
324
+    private function collectIncomingShares(string $sourceUid,
325
+                                        OutputInterface $output,
326
+                                        View $view,
327
+                                        bool $addKeys = false): array {
328
+        $output->writeln("Collecting all incoming share information for files and folders of $sourceUid ...");
329
+
330
+        $shares = [];
331
+        $progress = new ProgressBar($output);
332
+
333
+        $offset = 0;
334
+        while (true) {
335
+            $sharePage = $this->shareManager->getSharedWith($sourceUid, IShare::TYPE_USER, null, 50, $offset);
336
+            $progress->advance(count($sharePage));
337
+            if (empty($sharePage)) {
338
+                break;
339
+            }
340
+            if ($addKeys) {
341
+                foreach ($sharePage as $singleShare) {
342
+                    $shares[$singleShare->getNodeId()] = $singleShare;
343
+                }
344
+            } else {
345
+                foreach ($sharePage as $singleShare) {
346
+                    $shares[] = $singleShare;
347
+                }
348
+            }
349
+
350
+            $offset += 50;
351
+        }
352
+
353
+
354
+        $progress->finish();
355
+        $output->writeln('');
356
+        return $shares;
357
+    }
358
+
359
+    /**
360
+     * @throws TransferOwnershipException
361
+     */
362
+    protected function transferFiles(string $sourceUid,
363
+                                        string $sourcePath,
364
+                                        string $finalTarget,
365
+                                        View $view,
366
+                                        OutputInterface $output): void {
367
+        $output->writeln("Transferring files to $finalTarget ...");
368
+
369
+        // This change will help user to transfer the folder specified using --path option.
370
+        // Else only the content inside folder is transferred which is not correct.
371
+        if ($sourcePath !== "$sourceUid/files") {
372
+            $view->mkdir($finalTarget);
373
+            $finalTarget = $finalTarget . '/' . basename($sourcePath);
374
+        }
375
+        if ($view->rename($sourcePath, $finalTarget) === false) {
376
+            throw new TransferOwnershipException("Could not transfer files.", 1);
377
+        }
378
+        if (!is_dir("$sourceUid/files")) {
379
+            // because the files folder is moved away we need to recreate it
380
+            $view->mkdir("$sourceUid/files");
381
+        }
382
+    }
383
+
384
+    private function restoreShares(string $sourceUid,
385
+                                    string $destinationUid,
386
+                                    array $shares,
387
+                                    OutputInterface $output) {
388
+        $output->writeln("Restoring shares ...");
389
+        $progress = new ProgressBar($output, count($shares));
390
+
391
+        foreach ($shares as $share) {
392
+            try {
393
+                if ($share->getShareType() === IShare::TYPE_USER &&
394
+                    $share->getSharedWith() === $destinationUid) {
395
+                    // Unmount the shares before deleting, so we don't try to get the storage later on.
396
+                    $shareMountPoint = $this->mountManager->find('/' . $destinationUid . '/files' . $share->getTarget());
397
+                    if ($shareMountPoint) {
398
+                        $this->mountManager->removeMount($shareMountPoint->getMountPoint());
399
+                    }
400
+                    $this->shareManager->deleteShare($share);
401
+                } else {
402
+                    if ($share->getShareOwner() === $sourceUid) {
403
+                        $share->setShareOwner($destinationUid);
404
+                    }
405
+                    if ($share->getSharedBy() === $sourceUid) {
406
+                        $share->setSharedBy($destinationUid);
407
+                    }
408
+
409
+                    if ($share->getShareType() === IShare::TYPE_USER &&
410
+                        !$this->userManager->userExists($share->getSharedWith())) {
411
+                        // stray share with deleted user
412
+                        $output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted user "' . $share->getSharedWith() . '", deleting</error>');
413
+                        $this->shareManager->deleteShare($share);
414
+                        continue;
415
+                    } else {
416
+                        // trigger refetching of the node so that the new owner and mountpoint are taken into account
417
+                        // otherwise the checks on the share update will fail due to the original node not being available in the new user scope
418
+                        $this->userMountCache->clear();
419
+                        $share->setNodeId($share->getNode()->getId());
420
+
421
+                        $this->shareManager->updateShare($share);
422
+                    }
423
+                }
424
+            } catch (\OCP\Files\NotFoundException $e) {
425
+                $output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted file, skipping</error>');
426
+            } catch (\Throwable $e) {
427
+                $output->writeln('<error>Could not restore share with id ' . $share->getId() . ':' . $e->getMessage() . ' : ' . $e->getTraceAsString() . '</error>');
428
+            }
429
+            $progress->advance();
430
+        }
431
+        $progress->finish();
432
+        $output->writeln('');
433
+    }
434
+
435
+    private function transferIncomingShares(string $sourceUid,
436
+                                    string $destinationUid,
437
+                                    array $sourceShares,
438
+                                    array $destinationShares,
439
+                                    OutputInterface $output,
440
+                                    string $path,
441
+                                    string $finalTarget,
442
+                                    bool $move): void {
443
+        $output->writeln("Restoring incoming shares ...");
444
+        $progress = new ProgressBar($output, count($sourceShares));
445
+        $prefix = "$destinationUid/files";
446
+        $finalShareTarget = '';
447
+        if (substr($finalTarget, 0, strlen($prefix)) === $prefix) {
448
+            $finalShareTarget = substr($finalTarget, strlen($prefix));
449
+        }
450
+        foreach ($sourceShares as $share) {
451
+            try {
452
+                // Only restore if share is in given path.
453
+                $pathToCheck = '/';
454
+                if (trim($path, '/') !== '') {
455
+                    $pathToCheck = '/' . trim($path) . '/';
456
+                }
457
+                if (substr($share->getTarget(), 0, strlen($pathToCheck)) !== $pathToCheck) {
458
+                    continue;
459
+                }
460
+                $shareTarget = $share->getTarget();
461
+                $shareTarget = $finalShareTarget . $shareTarget;
462
+                if ($share->getShareType() === IShare::TYPE_USER &&
463
+                    $share->getSharedBy() === $destinationUid) {
464
+                    $this->shareManager->deleteShare($share);
465
+                } elseif (isset($destinationShares[$share->getNodeId()])) {
466
+                    $destinationShare = $destinationShares[$share->getNodeId()];
467
+                    // Keep the share which has the most permissions and discard the other one.
468
+                    if ($destinationShare->getPermissions() < $share->getPermissions()) {
469
+                        $this->shareManager->deleteShare($destinationShare);
470
+                        $share->setSharedWith($destinationUid);
471
+                        // trigger refetching of the node so that the new owner and mountpoint are taken into account
472
+                        // otherwise the checks on the share update will fail due to the original node not being available in the new user scope
473
+                        $this->userMountCache->clear();
474
+                        $share->setNodeId($share->getNode()->getId());
475
+                        $this->shareManager->updateShare($share);
476
+                        // The share is already transferred.
477
+                        $progress->advance();
478
+                        if ($move) {
479
+                            continue;
480
+                        }
481
+                        $share->setTarget($shareTarget);
482
+                        $this->shareManager->moveShare($share, $destinationUid);
483
+                        continue;
484
+                    }
485
+                    $this->shareManager->deleteShare($share);
486
+                } elseif ($share->getShareOwner() === $destinationUid) {
487
+                    $this->shareManager->deleteShare($share);
488
+                } else {
489
+                    $share->setSharedWith($destinationUid);
490
+                    $share->setNodeId($share->getNode()->getId());
491
+                    $this->shareManager->updateShare($share);
492
+                    // trigger refetching of the node so that the new owner and mountpoint are taken into account
493
+                    // otherwise the checks on the share update will fail due to the original node not being available in the new user scope
494
+                    $this->userMountCache->clear();
495
+                    // The share is already transferred.
496
+                    $progress->advance();
497
+                    if ($move) {
498
+                        continue;
499
+                    }
500
+                    $share->setTarget($shareTarget);
501
+                    $this->shareManager->moveShare($share, $destinationUid);
502
+                    continue;
503
+                }
504
+            } catch (\OCP\Files\NotFoundException $e) {
505
+                $output->writeln('<error>Share with id ' . $share->getId() . ' points at deleted file, skipping</error>');
506
+            } catch (\Throwable $e) {
507
+                $output->writeln('<error>Could not restore share with id ' . $share->getId() . ':' . $e->getTraceAsString() . '</error>');
508
+            }
509
+            $progress->advance();
510
+        }
511
+        $progress->finish();
512
+        $output->writeln('');
513
+    }
514 514
 }
Please login to merge, or discard this patch.
apps/files/lib/Controller/ApiController.php 1 patch
Indentation   +327 added lines, -327 removed lines patch added patch discarded remove patch
@@ -62,359 +62,359 @@
 block discarded – undo
62 62
  * @package OCA\Files\Controller
63 63
  */
64 64
 class ApiController extends Controller {
65
-	private TagService $tagService;
66
-	private IManager $shareManager;
67
-	private IPreview $previewManager;
68
-	private IUserSession $userSession;
69
-	private IConfig $config;
70
-	private Folder $userFolder;
71
-	private UserConfig $userConfig;
65
+    private TagService $tagService;
66
+    private IManager $shareManager;
67
+    private IPreview $previewManager;
68
+    private IUserSession $userSession;
69
+    private IConfig $config;
70
+    private Folder $userFolder;
71
+    private UserConfig $userConfig;
72 72
 
73
-	/**
74
-	 * @param string $appName
75
-	 * @param IRequest $request
76
-	 * @param IUserSession $userSession
77
-	 * @param TagService $tagService
78
-	 * @param IPreview $previewManager
79
-	 * @param IManager $shareManager
80
-	 * @param IConfig $config
81
-	 * @param Folder $userFolder
82
-	 */
83
-	public function __construct($appName,
84
-								IRequest $request,
85
-								IUserSession $userSession,
86
-								TagService $tagService,
87
-								IPreview $previewManager,
88
-								IManager $shareManager,
89
-								IConfig $config,
90
-								Folder $userFolder,
91
-								UserConfig $userConfig) {
92
-		parent::__construct($appName, $request);
93
-		$this->userSession = $userSession;
94
-		$this->tagService = $tagService;
95
-		$this->previewManager = $previewManager;
96
-		$this->shareManager = $shareManager;
97
-		$this->config = $config;
98
-		$this->userFolder = $userFolder;
99
-		$this->userConfig = $userConfig;
100
-	}
73
+    /**
74
+     * @param string $appName
75
+     * @param IRequest $request
76
+     * @param IUserSession $userSession
77
+     * @param TagService $tagService
78
+     * @param IPreview $previewManager
79
+     * @param IManager $shareManager
80
+     * @param IConfig $config
81
+     * @param Folder $userFolder
82
+     */
83
+    public function __construct($appName,
84
+                                IRequest $request,
85
+                                IUserSession $userSession,
86
+                                TagService $tagService,
87
+                                IPreview $previewManager,
88
+                                IManager $shareManager,
89
+                                IConfig $config,
90
+                                Folder $userFolder,
91
+                                UserConfig $userConfig) {
92
+        parent::__construct($appName, $request);
93
+        $this->userSession = $userSession;
94
+        $this->tagService = $tagService;
95
+        $this->previewManager = $previewManager;
96
+        $this->shareManager = $shareManager;
97
+        $this->config = $config;
98
+        $this->userFolder = $userFolder;
99
+        $this->userConfig = $userConfig;
100
+    }
101 101
 
102
-	/**
103
-	 * Gets a thumbnail of the specified file
104
-	 *
105
-	 * @since API version 1.0
106
-	 *
107
-	 * @NoAdminRequired
108
-	 * @NoCSRFRequired
109
-	 * @StrictCookieRequired
110
-	 *
111
-	 * @param int $x
112
-	 * @param int $y
113
-	 * @param string $file URL-encoded filename
114
-	 * @return DataResponse|FileDisplayResponse
115
-	 */
116
-	public function getThumbnail($x, $y, $file) {
117
-		if ($x < 1 || $y < 1) {
118
-			return new DataResponse(['message' => 'Requested size must be numeric and a positive value.'], Http::STATUS_BAD_REQUEST);
119
-		}
102
+    /**
103
+     * Gets a thumbnail of the specified file
104
+     *
105
+     * @since API version 1.0
106
+     *
107
+     * @NoAdminRequired
108
+     * @NoCSRFRequired
109
+     * @StrictCookieRequired
110
+     *
111
+     * @param int $x
112
+     * @param int $y
113
+     * @param string $file URL-encoded filename
114
+     * @return DataResponse|FileDisplayResponse
115
+     */
116
+    public function getThumbnail($x, $y, $file) {
117
+        if ($x < 1 || $y < 1) {
118
+            return new DataResponse(['message' => 'Requested size must be numeric and a positive value.'], Http::STATUS_BAD_REQUEST);
119
+        }
120 120
 
121
-		try {
122
-			$file = $this->userFolder->get($file);
123
-			if ($file instanceof Folder) {
124
-				throw new NotFoundException();
125
-			}
121
+        try {
122
+            $file = $this->userFolder->get($file);
123
+            if ($file instanceof Folder) {
124
+                throw new NotFoundException();
125
+            }
126 126
 
127
-			/** @var File $file */
128
-			$preview = $this->previewManager->getPreview($file, $x, $y, true);
127
+            /** @var File $file */
128
+            $preview = $this->previewManager->getPreview($file, $x, $y, true);
129 129
 
130
-			return new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => $preview->getMimeType()]);
131
-		} catch (NotFoundException $e) {
132
-			return new DataResponse(['message' => 'File not found.'], Http::STATUS_NOT_FOUND);
133
-		} catch (\Exception $e) {
134
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
135
-		}
136
-	}
130
+            return new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => $preview->getMimeType()]);
131
+        } catch (NotFoundException $e) {
132
+            return new DataResponse(['message' => 'File not found.'], Http::STATUS_NOT_FOUND);
133
+        } catch (\Exception $e) {
134
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
135
+        }
136
+    }
137 137
 
138
-	/**
139
-	 * Updates the info of the specified file path
140
-	 * The passed tags are absolute, which means they will
141
-	 * replace the actual tag selection.
142
-	 *
143
-	 * @NoAdminRequired
144
-	 *
145
-	 * @param string $path path
146
-	 * @param array|string $tags array of tags
147
-	 * @return DataResponse
148
-	 */
149
-	public function updateFileTags($path, $tags = null) {
150
-		$result = [];
151
-		// if tags specified or empty array, update tags
152
-		if (!is_null($tags)) {
153
-			try {
154
-				$this->tagService->updateFileTags($path, $tags);
155
-			} catch (\OCP\Files\NotFoundException $e) {
156
-				return new DataResponse([
157
-					'message' => $e->getMessage()
158
-				], Http::STATUS_NOT_FOUND);
159
-			} catch (\OCP\Files\StorageNotAvailableException $e) {
160
-				return new DataResponse([
161
-					'message' => $e->getMessage()
162
-				], Http::STATUS_SERVICE_UNAVAILABLE);
163
-			} catch (\Exception $e) {
164
-				return new DataResponse([
165
-					'message' => $e->getMessage()
166
-				], Http::STATUS_NOT_FOUND);
167
-			}
168
-			$result['tags'] = $tags;
169
-		}
170
-		return new DataResponse($result);
171
-	}
138
+    /**
139
+     * Updates the info of the specified file path
140
+     * The passed tags are absolute, which means they will
141
+     * replace the actual tag selection.
142
+     *
143
+     * @NoAdminRequired
144
+     *
145
+     * @param string $path path
146
+     * @param array|string $tags array of tags
147
+     * @return DataResponse
148
+     */
149
+    public function updateFileTags($path, $tags = null) {
150
+        $result = [];
151
+        // if tags specified or empty array, update tags
152
+        if (!is_null($tags)) {
153
+            try {
154
+                $this->tagService->updateFileTags($path, $tags);
155
+            } catch (\OCP\Files\NotFoundException $e) {
156
+                return new DataResponse([
157
+                    'message' => $e->getMessage()
158
+                ], Http::STATUS_NOT_FOUND);
159
+            } catch (\OCP\Files\StorageNotAvailableException $e) {
160
+                return new DataResponse([
161
+                    'message' => $e->getMessage()
162
+                ], Http::STATUS_SERVICE_UNAVAILABLE);
163
+            } catch (\Exception $e) {
164
+                return new DataResponse([
165
+                    'message' => $e->getMessage()
166
+                ], Http::STATUS_NOT_FOUND);
167
+            }
168
+            $result['tags'] = $tags;
169
+        }
170
+        return new DataResponse($result);
171
+    }
172 172
 
173
-	/**
174
-	 * @param \OCP\Files\Node[] $nodes
175
-	 * @return array
176
-	 */
177
-	private function formatNodes(array $nodes) {
178
-		$shareTypesForNodes = $this->getShareTypesForNodes($nodes);
179
-		return array_values(array_map(function (Node $node) use ($shareTypesForNodes) {
180
-			$shareTypes = $shareTypesForNodes[$node->getId()] ?? [];
181
-			$file = \OCA\Files\Helper::formatFileInfo($node->getFileInfo());
182
-			$file['hasPreview'] = $this->previewManager->isAvailable($node);
183
-			$parts = explode('/', dirname($node->getPath()), 4);
184
-			if (isset($parts[3])) {
185
-				$file['path'] = '/' . $parts[3];
186
-			} else {
187
-				$file['path'] = '/';
188
-			}
189
-			if (!empty($shareTypes)) {
190
-				$file['shareTypes'] = $shareTypes;
191
-			}
192
-			return $file;
193
-		}, $nodes));
194
-	}
173
+    /**
174
+     * @param \OCP\Files\Node[] $nodes
175
+     * @return array
176
+     */
177
+    private function formatNodes(array $nodes) {
178
+        $shareTypesForNodes = $this->getShareTypesForNodes($nodes);
179
+        return array_values(array_map(function (Node $node) use ($shareTypesForNodes) {
180
+            $shareTypes = $shareTypesForNodes[$node->getId()] ?? [];
181
+            $file = \OCA\Files\Helper::formatFileInfo($node->getFileInfo());
182
+            $file['hasPreview'] = $this->previewManager->isAvailable($node);
183
+            $parts = explode('/', dirname($node->getPath()), 4);
184
+            if (isset($parts[3])) {
185
+                $file['path'] = '/' . $parts[3];
186
+            } else {
187
+                $file['path'] = '/';
188
+            }
189
+            if (!empty($shareTypes)) {
190
+                $file['shareTypes'] = $shareTypes;
191
+            }
192
+            return $file;
193
+        }, $nodes));
194
+    }
195 195
 
196
-	/**
197
-	 * Get the share types for each node
198
-	 *
199
-	 * @param \OCP\Files\Node[] $nodes
200
-	 * @return array<int, int[]> list of share types for each fileid
201
-	 */
202
-	private function getShareTypesForNodes(array $nodes): array {
203
-		$userId = $this->userSession->getUser()->getUID();
204
-		$requestedShareTypes = [
205
-			IShare::TYPE_USER,
206
-			IShare::TYPE_GROUP,
207
-			IShare::TYPE_LINK,
208
-			IShare::TYPE_REMOTE,
209
-			IShare::TYPE_EMAIL,
210
-			IShare::TYPE_ROOM,
211
-			IShare::TYPE_DECK,
212
-			IShare::TYPE_SCIENCEMESH,
213
-		];
214
-		$shareTypes = [];
196
+    /**
197
+     * Get the share types for each node
198
+     *
199
+     * @param \OCP\Files\Node[] $nodes
200
+     * @return array<int, int[]> list of share types for each fileid
201
+     */
202
+    private function getShareTypesForNodes(array $nodes): array {
203
+        $userId = $this->userSession->getUser()->getUID();
204
+        $requestedShareTypes = [
205
+            IShare::TYPE_USER,
206
+            IShare::TYPE_GROUP,
207
+            IShare::TYPE_LINK,
208
+            IShare::TYPE_REMOTE,
209
+            IShare::TYPE_EMAIL,
210
+            IShare::TYPE_ROOM,
211
+            IShare::TYPE_DECK,
212
+            IShare::TYPE_SCIENCEMESH,
213
+        ];
214
+        $shareTypes = [];
215 215
 
216
-		$nodeIds = array_map(function (Node $node) {
217
-			return $node->getId();
218
-		}, $nodes);
216
+        $nodeIds = array_map(function (Node $node) {
217
+            return $node->getId();
218
+        }, $nodes);
219 219
 
220
-		foreach ($requestedShareTypes as $shareType) {
221
-			$nodesLeft = array_combine($nodeIds, array_fill(0, count($nodeIds), true));
222
-			$offset = 0;
220
+        foreach ($requestedShareTypes as $shareType) {
221
+            $nodesLeft = array_combine($nodeIds, array_fill(0, count($nodeIds), true));
222
+            $offset = 0;
223 223
 
224
-			// fetch shares until we've either found shares for all nodes or there are no more shares left
225
-			while (count($nodesLeft) > 0) {
226
-				$shares = $this->shareManager->getSharesBy($userId, $shareType, null, false, 100, $offset);
227
-				foreach ($shares as $share) {
228
-					$fileId = $share->getNodeId();
229
-					if (isset($nodesLeft[$fileId])) {
230
-						if (!isset($shareTypes[$fileId])) {
231
-							$shareTypes[$fileId] = [];
232
-						}
233
-						$shareTypes[$fileId][] = $shareType;
234
-						unset($nodesLeft[$fileId]);
235
-					}
236
-				}
224
+            // fetch shares until we've either found shares for all nodes or there are no more shares left
225
+            while (count($nodesLeft) > 0) {
226
+                $shares = $this->shareManager->getSharesBy($userId, $shareType, null, false, 100, $offset);
227
+                foreach ($shares as $share) {
228
+                    $fileId = $share->getNodeId();
229
+                    if (isset($nodesLeft[$fileId])) {
230
+                        if (!isset($shareTypes[$fileId])) {
231
+                            $shareTypes[$fileId] = [];
232
+                        }
233
+                        $shareTypes[$fileId][] = $shareType;
234
+                        unset($nodesLeft[$fileId]);
235
+                    }
236
+                }
237 237
 
238
-				if (count($shares) < 100) {
239
-					break;
240
-				} else {
241
-					$offset += count($shares);
242
-				}
243
-			}
244
-		}
245
-		return $shareTypes;
246
-	}
238
+                if (count($shares) < 100) {
239
+                    break;
240
+                } else {
241
+                    $offset += count($shares);
242
+                }
243
+            }
244
+        }
245
+        return $shareTypes;
246
+    }
247 247
 
248
-	/**
249
-	 * Returns a list of recently modified files.
250
-	 *
251
-	 * @NoAdminRequired
252
-	 *
253
-	 * @return DataResponse
254
-	 */
255
-	public function getRecentFiles() {
256
-		$nodes = $this->userFolder->getRecent(100);
257
-		$files = $this->formatNodes($nodes);
258
-		return new DataResponse(['files' => $files]);
259
-	}
248
+    /**
249
+     * Returns a list of recently modified files.
250
+     *
251
+     * @NoAdminRequired
252
+     *
253
+     * @return DataResponse
254
+     */
255
+    public function getRecentFiles() {
256
+        $nodes = $this->userFolder->getRecent(100);
257
+        $files = $this->formatNodes($nodes);
258
+        return new DataResponse(['files' => $files]);
259
+    }
260 260
 
261 261
 
262
-	/**
263
-	 * Returns the current logged-in user's storage stats.
264
-	 *
265
-	 * @NoAdminRequired
266
-	 *
267
-	 * @param ?string $dir the directory to get the storage stats from
268
-	 * @return JSONResponse
269
-	 */
270
-	public function getStorageStats($dir = '/'): JSONResponse {
271
-		$storageInfo = \OC_Helper::getStorageInfo($dir ?: '/');
272
-		return new JSONResponse(['message' => 'ok', 'data' => $storageInfo]);
273
-	}
262
+    /**
263
+     * Returns the current logged-in user's storage stats.
264
+     *
265
+     * @NoAdminRequired
266
+     *
267
+     * @param ?string $dir the directory to get the storage stats from
268
+     * @return JSONResponse
269
+     */
270
+    public function getStorageStats($dir = '/'): JSONResponse {
271
+        $storageInfo = \OC_Helper::getStorageInfo($dir ?: '/');
272
+        return new JSONResponse(['message' => 'ok', 'data' => $storageInfo]);
273
+    }
274 274
 
275
-	/**
276
-	 * Change the default sort mode
277
-	 *
278
-	 * @NoAdminRequired
279
-	 *
280
-	 * @param string $mode
281
-	 * @param string $direction
282
-	 * @return Response
283
-	 * @throws \OCP\PreConditionNotMetException
284
-	 */
285
-	public function updateFileSorting($mode, $direction) {
286
-		$allowedMode = ['name', 'size', 'mtime'];
287
-		$allowedDirection = ['asc', 'desc'];
288
-		if (!in_array($mode, $allowedMode) || !in_array($direction, $allowedDirection)) {
289
-			$response = new Response();
290
-			$response->setStatus(Http::STATUS_UNPROCESSABLE_ENTITY);
291
-			return $response;
292
-		}
293
-		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'file_sorting', $mode);
294
-		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'file_sorting_direction', $direction);
295
-		return new Response();
296
-	}
275
+    /**
276
+     * Change the default sort mode
277
+     *
278
+     * @NoAdminRequired
279
+     *
280
+     * @param string $mode
281
+     * @param string $direction
282
+     * @return Response
283
+     * @throws \OCP\PreConditionNotMetException
284
+     */
285
+    public function updateFileSorting($mode, $direction) {
286
+        $allowedMode = ['name', 'size', 'mtime'];
287
+        $allowedDirection = ['asc', 'desc'];
288
+        if (!in_array($mode, $allowedMode) || !in_array($direction, $allowedDirection)) {
289
+            $response = new Response();
290
+            $response->setStatus(Http::STATUS_UNPROCESSABLE_ENTITY);
291
+            return $response;
292
+        }
293
+        $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'file_sorting', $mode);
294
+        $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'file_sorting_direction', $direction);
295
+        return new Response();
296
+    }
297 297
 
298
-	/**
299
-	 * Toggle default files user config
300
-	 *
301
-	 * @NoAdminRequired
302
-	 *
303
-	 * @param string $key
304
-	 * @param string|bool $value
305
-	 * @return JSONResponse
306
-	 */
307
-	public function setConfig(string $key, $value): JSONResponse {
308
-		try {
309
-			$this->userConfig->setConfig($key, (string)$value);
310
-		} catch (\InvalidArgumentException $e) {
311
-			return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
312
-		}
298
+    /**
299
+     * Toggle default files user config
300
+     *
301
+     * @NoAdminRequired
302
+     *
303
+     * @param string $key
304
+     * @param string|bool $value
305
+     * @return JSONResponse
306
+     */
307
+    public function setConfig(string $key, $value): JSONResponse {
308
+        try {
309
+            $this->userConfig->setConfig($key, (string)$value);
310
+        } catch (\InvalidArgumentException $e) {
311
+            return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
312
+        }
313 313
 
314
-		return new JSONResponse(['message' => 'ok', 'data' => ['key' => $key, 'value' => $value]]);
315
-	}
314
+        return new JSONResponse(['message' => 'ok', 'data' => ['key' => $key, 'value' => $value]]);
315
+    }
316 316
 
317 317
 
318
-	/**
319
-	 * Get the user config
320
-	 *
321
-	 * @NoAdminRequired
322
-	 *
323
-	 * @return JSONResponse
324
-	 */
325
-	public function getConfigs(): JSONResponse {
326
-		return new JSONResponse(['message' => 'ok', 'data' => $this->userConfig->getConfigs()]);
327
-	}
318
+    /**
319
+     * Get the user config
320
+     *
321
+     * @NoAdminRequired
322
+     *
323
+     * @return JSONResponse
324
+     */
325
+    public function getConfigs(): JSONResponse {
326
+        return new JSONResponse(['message' => 'ok', 'data' => $this->userConfig->getConfigs()]);
327
+    }
328 328
 
329
-	/**
330
-	 * Toggle default for showing/hiding hidden files
331
-	 *
332
-	 * @NoAdminRequired
333
-	 *
334
-	 * @param bool $value
335
-	 * @return Response
336
-	 * @throws \OCP\PreConditionNotMetException
337
-	 */
338
-	public function showHiddenFiles(bool $value): Response {
339
-		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', $value ? '1' : '0');
340
-		return new Response();
341
-	}
329
+    /**
330
+     * Toggle default for showing/hiding hidden files
331
+     *
332
+     * @NoAdminRequired
333
+     *
334
+     * @param bool $value
335
+     * @return Response
336
+     * @throws \OCP\PreConditionNotMetException
337
+     */
338
+    public function showHiddenFiles(bool $value): Response {
339
+        $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', $value ? '1' : '0');
340
+        return new Response();
341
+    }
342 342
 
343
-	/**
344
-	 * Toggle default for cropping preview images
345
-	 *
346
-	 * @NoAdminRequired
347
-	 *
348
-	 * @param bool $value
349
-	 * @return Response
350
-	 * @throws \OCP\PreConditionNotMetException
351
-	 */
352
-	public function cropImagePreviews(bool $value): Response {
353
-		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'crop_image_previews', $value ? '1' : '0');
354
-		return new Response();
355
-	}
343
+    /**
344
+     * Toggle default for cropping preview images
345
+     *
346
+     * @NoAdminRequired
347
+     *
348
+     * @param bool $value
349
+     * @return Response
350
+     * @throws \OCP\PreConditionNotMetException
351
+     */
352
+    public function cropImagePreviews(bool $value): Response {
353
+        $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'crop_image_previews', $value ? '1' : '0');
354
+        return new Response();
355
+    }
356 356
 
357
-	/**
358
-	 * Toggle default for files grid view
359
-	 *
360
-	 * @NoAdminRequired
361
-	 *
362
-	 * @param bool $show
363
-	 * @return Response
364
-	 * @throws \OCP\PreConditionNotMetException
365
-	 */
366
-	public function showGridView(bool $show): Response {
367
-		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', $show ? '1' : '0');
368
-		return new Response();
369
-	}
357
+    /**
358
+     * Toggle default for files grid view
359
+     *
360
+     * @NoAdminRequired
361
+     *
362
+     * @param bool $show
363
+     * @return Response
364
+     * @throws \OCP\PreConditionNotMetException
365
+     */
366
+    public function showGridView(bool $show): Response {
367
+        $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', $show ? '1' : '0');
368
+        return new Response();
369
+    }
370 370
 
371
-	/**
372
-	 * Get default settings for the grid view
373
-	 *
374
-	 * @NoAdminRequired
375
-	 */
376
-	public function getGridView() {
377
-		$status = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', '0') === '1';
378
-		return new JSONResponse(['gridview' => $status]);
379
-	}
371
+    /**
372
+     * Get default settings for the grid view
373
+     *
374
+     * @NoAdminRequired
375
+     */
376
+    public function getGridView() {
377
+        $status = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', '0') === '1';
378
+        return new JSONResponse(['gridview' => $status]);
379
+    }
380 380
 
381
-	/**
382
-	 * Toggle default for showing/hiding xxx folder
383
-	 *
384
-	 * @NoAdminRequired
385
-	 *
386
-	 * @param int $show
387
-	 * @param string $key the key of the folder
388
-	 *
389
-	 * @return Response
390
-	 * @throws \OCP\PreConditionNotMetException
391
-	 */
392
-	public function toggleShowFolder(int $show, string $key): Response {
393
-		if ($show !== 0 && $show !== 1) {
394
-			return new DataResponse([
395
-				'message' => 'Invalid show value. Only 0 and 1 are allowed.'
396
-			], Http::STATUS_BAD_REQUEST);
397
-		}
381
+    /**
382
+     * Toggle default for showing/hiding xxx folder
383
+     *
384
+     * @NoAdminRequired
385
+     *
386
+     * @param int $show
387
+     * @param string $key the key of the folder
388
+     *
389
+     * @return Response
390
+     * @throws \OCP\PreConditionNotMetException
391
+     */
392
+    public function toggleShowFolder(int $show, string $key): Response {
393
+        if ($show !== 0 && $show !== 1) {
394
+            return new DataResponse([
395
+                'message' => 'Invalid show value. Only 0 and 1 are allowed.'
396
+            ], Http::STATUS_BAD_REQUEST);
397
+        }
398 398
 
399
-		$userId = $this->userSession->getUser()->getUID();
399
+        $userId = $this->userSession->getUser()->getUID();
400 400
 
401
-		// Set the new value and return it
402
-		// Using a prefix prevents the user from setting arbitrary keys
403
-		$this->config->setUserValue($userId, 'files', 'show_' . $key, (string)$show);
404
-		return new JSONResponse([$key => $show]);
405
-	}
401
+        // Set the new value and return it
402
+        // Using a prefix prevents the user from setting arbitrary keys
403
+        $this->config->setUserValue($userId, 'files', 'show_' . $key, (string)$show);
404
+        return new JSONResponse([$key => $show]);
405
+    }
406 406
 
407
-	/**
408
-	 * Get sorting-order for custom sorting
409
-	 *
410
-	 * @NoAdminRequired
411
-	 *
412
-	 * @param string $folderpath
413
-	 * @return string
414
-	 * @throws \OCP\Files\NotFoundException
415
-	 */
416
-	public function getNodeType($folderpath) {
417
-		$node = $this->userFolder->get($folderpath);
418
-		return $node->getType();
419
-	}
407
+    /**
408
+     * Get sorting-order for custom sorting
409
+     *
410
+     * @NoAdminRequired
411
+     *
412
+     * @param string $folderpath
413
+     * @return string
414
+     * @throws \OCP\Files\NotFoundException
415
+     */
416
+    public function getNodeType($folderpath) {
417
+        $node = $this->userFolder->get($folderpath);
418
+        return $node->getType();
419
+    }
420 420
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/MountProvider.php 1 patch
Indentation   +254 added lines, -254 removed lines patch added patch discarded remove patch
@@ -43,258 +43,258 @@
 block discarded – undo
43 43
 use OCP\Share\IShare;
44 44
 
45 45
 class MountProvider implements IMountProvider {
46
-	/**
47
-	 * @var \OCP\IConfig
48
-	 */
49
-	protected $config;
50
-
51
-	/**
52
-	 * @var IManager
53
-	 */
54
-	protected $shareManager;
55
-
56
-	/**
57
-	 * @var ILogger
58
-	 */
59
-	protected $logger;
60
-
61
-	/** @var IEventDispatcher */
62
-	protected $eventDispatcher;
63
-
64
-	/** @var ICacheFactory */
65
-	protected $cacheFactory;
66
-
67
-	/**
68
-	 * @param \OCP\IConfig $config
69
-	 * @param IManager $shareManager
70
-	 * @param ILogger $logger
71
-	 */
72
-	public function __construct(
73
-		IConfig $config,
74
-		IManager $shareManager,
75
-		ILogger $logger,
76
-		IEventDispatcher $eventDispatcher,
77
-		ICacheFactory $cacheFactory
78
-	) {
79
-		$this->config = $config;
80
-		$this->shareManager = $shareManager;
81
-		$this->logger = $logger;
82
-		$this->eventDispatcher = $eventDispatcher;
83
-		$this->cacheFactory = $cacheFactory;
84
-	}
85
-
86
-
87
-	/**
88
-	 * Get all mountpoints applicable for the user and check for shares where we need to update the etags
89
-	 *
90
-	 * @param \OCP\IUser $user
91
-	 * @param \OCP\Files\Storage\IStorageFactory $loader
92
-	 * @return \OCP\Files\Mount\IMountPoint[]
93
-	 */
94
-	public function getMountsForUser(IUser $user, IStorageFactory $loader) {
95
-		$shares = $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_USER, null, -1);
96
-		$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_GROUP, null, -1));
97
-		$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_CIRCLE, null, -1));
98
-		$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_ROOM, null, -1));
99
-		$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_DECK, null, -1));
100
-		$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_SCIENCEMESH, null, -1));
101
-
102
-
103
-		// filter out excluded shares and group shares that includes self
104
-		$shares = array_filter($shares, function (\OCP\Share\IShare $share) use ($user) {
105
-			return $share->getPermissions() > 0 && $share->getShareOwner() !== $user->getUID();
106
-		});
107
-
108
-		$superShares = $this->buildSuperShares($shares, $user);
109
-
110
-		$mounts = [];
111
-		$view = new View('/' . $user->getUID() . '/files');
112
-		$ownerViews = [];
113
-		$sharingDisabledForUser = $this->shareManager->sharingDisabledForUser($user->getUID());
114
-		/** @var CappedMemoryCache<bool> $folderExistCache */
115
-		$foldersExistCache = new CappedMemoryCache();
116
-		foreach ($superShares as $share) {
117
-			try {
118
-				/** @var \OCP\Share\IShare $parentShare */
119
-				$parentShare = $share[0];
120
-
121
-				if ($parentShare->getStatus() !== IShare::STATUS_ACCEPTED &&
122
-					($parentShare->getShareType() === IShare::TYPE_GROUP ||
123
-						$parentShare->getShareType() === IShare::TYPE_USERGROUP ||
124
-						$parentShare->getShareType() === IShare::TYPE_USER)) {
125
-					continue;
126
-				}
127
-
128
-				$owner = $parentShare->getShareOwner();
129
-				if (!isset($ownerViews[$owner])) {
130
-					$ownerViews[$owner] = new View('/' . $parentShare->getShareOwner() . '/files');
131
-				}
132
-				$mount = new SharedMount(
133
-					'\OCA\Files_Sharing\SharedStorage',
134
-					$mounts,
135
-					[
136
-						'user' => $user->getUID(),
137
-						// parent share
138
-						'superShare' => $parentShare,
139
-						// children/component of the superShare
140
-						'groupedShares' => $share[1],
141
-						'ownerView' => $ownerViews[$owner],
142
-						'sharingDisabledForUser' => $sharingDisabledForUser
143
-					],
144
-					$loader,
145
-					$view,
146
-					$foldersExistCache,
147
-					$this->eventDispatcher,
148
-					$user,
149
-					$this->cacheFactory->createLocal('share-valid-mountpoint')
150
-				);
151
-
152
-				$event = new ShareMountedEvent($mount);
153
-				$this->eventDispatcher->dispatchTyped($event);
154
-
155
-				$mounts[$mount->getMountPoint()] = $mount;
156
-				foreach ($event->getAdditionalMounts() as $additionalMount) {
157
-					$mounts[$additionalMount->getMountPoint()] = $additionalMount;
158
-				}
159
-			} catch (\Exception $e) {
160
-				$this->logger->logException($e);
161
-				$this->logger->error('Error while trying to create shared mount');
162
-			}
163
-		}
164
-
165
-		// array_filter removes the null values from the array
166
-		return array_values(array_filter($mounts));
167
-	}
168
-
169
-	/**
170
-	 * Groups shares by path (nodeId) and target path
171
-	 *
172
-	 * @param \OCP\Share\IShare[] $shares
173
-	 * @return \OCP\Share\IShare[][] array of grouped shares, each element in the
174
-	 * array is a group which itself is an array of shares
175
-	 */
176
-	private function groupShares(array $shares) {
177
-		$tmp = [];
178
-
179
-		foreach ($shares as $share) {
180
-			if (!isset($tmp[$share->getNodeId()])) {
181
-				$tmp[$share->getNodeId()] = [];
182
-			}
183
-			$tmp[$share->getNodeId()][] = $share;
184
-		}
185
-
186
-		$result = [];
187
-		// sort by stime, the super share will be based on the least recent share
188
-		foreach ($tmp as &$tmp2) {
189
-			@usort($tmp2, function ($a, $b) {
190
-				$aTime = $a->getShareTime()->getTimestamp();
191
-				$bTime = $b->getShareTime()->getTimestamp();
192
-				if ($aTime === $bTime) {
193
-					return $a->getId() < $b->getId() ? -1 : 1;
194
-				}
195
-				return $aTime < $bTime ? -1 : 1;
196
-			});
197
-			$result[] = $tmp2;
198
-		}
199
-
200
-		return array_values($result);
201
-	}
202
-
203
-	/**
204
-	 * Build super shares (virtual share) by grouping them by node id and target,
205
-	 * then for each group compute the super share and return it along with the matching
206
-	 * grouped shares. The most permissive permissions are used based on the permissions
207
-	 * of all shares within the group.
208
-	 *
209
-	 * @param \OCP\Share\IShare[] $allShares
210
-	 * @param \OCP\IUser $user user
211
-	 * @return array Tuple of [superShare, groupedShares]
212
-	 */
213
-	private function buildSuperShares(array $allShares, \OCP\IUser $user) {
214
-		$result = [];
215
-
216
-		$groupedShares = $this->groupShares($allShares);
217
-
218
-		/** @var \OCP\Share\IShare[] $shares */
219
-		foreach ($groupedShares as $shares) {
220
-			if (count($shares) === 0) {
221
-				continue;
222
-			}
223
-
224
-			$superShare = $this->shareManager->newShare();
225
-
226
-			// compute super share based on first entry of the group
227
-			$superShare->setId($shares[0]->getId())
228
-				->setShareOwner($shares[0]->getShareOwner())
229
-				->setNodeId($shares[0]->getNodeId())
230
-				->setShareType($shares[0]->getShareType())
231
-				->setTarget($shares[0]->getTarget());
232
-
233
-			// Gather notes from all the shares.
234
-			// Since these are readly available here, storing them
235
-			// enables the DAV FilesPlugin to avoid executing many
236
-			// DB queries to retrieve the same information.
237
-			$allNotes = implode("\n", array_map(function ($sh) { return $sh->getNote(); }, $shares));
238
-			$superShare->setNote($allNotes);
239
-
240
-			// use most permissive permissions
241
-			// this covers the case where there are multiple shares for the same
242
-			// file e.g. from different groups and different permissions
243
-			$superPermissions = 0;
244
-			$superAttributes = $this->shareManager->newShare()->newAttributes();
245
-			$status = IShare::STATUS_PENDING;
246
-			foreach ($shares as $share) {
247
-				$superPermissions |= $share->getPermissions();
248
-				$status = max($status, $share->getStatus());
249
-				// update permissions
250
-				$superPermissions |= $share->getPermissions();
251
-
252
-				// update share permission attributes
253
-				$attributes = $share->getAttributes();
254
-				if ($attributes !== null) {
255
-					foreach ($attributes->toArray() as $attribute) {
256
-						if ($superAttributes->getAttribute($attribute['scope'], $attribute['key']) === true) {
257
-							// if super share attribute is already enabled, it is most permissive
258
-							continue;
259
-						}
260
-						// update supershare attributes with subshare attribute
261
-						$superAttributes->setAttribute($attribute['scope'], $attribute['key'], $attribute['enabled']);
262
-					}
263
-				}
264
-
265
-				// adjust target, for database consistency if needed
266
-				if ($share->getTarget() !== $superShare->getTarget()) {
267
-					$share->setTarget($superShare->getTarget());
268
-					try {
269
-						$this->shareManager->moveShare($share, $user->getUID());
270
-					} catch (\InvalidArgumentException $e) {
271
-						// ignore as it is not important and we don't want to
272
-						// block FS setup
273
-
274
-						// the subsequent code anyway only uses the target of the
275
-						// super share
276
-
277
-						// such issue can usually happen when dealing with
278
-						// null groups which usually appear with group backend
279
-						// caching inconsistencies
280
-						$this->logger->debug(
281
-							'Could not adjust share target for share ' . $share->getId() . ' to make it consistent: ' . $e->getMessage(),
282
-							['app' => 'files_sharing']
283
-						);
284
-					}
285
-				}
286
-				if (!is_null($share->getNodeCacheEntry())) {
287
-					$superShare->setNodeCacheEntry($share->getNodeCacheEntry());
288
-				}
289
-			}
290
-
291
-			$superShare->setPermissions($superPermissions);
292
-			$superShare->setStatus($status);
293
-			$superShare->setAttributes($superAttributes);
294
-
295
-			$result[] = [$superShare, $shares];
296
-		}
297
-
298
-		return $result;
299
-	}
46
+    /**
47
+     * @var \OCP\IConfig
48
+     */
49
+    protected $config;
50
+
51
+    /**
52
+     * @var IManager
53
+     */
54
+    protected $shareManager;
55
+
56
+    /**
57
+     * @var ILogger
58
+     */
59
+    protected $logger;
60
+
61
+    /** @var IEventDispatcher */
62
+    protected $eventDispatcher;
63
+
64
+    /** @var ICacheFactory */
65
+    protected $cacheFactory;
66
+
67
+    /**
68
+     * @param \OCP\IConfig $config
69
+     * @param IManager $shareManager
70
+     * @param ILogger $logger
71
+     */
72
+    public function __construct(
73
+        IConfig $config,
74
+        IManager $shareManager,
75
+        ILogger $logger,
76
+        IEventDispatcher $eventDispatcher,
77
+        ICacheFactory $cacheFactory
78
+    ) {
79
+        $this->config = $config;
80
+        $this->shareManager = $shareManager;
81
+        $this->logger = $logger;
82
+        $this->eventDispatcher = $eventDispatcher;
83
+        $this->cacheFactory = $cacheFactory;
84
+    }
85
+
86
+
87
+    /**
88
+     * Get all mountpoints applicable for the user and check for shares where we need to update the etags
89
+     *
90
+     * @param \OCP\IUser $user
91
+     * @param \OCP\Files\Storage\IStorageFactory $loader
92
+     * @return \OCP\Files\Mount\IMountPoint[]
93
+     */
94
+    public function getMountsForUser(IUser $user, IStorageFactory $loader) {
95
+        $shares = $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_USER, null, -1);
96
+        $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_GROUP, null, -1));
97
+        $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_CIRCLE, null, -1));
98
+        $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_ROOM, null, -1));
99
+        $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_DECK, null, -1));
100
+        $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), IShare::TYPE_SCIENCEMESH, null, -1));
101
+
102
+
103
+        // filter out excluded shares and group shares that includes self
104
+        $shares = array_filter($shares, function (\OCP\Share\IShare $share) use ($user) {
105
+            return $share->getPermissions() > 0 && $share->getShareOwner() !== $user->getUID();
106
+        });
107
+
108
+        $superShares = $this->buildSuperShares($shares, $user);
109
+
110
+        $mounts = [];
111
+        $view = new View('/' . $user->getUID() . '/files');
112
+        $ownerViews = [];
113
+        $sharingDisabledForUser = $this->shareManager->sharingDisabledForUser($user->getUID());
114
+        /** @var CappedMemoryCache<bool> $folderExistCache */
115
+        $foldersExistCache = new CappedMemoryCache();
116
+        foreach ($superShares as $share) {
117
+            try {
118
+                /** @var \OCP\Share\IShare $parentShare */
119
+                $parentShare = $share[0];
120
+
121
+                if ($parentShare->getStatus() !== IShare::STATUS_ACCEPTED &&
122
+                    ($parentShare->getShareType() === IShare::TYPE_GROUP ||
123
+                        $parentShare->getShareType() === IShare::TYPE_USERGROUP ||
124
+                        $parentShare->getShareType() === IShare::TYPE_USER)) {
125
+                    continue;
126
+                }
127
+
128
+                $owner = $parentShare->getShareOwner();
129
+                if (!isset($ownerViews[$owner])) {
130
+                    $ownerViews[$owner] = new View('/' . $parentShare->getShareOwner() . '/files');
131
+                }
132
+                $mount = new SharedMount(
133
+                    '\OCA\Files_Sharing\SharedStorage',
134
+                    $mounts,
135
+                    [
136
+                        'user' => $user->getUID(),
137
+                        // parent share
138
+                        'superShare' => $parentShare,
139
+                        // children/component of the superShare
140
+                        'groupedShares' => $share[1],
141
+                        'ownerView' => $ownerViews[$owner],
142
+                        'sharingDisabledForUser' => $sharingDisabledForUser
143
+                    ],
144
+                    $loader,
145
+                    $view,
146
+                    $foldersExistCache,
147
+                    $this->eventDispatcher,
148
+                    $user,
149
+                    $this->cacheFactory->createLocal('share-valid-mountpoint')
150
+                );
151
+
152
+                $event = new ShareMountedEvent($mount);
153
+                $this->eventDispatcher->dispatchTyped($event);
154
+
155
+                $mounts[$mount->getMountPoint()] = $mount;
156
+                foreach ($event->getAdditionalMounts() as $additionalMount) {
157
+                    $mounts[$additionalMount->getMountPoint()] = $additionalMount;
158
+                }
159
+            } catch (\Exception $e) {
160
+                $this->logger->logException($e);
161
+                $this->logger->error('Error while trying to create shared mount');
162
+            }
163
+        }
164
+
165
+        // array_filter removes the null values from the array
166
+        return array_values(array_filter($mounts));
167
+    }
168
+
169
+    /**
170
+     * Groups shares by path (nodeId) and target path
171
+     *
172
+     * @param \OCP\Share\IShare[] $shares
173
+     * @return \OCP\Share\IShare[][] array of grouped shares, each element in the
174
+     * array is a group which itself is an array of shares
175
+     */
176
+    private function groupShares(array $shares) {
177
+        $tmp = [];
178
+
179
+        foreach ($shares as $share) {
180
+            if (!isset($tmp[$share->getNodeId()])) {
181
+                $tmp[$share->getNodeId()] = [];
182
+            }
183
+            $tmp[$share->getNodeId()][] = $share;
184
+        }
185
+
186
+        $result = [];
187
+        // sort by stime, the super share will be based on the least recent share
188
+        foreach ($tmp as &$tmp2) {
189
+            @usort($tmp2, function ($a, $b) {
190
+                $aTime = $a->getShareTime()->getTimestamp();
191
+                $bTime = $b->getShareTime()->getTimestamp();
192
+                if ($aTime === $bTime) {
193
+                    return $a->getId() < $b->getId() ? -1 : 1;
194
+                }
195
+                return $aTime < $bTime ? -1 : 1;
196
+            });
197
+            $result[] = $tmp2;
198
+        }
199
+
200
+        return array_values($result);
201
+    }
202
+
203
+    /**
204
+     * Build super shares (virtual share) by grouping them by node id and target,
205
+     * then for each group compute the super share and return it along with the matching
206
+     * grouped shares. The most permissive permissions are used based on the permissions
207
+     * of all shares within the group.
208
+     *
209
+     * @param \OCP\Share\IShare[] $allShares
210
+     * @param \OCP\IUser $user user
211
+     * @return array Tuple of [superShare, groupedShares]
212
+     */
213
+    private function buildSuperShares(array $allShares, \OCP\IUser $user) {
214
+        $result = [];
215
+
216
+        $groupedShares = $this->groupShares($allShares);
217
+
218
+        /** @var \OCP\Share\IShare[] $shares */
219
+        foreach ($groupedShares as $shares) {
220
+            if (count($shares) === 0) {
221
+                continue;
222
+            }
223
+
224
+            $superShare = $this->shareManager->newShare();
225
+
226
+            // compute super share based on first entry of the group
227
+            $superShare->setId($shares[0]->getId())
228
+                ->setShareOwner($shares[0]->getShareOwner())
229
+                ->setNodeId($shares[0]->getNodeId())
230
+                ->setShareType($shares[0]->getShareType())
231
+                ->setTarget($shares[0]->getTarget());
232
+
233
+            // Gather notes from all the shares.
234
+            // Since these are readly available here, storing them
235
+            // enables the DAV FilesPlugin to avoid executing many
236
+            // DB queries to retrieve the same information.
237
+            $allNotes = implode("\n", array_map(function ($sh) { return $sh->getNote(); }, $shares));
238
+            $superShare->setNote($allNotes);
239
+
240
+            // use most permissive permissions
241
+            // this covers the case where there are multiple shares for the same
242
+            // file e.g. from different groups and different permissions
243
+            $superPermissions = 0;
244
+            $superAttributes = $this->shareManager->newShare()->newAttributes();
245
+            $status = IShare::STATUS_PENDING;
246
+            foreach ($shares as $share) {
247
+                $superPermissions |= $share->getPermissions();
248
+                $status = max($status, $share->getStatus());
249
+                // update permissions
250
+                $superPermissions |= $share->getPermissions();
251
+
252
+                // update share permission attributes
253
+                $attributes = $share->getAttributes();
254
+                if ($attributes !== null) {
255
+                    foreach ($attributes->toArray() as $attribute) {
256
+                        if ($superAttributes->getAttribute($attribute['scope'], $attribute['key']) === true) {
257
+                            // if super share attribute is already enabled, it is most permissive
258
+                            continue;
259
+                        }
260
+                        // update supershare attributes with subshare attribute
261
+                        $superAttributes->setAttribute($attribute['scope'], $attribute['key'], $attribute['enabled']);
262
+                    }
263
+                }
264
+
265
+                // adjust target, for database consistency if needed
266
+                if ($share->getTarget() !== $superShare->getTarget()) {
267
+                    $share->setTarget($superShare->getTarget());
268
+                    try {
269
+                        $this->shareManager->moveShare($share, $user->getUID());
270
+                    } catch (\InvalidArgumentException $e) {
271
+                        // ignore as it is not important and we don't want to
272
+                        // block FS setup
273
+
274
+                        // the subsequent code anyway only uses the target of the
275
+                        // super share
276
+
277
+                        // such issue can usually happen when dealing with
278
+                        // null groups which usually appear with group backend
279
+                        // caching inconsistencies
280
+                        $this->logger->debug(
281
+                            'Could not adjust share target for share ' . $share->getId() . ' to make it consistent: ' . $e->getMessage(),
282
+                            ['app' => 'files_sharing']
283
+                        );
284
+                    }
285
+                }
286
+                if (!is_null($share->getNodeCacheEntry())) {
287
+                    $superShare->setNodeCacheEntry($share->getNodeCacheEntry());
288
+                }
289
+            }
290
+
291
+            $superShare->setPermissions($superPermissions);
292
+            $superShare->setStatus($status);
293
+            $superShare->setAttributes($superAttributes);
294
+
295
+            $result[] = [$superShare, $shares];
296
+        }
297
+
298
+        return $result;
299
+    }
300 300
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Controller/DeletedShareAPIController.php 2 patches
Indentation   +216 added lines, -216 removed lines patch added patch discarded remove patch
@@ -49,220 +49,220 @@
 block discarded – undo
49 49
 
50 50
 class DeletedShareAPIController extends OCSController {
51 51
 
52
-	/** @var ShareManager */
53
-	private $shareManager;
54
-
55
-	/** @var string */
56
-	private $userId;
57
-
58
-	/** @var IUserManager */
59
-	private $userManager;
60
-
61
-	/** @var IGroupManager */
62
-	private $groupManager;
63
-
64
-	/** @var IRootFolder */
65
-	private $rootFolder;
66
-
67
-	/** @var IAppManager */
68
-	private $appManager;
69
-
70
-	/** @var IServerContainer */
71
-	private $serverContainer;
72
-
73
-	public function __construct(string $appName,
74
-								IRequest $request,
75
-								ShareManager $shareManager,
76
-								string $UserId,
77
-								IUserManager $userManager,
78
-								IGroupManager $groupManager,
79
-								IRootFolder $rootFolder,
80
-								IAppManager $appManager,
81
-								IServerContainer $serverContainer) {
82
-		parent::__construct($appName, $request);
83
-
84
-		$this->shareManager = $shareManager;
85
-		$this->userId = $UserId;
86
-		$this->userManager = $userManager;
87
-		$this->groupManager = $groupManager;
88
-		$this->rootFolder = $rootFolder;
89
-		$this->appManager = $appManager;
90
-		$this->serverContainer = $serverContainer;
91
-	}
92
-
93
-	/**
94
-	 * @suppress PhanUndeclaredClassMethod
95
-	 */
96
-	private function formatShare(IShare $share): array {
97
-		$result = [
98
-			'id' => $share->getFullId(),
99
-			'share_type' => $share->getShareType(),
100
-			'uid_owner' => $share->getSharedBy(),
101
-			'displayname_owner' => $this->userManager->get($share->getSharedBy())->getDisplayName(),
102
-			'permissions' => 0,
103
-			'stime' => $share->getShareTime()->getTimestamp(),
104
-			'parent' => null,
105
-			'expiration' => null,
106
-			'token' => null,
107
-			'uid_file_owner' => $share->getShareOwner(),
108
-			'displayname_file_owner' => $this->userManager->get($share->getShareOwner())->getDisplayName(),
109
-			'path' => $share->getTarget(),
110
-		];
111
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
112
-		$nodes = $userFolder->getById($share->getNodeId());
113
-		if (empty($nodes)) {
114
-			// fallback to guessing the path
115
-			$node = $userFolder->get($share->getTarget());
116
-			if ($node === null || $share->getTarget() === '') {
117
-				throw new NotFoundException();
118
-			}
119
-		} else {
120
-			$node = $nodes[0];
121
-		}
122
-
123
-		$result['path'] = $userFolder->getRelativePath($node->getPath());
124
-		if ($node instanceof \OCP\Files\Folder) {
125
-			$result['item_type'] = 'folder';
126
-		} else {
127
-			$result['item_type'] = 'file';
128
-		}
129
-		$result['mimetype'] = $node->getMimetype();
130
-		$result['storage_id'] = $node->getStorage()->getId();
131
-		$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
132
-		$result['item_source'] = $node->getId();
133
-		$result['file_source'] = $node->getId();
134
-		$result['file_parent'] = $node->getParent()->getId();
135
-		$result['file_target'] = $share->getTarget();
136
-
137
-		$expiration = $share->getExpirationDate();
138
-		if ($expiration !== null) {
139
-			$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
140
-		}
141
-
142
-		if ($share->getShareType() === IShare::TYPE_GROUP) {
143
-			$group = $this->groupManager->get($share->getSharedWith());
144
-			$result['share_with'] = $share->getSharedWith();
145
-			$result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
146
-		} elseif ($share->getShareType() === IShare::TYPE_ROOM) {
147
-			$result['share_with'] = $share->getSharedWith();
148
-			$result['share_with_displayname'] = '';
149
-
150
-			try {
151
-				$result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
152
-			} catch (QueryException $e) {
153
-			}
154
-		} elseif ($share->getShareType() === IShare::TYPE_DECK) {
155
-			$result['share_with'] = $share->getSharedWith();
156
-			$result['share_with_displayname'] = '';
157
-
158
-			try {
159
-				$result = array_merge($result, $this->getDeckShareHelper()->formatShare($share));
160
-			} catch (QueryException $e) {
161
-			}
162
-		} elseif ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
163
-			$result['share_with'] = $share->getSharedWith();
164
-			$result['share_with_displayname'] = '';
165
-
166
-			try {
167
-				$result = array_merge($result, $this->getSciencemeshShareHelper()->formatShare($share));
168
-			} catch (QueryException $e) {
169
-			}
170
-		}
171
-
172
-		return $result;
173
-	}
174
-
175
-	/**
176
-	 * @NoAdminRequired
177
-	 */
178
-	public function index(): DataResponse {
179
-		$groupShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_GROUP, null, -1, 0);
180
-		$roomShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_ROOM, null, -1, 0);
181
-		$deckShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_DECK, null, -1, 0);
182
-		$sciencemeshShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_SCIENCEMESH, null, -1, 0);
183
-
184
-		$shares = array_merge($groupShares, $roomShares, $deckShares, $sciencemeshShares);
185
-
186
-		$shares = array_map(function (IShare $share) {
187
-			return $this->formatShare($share);
188
-		}, $shares);
189
-
190
-		return new DataResponse($shares);
191
-	}
192
-
193
-	/**
194
-	 * @NoAdminRequired
195
-	 *
196
-	 * @throws OCSException
197
-	 */
198
-	public function undelete(string $id): DataResponse {
199
-		try {
200
-			$share = $this->shareManager->getShareById($id, $this->userId);
201
-		} catch (ShareNotFound $e) {
202
-			throw new OCSNotFoundException('Share not found');
203
-		}
204
-
205
-		if ($share->getPermissions() !== 0) {
206
-			throw new OCSNotFoundException('No deleted share found');
207
-		}
208
-
209
-		try {
210
-			$this->shareManager->restoreShare($share, $this->userId);
211
-		} catch (GenericShareException $e) {
212
-			throw new OCSException('Something went wrong');
213
-		}
214
-
215
-		return new DataResponse([]);
216
-	}
217
-
218
-	/**
219
-	 * Returns the helper of DeletedShareAPIController for room shares.
220
-	 *
221
-	 * If the Talk application is not enabled or the helper is not available
222
-	 * a QueryException is thrown instead.
223
-	 *
224
-	 * @return \OCA\Talk\Share\Helper\DeletedShareAPIController
225
-	 * @throws QueryException
226
-	 */
227
-	private function getRoomShareHelper() {
228
-		if (!$this->appManager->isEnabledForUser('spreed')) {
229
-			throw new QueryException();
230
-		}
231
-
232
-		return $this->serverContainer->get('\OCA\Talk\Share\Helper\DeletedShareAPIController');
233
-	}
234
-
235
-	/**
236
-	 * Returns the helper of DeletedShareAPIHelper for deck shares.
237
-	 *
238
-	 * If the Deck application is not enabled or the helper is not available
239
-	 * a QueryException is thrown instead.
240
-	 *
241
-	 * @return \OCA\Deck\Sharing\ShareAPIHelper
242
-	 * @throws QueryException
243
-	 */
244
-	private function getDeckShareHelper() {
245
-		if (!$this->appManager->isEnabledForUser('deck')) {
246
-			throw new QueryException();
247
-		}
248
-
249
-		return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper');
250
-	}
251
-
252
-	/**
253
-	 * Returns the helper of DeletedShareAPIHelper for sciencemesh shares.
254
-	 *
255
-	 * If the sciencemesh application is not enabled or the helper is not available
256
-	 * a QueryException is thrown instead.
257
-	 *
258
-	 * @return \OCA\Deck\Sharing\ShareAPIHelper
259
-	 * @throws QueryException
260
-	 */
261
-	private function getSciencemeshShareHelper() {
262
-		if (!$this->appManager->isEnabledForUser('sciencemesh')) {
263
-			throw new QueryException();
264
-		}
265
-
266
-		return $this->serverContainer->get('\OCA\ScienceMesh\Sharing\ShareAPIHelper');
267
-	}
52
+    /** @var ShareManager */
53
+    private $shareManager;
54
+
55
+    /** @var string */
56
+    private $userId;
57
+
58
+    /** @var IUserManager */
59
+    private $userManager;
60
+
61
+    /** @var IGroupManager */
62
+    private $groupManager;
63
+
64
+    /** @var IRootFolder */
65
+    private $rootFolder;
66
+
67
+    /** @var IAppManager */
68
+    private $appManager;
69
+
70
+    /** @var IServerContainer */
71
+    private $serverContainer;
72
+
73
+    public function __construct(string $appName,
74
+                                IRequest $request,
75
+                                ShareManager $shareManager,
76
+                                string $UserId,
77
+                                IUserManager $userManager,
78
+                                IGroupManager $groupManager,
79
+                                IRootFolder $rootFolder,
80
+                                IAppManager $appManager,
81
+                                IServerContainer $serverContainer) {
82
+        parent::__construct($appName, $request);
83
+
84
+        $this->shareManager = $shareManager;
85
+        $this->userId = $UserId;
86
+        $this->userManager = $userManager;
87
+        $this->groupManager = $groupManager;
88
+        $this->rootFolder = $rootFolder;
89
+        $this->appManager = $appManager;
90
+        $this->serverContainer = $serverContainer;
91
+    }
92
+
93
+    /**
94
+     * @suppress PhanUndeclaredClassMethod
95
+     */
96
+    private function formatShare(IShare $share): array {
97
+        $result = [
98
+            'id' => $share->getFullId(),
99
+            'share_type' => $share->getShareType(),
100
+            'uid_owner' => $share->getSharedBy(),
101
+            'displayname_owner' => $this->userManager->get($share->getSharedBy())->getDisplayName(),
102
+            'permissions' => 0,
103
+            'stime' => $share->getShareTime()->getTimestamp(),
104
+            'parent' => null,
105
+            'expiration' => null,
106
+            'token' => null,
107
+            'uid_file_owner' => $share->getShareOwner(),
108
+            'displayname_file_owner' => $this->userManager->get($share->getShareOwner())->getDisplayName(),
109
+            'path' => $share->getTarget(),
110
+        ];
111
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
112
+        $nodes = $userFolder->getById($share->getNodeId());
113
+        if (empty($nodes)) {
114
+            // fallback to guessing the path
115
+            $node = $userFolder->get($share->getTarget());
116
+            if ($node === null || $share->getTarget() === '') {
117
+                throw new NotFoundException();
118
+            }
119
+        } else {
120
+            $node = $nodes[0];
121
+        }
122
+
123
+        $result['path'] = $userFolder->getRelativePath($node->getPath());
124
+        if ($node instanceof \OCP\Files\Folder) {
125
+            $result['item_type'] = 'folder';
126
+        } else {
127
+            $result['item_type'] = 'file';
128
+        }
129
+        $result['mimetype'] = $node->getMimetype();
130
+        $result['storage_id'] = $node->getStorage()->getId();
131
+        $result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
132
+        $result['item_source'] = $node->getId();
133
+        $result['file_source'] = $node->getId();
134
+        $result['file_parent'] = $node->getParent()->getId();
135
+        $result['file_target'] = $share->getTarget();
136
+
137
+        $expiration = $share->getExpirationDate();
138
+        if ($expiration !== null) {
139
+            $result['expiration'] = $expiration->format('Y-m-d 00:00:00');
140
+        }
141
+
142
+        if ($share->getShareType() === IShare::TYPE_GROUP) {
143
+            $group = $this->groupManager->get($share->getSharedWith());
144
+            $result['share_with'] = $share->getSharedWith();
145
+            $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
146
+        } elseif ($share->getShareType() === IShare::TYPE_ROOM) {
147
+            $result['share_with'] = $share->getSharedWith();
148
+            $result['share_with_displayname'] = '';
149
+
150
+            try {
151
+                $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
152
+            } catch (QueryException $e) {
153
+            }
154
+        } elseif ($share->getShareType() === IShare::TYPE_DECK) {
155
+            $result['share_with'] = $share->getSharedWith();
156
+            $result['share_with_displayname'] = '';
157
+
158
+            try {
159
+                $result = array_merge($result, $this->getDeckShareHelper()->formatShare($share));
160
+            } catch (QueryException $e) {
161
+            }
162
+        } elseif ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
163
+            $result['share_with'] = $share->getSharedWith();
164
+            $result['share_with_displayname'] = '';
165
+
166
+            try {
167
+                $result = array_merge($result, $this->getSciencemeshShareHelper()->formatShare($share));
168
+            } catch (QueryException $e) {
169
+            }
170
+        }
171
+
172
+        return $result;
173
+    }
174
+
175
+    /**
176
+     * @NoAdminRequired
177
+     */
178
+    public function index(): DataResponse {
179
+        $groupShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_GROUP, null, -1, 0);
180
+        $roomShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_ROOM, null, -1, 0);
181
+        $deckShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_DECK, null, -1, 0);
182
+        $sciencemeshShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_SCIENCEMESH, null, -1, 0);
183
+
184
+        $shares = array_merge($groupShares, $roomShares, $deckShares, $sciencemeshShares);
185
+
186
+        $shares = array_map(function (IShare $share) {
187
+            return $this->formatShare($share);
188
+        }, $shares);
189
+
190
+        return new DataResponse($shares);
191
+    }
192
+
193
+    /**
194
+     * @NoAdminRequired
195
+     *
196
+     * @throws OCSException
197
+     */
198
+    public function undelete(string $id): DataResponse {
199
+        try {
200
+            $share = $this->shareManager->getShareById($id, $this->userId);
201
+        } catch (ShareNotFound $e) {
202
+            throw new OCSNotFoundException('Share not found');
203
+        }
204
+
205
+        if ($share->getPermissions() !== 0) {
206
+            throw new OCSNotFoundException('No deleted share found');
207
+        }
208
+
209
+        try {
210
+            $this->shareManager->restoreShare($share, $this->userId);
211
+        } catch (GenericShareException $e) {
212
+            throw new OCSException('Something went wrong');
213
+        }
214
+
215
+        return new DataResponse([]);
216
+    }
217
+
218
+    /**
219
+     * Returns the helper of DeletedShareAPIController for room shares.
220
+     *
221
+     * If the Talk application is not enabled or the helper is not available
222
+     * a QueryException is thrown instead.
223
+     *
224
+     * @return \OCA\Talk\Share\Helper\DeletedShareAPIController
225
+     * @throws QueryException
226
+     */
227
+    private function getRoomShareHelper() {
228
+        if (!$this->appManager->isEnabledForUser('spreed')) {
229
+            throw new QueryException();
230
+        }
231
+
232
+        return $this->serverContainer->get('\OCA\Talk\Share\Helper\DeletedShareAPIController');
233
+    }
234
+
235
+    /**
236
+     * Returns the helper of DeletedShareAPIHelper for deck shares.
237
+     *
238
+     * If the Deck application is not enabled or the helper is not available
239
+     * a QueryException is thrown instead.
240
+     *
241
+     * @return \OCA\Deck\Sharing\ShareAPIHelper
242
+     * @throws QueryException
243
+     */
244
+    private function getDeckShareHelper() {
245
+        if (!$this->appManager->isEnabledForUser('deck')) {
246
+            throw new QueryException();
247
+        }
248
+
249
+        return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper');
250
+    }
251
+
252
+    /**
253
+     * Returns the helper of DeletedShareAPIHelper for sciencemesh shares.
254
+     *
255
+     * If the sciencemesh application is not enabled or the helper is not available
256
+     * a QueryException is thrown instead.
257
+     *
258
+     * @return \OCA\Deck\Sharing\ShareAPIHelper
259
+     * @throws QueryException
260
+     */
261
+    private function getSciencemeshShareHelper() {
262
+        if (!$this->appManager->isEnabledForUser('sciencemesh')) {
263
+            throw new QueryException();
264
+        }
265
+
266
+        return $this->serverContainer->get('\OCA\ScienceMesh\Sharing\ShareAPIHelper');
267
+    }
268 268
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -183,7 +183,7 @@
 block discarded – undo
183 183
 
184 184
 		$shares = array_merge($groupShares, $roomShares, $deckShares, $sciencemeshShares);
185 185
 
186
-		$shares = array_map(function (IShare $share) {
186
+		$shares = array_map(function(IShare $share) {
187 187
 			return $this->formatShare($share);
188 188
 		}, $shares);
189 189
 
Please login to merge, or discard this patch.