Completed
Push — master ( 031add...ab3599 )
by Morris
40:08 queued 20:01
created
lib/private/Share20/Manager.php 2 patches
Indentation   +1531 added lines, -1531 removed lines patch added patch discarded remove patch
@@ -72,1559 +72,1559 @@
 block discarded – undo
72 72
  */
73 73
 class Manager implements IManager {
74 74
 
75
-	/** @var IProviderFactory */
76
-	private $factory;
77
-	/** @var ILogger */
78
-	private $logger;
79
-	/** @var IConfig */
80
-	private $config;
81
-	/** @var ISecureRandom */
82
-	private $secureRandom;
83
-	/** @var IHasher */
84
-	private $hasher;
85
-	/** @var IMountManager */
86
-	private $mountManager;
87
-	/** @var IGroupManager */
88
-	private $groupManager;
89
-	/** @var IL10N */
90
-	private $l;
91
-	/** @var IFactory */
92
-	private $l10nFactory;
93
-	/** @var IUserManager */
94
-	private $userManager;
95
-	/** @var IRootFolder */
96
-	private $rootFolder;
97
-	/** @var CappedMemoryCache */
98
-	private $sharingDisabledForUsersCache;
99
-	/** @var EventDispatcher */
100
-	private $eventDispatcher;
101
-	/** @var LegacyHooks */
102
-	private $legacyHooks;
103
-	/** @var IMailer */
104
-	private $mailer;
105
-	/** @var IURLGenerator */
106
-	private $urlGenerator;
107
-	/** @var \OC_Defaults */
108
-	private $defaults;
109
-
110
-
111
-	/**
112
-	 * Manager constructor.
113
-	 *
114
-	 * @param ILogger $logger
115
-	 * @param IConfig $config
116
-	 * @param ISecureRandom $secureRandom
117
-	 * @param IHasher $hasher
118
-	 * @param IMountManager $mountManager
119
-	 * @param IGroupManager $groupManager
120
-	 * @param IL10N $l
121
-	 * @param IFactory $l10nFactory
122
-	 * @param IProviderFactory $factory
123
-	 * @param IUserManager $userManager
124
-	 * @param IRootFolder $rootFolder
125
-	 * @param EventDispatcher $eventDispatcher
126
-	 * @param IMailer $mailer
127
-	 * @param IURLGenerator $urlGenerator
128
-	 * @param \OC_Defaults $defaults
129
-	 */
130
-	public function __construct(
131
-			ILogger $logger,
132
-			IConfig $config,
133
-			ISecureRandom $secureRandom,
134
-			IHasher $hasher,
135
-			IMountManager $mountManager,
136
-			IGroupManager $groupManager,
137
-			IL10N $l,
138
-			IFactory $l10nFactory,
139
-			IProviderFactory $factory,
140
-			IUserManager $userManager,
141
-			IRootFolder $rootFolder,
142
-			EventDispatcher $eventDispatcher,
143
-			IMailer $mailer,
144
-			IURLGenerator $urlGenerator,
145
-			\OC_Defaults $defaults
146
-	) {
147
-		$this->logger = $logger;
148
-		$this->config = $config;
149
-		$this->secureRandom = $secureRandom;
150
-		$this->hasher = $hasher;
151
-		$this->mountManager = $mountManager;
152
-		$this->groupManager = $groupManager;
153
-		$this->l = $l;
154
-		$this->l10nFactory = $l10nFactory;
155
-		$this->factory = $factory;
156
-		$this->userManager = $userManager;
157
-		$this->rootFolder = $rootFolder;
158
-		$this->eventDispatcher = $eventDispatcher;
159
-		$this->sharingDisabledForUsersCache = new CappedMemoryCache();
160
-		$this->legacyHooks = new LegacyHooks($this->eventDispatcher);
161
-		$this->mailer = $mailer;
162
-		$this->urlGenerator = $urlGenerator;
163
-		$this->defaults = $defaults;
164
-	}
165
-
166
-	/**
167
-	 * Convert from a full share id to a tuple (providerId, shareId)
168
-	 *
169
-	 * @param string $id
170
-	 * @return string[]
171
-	 */
172
-	private function splitFullId($id) {
173
-		return explode(':', $id, 2);
174
-	}
175
-
176
-	/**
177
-	 * Verify if a password meets all requirements
178
-	 *
179
-	 * @param string $password
180
-	 * @throws \Exception
181
-	 */
182
-	protected function verifyPassword($password) {
183
-		if ($password === null) {
184
-			// No password is set, check if this is allowed.
185
-			if ($this->shareApiLinkEnforcePassword()) {
186
-				throw new \InvalidArgumentException('Passwords are enforced for link shares');
187
-			}
188
-
189
-			return;
190
-		}
191
-
192
-		// Let others verify the password
193
-		try {
194
-			$event = new GenericEvent($password);
195
-			$this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event);
196
-		} catch (HintException $e) {
197
-			throw new \Exception($e->getHint());
198
-		}
199
-	}
200
-
201
-	/**
202
-	 * Check for generic requirements before creating a share
203
-	 *
204
-	 * @param \OCP\Share\IShare $share
205
-	 * @throws \InvalidArgumentException
206
-	 * @throws GenericShareException
207
-	 *
208
-	 * @suppress PhanUndeclaredClassMethod
209
-	 */
210
-	protected function generalCreateChecks(\OCP\Share\IShare $share) {
211
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
212
-			// We expect a valid user as sharedWith for user shares
213
-			if (!$this->userManager->userExists($share->getSharedWith())) {
214
-				throw new \InvalidArgumentException('SharedWith is not a valid user');
215
-			}
216
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
217
-			// We expect a valid group as sharedWith for group shares
218
-			if (!$this->groupManager->groupExists($share->getSharedWith())) {
219
-				throw new \InvalidArgumentException('SharedWith is not a valid group');
220
-			}
221
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
222
-			if ($share->getSharedWith() !== null) {
223
-				throw new \InvalidArgumentException('SharedWith should be empty');
224
-			}
225
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
226
-			if ($share->getSharedWith() === null) {
227
-				throw new \InvalidArgumentException('SharedWith should not be empty');
228
-			}
229
-		}  else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
230
-			if ($share->getSharedWith() === null) {
231
-				throw new \InvalidArgumentException('SharedWith should not be empty');
232
-			}
233
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
234
-			if ($share->getSharedWith() === null) {
235
-				throw new \InvalidArgumentException('SharedWith should not be empty');
236
-			}
237
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) {
238
-			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($share->getSharedWith());
239
-			if ($circle === null) {
240
-				throw new \InvalidArgumentException('SharedWith is not a valid circle');
241
-			}
242
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM) {
243
-		} else {
244
-			// We can't handle other types yet
245
-			throw new \InvalidArgumentException('unknown share type');
246
-		}
247
-
248
-		// Verify the initiator of the share is set
249
-		if ($share->getSharedBy() === null) {
250
-			throw new \InvalidArgumentException('SharedBy should be set');
251
-		}
252
-
253
-		// Cannot share with yourself
254
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
255
-			$share->getSharedWith() === $share->getSharedBy()) {
256
-			throw new \InvalidArgumentException('Can’t share with yourself');
257
-		}
258
-
259
-		// The path should be set
260
-		if ($share->getNode() === null) {
261
-			throw new \InvalidArgumentException('Path should be set');
262
-		}
263
-
264
-		// And it should be a file or a folder
265
-		if (!($share->getNode() instanceof \OCP\Files\File) &&
266
-				!($share->getNode() instanceof \OCP\Files\Folder)) {
267
-			throw new \InvalidArgumentException('Path should be either a file or a folder');
268
-		}
269
-
270
-		// And you can't share your rootfolder
271
-		if ($this->userManager->userExists($share->getSharedBy())) {
272
-			$sharedPath = $this->rootFolder->getUserFolder($share->getSharedBy())->getPath();
273
-		} else {
274
-			$sharedPath = $this->rootFolder->getUserFolder($share->getShareOwner())->getPath();
275
-		}
276
-		if ($sharedPath === $share->getNode()->getPath()) {
277
-			throw new \InvalidArgumentException('You can’t share your root folder');
278
-		}
279
-
280
-		// Check if we actually have share permissions
281
-		if (!$share->getNode()->isShareable()) {
282
-			$message_t = $this->l->t('You are not allowed to share %s', [$share->getNode()->getPath()]);
283
-			throw new GenericShareException($message_t, $message_t, 404);
284
-		}
285
-
286
-		// Permissions should be set
287
-		if ($share->getPermissions() === null) {
288
-			throw new \InvalidArgumentException('A share requires permissions');
289
-		}
290
-
291
-		/*
75
+    /** @var IProviderFactory */
76
+    private $factory;
77
+    /** @var ILogger */
78
+    private $logger;
79
+    /** @var IConfig */
80
+    private $config;
81
+    /** @var ISecureRandom */
82
+    private $secureRandom;
83
+    /** @var IHasher */
84
+    private $hasher;
85
+    /** @var IMountManager */
86
+    private $mountManager;
87
+    /** @var IGroupManager */
88
+    private $groupManager;
89
+    /** @var IL10N */
90
+    private $l;
91
+    /** @var IFactory */
92
+    private $l10nFactory;
93
+    /** @var IUserManager */
94
+    private $userManager;
95
+    /** @var IRootFolder */
96
+    private $rootFolder;
97
+    /** @var CappedMemoryCache */
98
+    private $sharingDisabledForUsersCache;
99
+    /** @var EventDispatcher */
100
+    private $eventDispatcher;
101
+    /** @var LegacyHooks */
102
+    private $legacyHooks;
103
+    /** @var IMailer */
104
+    private $mailer;
105
+    /** @var IURLGenerator */
106
+    private $urlGenerator;
107
+    /** @var \OC_Defaults */
108
+    private $defaults;
109
+
110
+
111
+    /**
112
+     * Manager constructor.
113
+     *
114
+     * @param ILogger $logger
115
+     * @param IConfig $config
116
+     * @param ISecureRandom $secureRandom
117
+     * @param IHasher $hasher
118
+     * @param IMountManager $mountManager
119
+     * @param IGroupManager $groupManager
120
+     * @param IL10N $l
121
+     * @param IFactory $l10nFactory
122
+     * @param IProviderFactory $factory
123
+     * @param IUserManager $userManager
124
+     * @param IRootFolder $rootFolder
125
+     * @param EventDispatcher $eventDispatcher
126
+     * @param IMailer $mailer
127
+     * @param IURLGenerator $urlGenerator
128
+     * @param \OC_Defaults $defaults
129
+     */
130
+    public function __construct(
131
+            ILogger $logger,
132
+            IConfig $config,
133
+            ISecureRandom $secureRandom,
134
+            IHasher $hasher,
135
+            IMountManager $mountManager,
136
+            IGroupManager $groupManager,
137
+            IL10N $l,
138
+            IFactory $l10nFactory,
139
+            IProviderFactory $factory,
140
+            IUserManager $userManager,
141
+            IRootFolder $rootFolder,
142
+            EventDispatcher $eventDispatcher,
143
+            IMailer $mailer,
144
+            IURLGenerator $urlGenerator,
145
+            \OC_Defaults $defaults
146
+    ) {
147
+        $this->logger = $logger;
148
+        $this->config = $config;
149
+        $this->secureRandom = $secureRandom;
150
+        $this->hasher = $hasher;
151
+        $this->mountManager = $mountManager;
152
+        $this->groupManager = $groupManager;
153
+        $this->l = $l;
154
+        $this->l10nFactory = $l10nFactory;
155
+        $this->factory = $factory;
156
+        $this->userManager = $userManager;
157
+        $this->rootFolder = $rootFolder;
158
+        $this->eventDispatcher = $eventDispatcher;
159
+        $this->sharingDisabledForUsersCache = new CappedMemoryCache();
160
+        $this->legacyHooks = new LegacyHooks($this->eventDispatcher);
161
+        $this->mailer = $mailer;
162
+        $this->urlGenerator = $urlGenerator;
163
+        $this->defaults = $defaults;
164
+    }
165
+
166
+    /**
167
+     * Convert from a full share id to a tuple (providerId, shareId)
168
+     *
169
+     * @param string $id
170
+     * @return string[]
171
+     */
172
+    private function splitFullId($id) {
173
+        return explode(':', $id, 2);
174
+    }
175
+
176
+    /**
177
+     * Verify if a password meets all requirements
178
+     *
179
+     * @param string $password
180
+     * @throws \Exception
181
+     */
182
+    protected function verifyPassword($password) {
183
+        if ($password === null) {
184
+            // No password is set, check if this is allowed.
185
+            if ($this->shareApiLinkEnforcePassword()) {
186
+                throw new \InvalidArgumentException('Passwords are enforced for link shares');
187
+            }
188
+
189
+            return;
190
+        }
191
+
192
+        // Let others verify the password
193
+        try {
194
+            $event = new GenericEvent($password);
195
+            $this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event);
196
+        } catch (HintException $e) {
197
+            throw new \Exception($e->getHint());
198
+        }
199
+    }
200
+
201
+    /**
202
+     * Check for generic requirements before creating a share
203
+     *
204
+     * @param \OCP\Share\IShare $share
205
+     * @throws \InvalidArgumentException
206
+     * @throws GenericShareException
207
+     *
208
+     * @suppress PhanUndeclaredClassMethod
209
+     */
210
+    protected function generalCreateChecks(\OCP\Share\IShare $share) {
211
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
212
+            // We expect a valid user as sharedWith for user shares
213
+            if (!$this->userManager->userExists($share->getSharedWith())) {
214
+                throw new \InvalidArgumentException('SharedWith is not a valid user');
215
+            }
216
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
217
+            // We expect a valid group as sharedWith for group shares
218
+            if (!$this->groupManager->groupExists($share->getSharedWith())) {
219
+                throw new \InvalidArgumentException('SharedWith is not a valid group');
220
+            }
221
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
222
+            if ($share->getSharedWith() !== null) {
223
+                throw new \InvalidArgumentException('SharedWith should be empty');
224
+            }
225
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) {
226
+            if ($share->getSharedWith() === null) {
227
+                throw new \InvalidArgumentException('SharedWith should not be empty');
228
+            }
229
+        }  else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
230
+            if ($share->getSharedWith() === null) {
231
+                throw new \InvalidArgumentException('SharedWith should not be empty');
232
+            }
233
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
234
+            if ($share->getSharedWith() === null) {
235
+                throw new \InvalidArgumentException('SharedWith should not be empty');
236
+            }
237
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_CIRCLE) {
238
+            $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($share->getSharedWith());
239
+            if ($circle === null) {
240
+                throw new \InvalidArgumentException('SharedWith is not a valid circle');
241
+            }
242
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM) {
243
+        } else {
244
+            // We can't handle other types yet
245
+            throw new \InvalidArgumentException('unknown share type');
246
+        }
247
+
248
+        // Verify the initiator of the share is set
249
+        if ($share->getSharedBy() === null) {
250
+            throw new \InvalidArgumentException('SharedBy should be set');
251
+        }
252
+
253
+        // Cannot share with yourself
254
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
255
+            $share->getSharedWith() === $share->getSharedBy()) {
256
+            throw new \InvalidArgumentException('Can’t share with yourself');
257
+        }
258
+
259
+        // The path should be set
260
+        if ($share->getNode() === null) {
261
+            throw new \InvalidArgumentException('Path should be set');
262
+        }
263
+
264
+        // And it should be a file or a folder
265
+        if (!($share->getNode() instanceof \OCP\Files\File) &&
266
+                !($share->getNode() instanceof \OCP\Files\Folder)) {
267
+            throw new \InvalidArgumentException('Path should be either a file or a folder');
268
+        }
269
+
270
+        // And you can't share your rootfolder
271
+        if ($this->userManager->userExists($share->getSharedBy())) {
272
+            $sharedPath = $this->rootFolder->getUserFolder($share->getSharedBy())->getPath();
273
+        } else {
274
+            $sharedPath = $this->rootFolder->getUserFolder($share->getShareOwner())->getPath();
275
+        }
276
+        if ($sharedPath === $share->getNode()->getPath()) {
277
+            throw new \InvalidArgumentException('You can’t share your root folder');
278
+        }
279
+
280
+        // Check if we actually have share permissions
281
+        if (!$share->getNode()->isShareable()) {
282
+            $message_t = $this->l->t('You are not allowed to share %s', [$share->getNode()->getPath()]);
283
+            throw new GenericShareException($message_t, $message_t, 404);
284
+        }
285
+
286
+        // Permissions should be set
287
+        if ($share->getPermissions() === null) {
288
+            throw new \InvalidArgumentException('A share requires permissions');
289
+        }
290
+
291
+        /*
292 292
 		 * Quick fix for #23536
293 293
 		 * Non moveable mount points do not have update and delete permissions
294 294
 		 * while we 'most likely' do have that on the storage.
295 295
 		 */
296
-		$permissions = $share->getNode()->getPermissions();
297
-		$mount = $share->getNode()->getMountPoint();
298
-		if (!($mount instanceof MoveableMount)) {
299
-			$permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
300
-		}
301
-
302
-		// Check that we do not share with more permissions than we have
303
-		if ($share->getPermissions() & ~$permissions) {
304
-			$message_t = $this->l->t('Can’t increase permissions of %s', [$share->getNode()->getPath()]);
305
-			throw new GenericShareException($message_t, $message_t, 404);
306
-		}
307
-
308
-
309
-		// Check that read permissions are always set
310
-		// Link shares are allowed to have no read permissions to allow upload to hidden folders
311
-		$noReadPermissionRequired = $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK
312
-			|| $share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL;
313
-		if (!$noReadPermissionRequired &&
314
-			($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
315
-			throw new \InvalidArgumentException('Shares need at least read permissions');
316
-		}
317
-
318
-		if ($share->getNode() instanceof \OCP\Files\File) {
319
-			if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
320
-				$message_t = $this->l->t('Files can’t be shared with delete permissions');
321
-				throw new GenericShareException($message_t);
322
-			}
323
-			if ($share->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
324
-				$message_t = $this->l->t('Files can’t be shared with create permissions');
325
-				throw new GenericShareException($message_t);
326
-			}
327
-		}
328
-	}
329
-
330
-	/**
331
-	 * Validate if the expiration date fits the system settings
332
-	 *
333
-	 * @param \OCP\Share\IShare $share The share to validate the expiration date of
334
-	 * @return \OCP\Share\IShare The modified share object
335
-	 * @throws GenericShareException
336
-	 * @throws \InvalidArgumentException
337
-	 * @throws \Exception
338
-	 */
339
-	protected function validateExpirationDate(\OCP\Share\IShare $share) {
340
-
341
-		$expirationDate = $share->getExpirationDate();
342
-
343
-		if ($expirationDate !== null) {
344
-			//Make sure the expiration date is a date
345
-			$expirationDate->setTime(0, 0, 0);
346
-
347
-			$date = new \DateTime();
348
-			$date->setTime(0, 0, 0);
349
-			if ($date >= $expirationDate) {
350
-				$message = $this->l->t('Expiration date is in the past');
351
-				throw new GenericShareException($message, $message, 404);
352
-			}
353
-		}
354
-
355
-		// If expiredate is empty set a default one if there is a default
356
-		$fullId = null;
357
-		try {
358
-			$fullId = $share->getFullId();
359
-		} catch (\UnexpectedValueException $e) {
360
-			// This is a new share
361
-		}
362
-
363
-		if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
364
-			$expirationDate = new \DateTime();
365
-			$expirationDate->setTime(0,0,0);
366
-			$expirationDate->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
367
-		}
368
-
369
-		// If we enforce the expiration date check that is does not exceed
370
-		if ($this->shareApiLinkDefaultExpireDateEnforced()) {
371
-			if ($expirationDate === null) {
372
-				throw new \InvalidArgumentException('Expiration date is enforced');
373
-			}
374
-
375
-			$date = new \DateTime();
376
-			$date->setTime(0, 0, 0);
377
-			$date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
378
-			if ($date < $expirationDate) {
379
-				$message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
380
-				throw new GenericShareException($message, $message, 404);
381
-			}
382
-		}
383
-
384
-		$accepted = true;
385
-		$message = '';
386
-		\OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
387
-			'expirationDate' => &$expirationDate,
388
-			'accepted' => &$accepted,
389
-			'message' => &$message,
390
-			'passwordSet' => $share->getPassword() !== null,
391
-		]);
392
-
393
-		if (!$accepted) {
394
-			throw new \Exception($message);
395
-		}
396
-
397
-		$share->setExpirationDate($expirationDate);
398
-
399
-		return $share;
400
-	}
401
-
402
-	/**
403
-	 * Check for pre share requirements for user shares
404
-	 *
405
-	 * @param \OCP\Share\IShare $share
406
-	 * @throws \Exception
407
-	 */
408
-	protected function userCreateChecks(\OCP\Share\IShare $share) {
409
-		// Check if we can share with group members only
410
-		if ($this->shareWithGroupMembersOnly()) {
411
-			$sharedBy = $this->userManager->get($share->getSharedBy());
412
-			$sharedWith = $this->userManager->get($share->getSharedWith());
413
-			// Verify we can share with this user
414
-			$groups = array_intersect(
415
-					$this->groupManager->getUserGroupIds($sharedBy),
416
-					$this->groupManager->getUserGroupIds($sharedWith)
417
-			);
418
-			if (empty($groups)) {
419
-				throw new \Exception('Sharing is only allowed with group members');
420
-			}
421
-		}
422
-
423
-		/*
296
+        $permissions = $share->getNode()->getPermissions();
297
+        $mount = $share->getNode()->getMountPoint();
298
+        if (!($mount instanceof MoveableMount)) {
299
+            $permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
300
+        }
301
+
302
+        // Check that we do not share with more permissions than we have
303
+        if ($share->getPermissions() & ~$permissions) {
304
+            $message_t = $this->l->t('Can’t increase permissions of %s', [$share->getNode()->getPath()]);
305
+            throw new GenericShareException($message_t, $message_t, 404);
306
+        }
307
+
308
+
309
+        // Check that read permissions are always set
310
+        // Link shares are allowed to have no read permissions to allow upload to hidden folders
311
+        $noReadPermissionRequired = $share->getShareType() === \OCP\Share::SHARE_TYPE_LINK
312
+            || $share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL;
313
+        if (!$noReadPermissionRequired &&
314
+            ($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) {
315
+            throw new \InvalidArgumentException('Shares need at least read permissions');
316
+        }
317
+
318
+        if ($share->getNode() instanceof \OCP\Files\File) {
319
+            if ($share->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
320
+                $message_t = $this->l->t('Files can’t be shared with delete permissions');
321
+                throw new GenericShareException($message_t);
322
+            }
323
+            if ($share->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
324
+                $message_t = $this->l->t('Files can’t be shared with create permissions');
325
+                throw new GenericShareException($message_t);
326
+            }
327
+        }
328
+    }
329
+
330
+    /**
331
+     * Validate if the expiration date fits the system settings
332
+     *
333
+     * @param \OCP\Share\IShare $share The share to validate the expiration date of
334
+     * @return \OCP\Share\IShare The modified share object
335
+     * @throws GenericShareException
336
+     * @throws \InvalidArgumentException
337
+     * @throws \Exception
338
+     */
339
+    protected function validateExpirationDate(\OCP\Share\IShare $share) {
340
+
341
+        $expirationDate = $share->getExpirationDate();
342
+
343
+        if ($expirationDate !== null) {
344
+            //Make sure the expiration date is a date
345
+            $expirationDate->setTime(0, 0, 0);
346
+
347
+            $date = new \DateTime();
348
+            $date->setTime(0, 0, 0);
349
+            if ($date >= $expirationDate) {
350
+                $message = $this->l->t('Expiration date is in the past');
351
+                throw new GenericShareException($message, $message, 404);
352
+            }
353
+        }
354
+
355
+        // If expiredate is empty set a default one if there is a default
356
+        $fullId = null;
357
+        try {
358
+            $fullId = $share->getFullId();
359
+        } catch (\UnexpectedValueException $e) {
360
+            // This is a new share
361
+        }
362
+
363
+        if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
364
+            $expirationDate = new \DateTime();
365
+            $expirationDate->setTime(0,0,0);
366
+            $expirationDate->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
367
+        }
368
+
369
+        // If we enforce the expiration date check that is does not exceed
370
+        if ($this->shareApiLinkDefaultExpireDateEnforced()) {
371
+            if ($expirationDate === null) {
372
+                throw new \InvalidArgumentException('Expiration date is enforced');
373
+            }
374
+
375
+            $date = new \DateTime();
376
+            $date->setTime(0, 0, 0);
377
+            $date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
378
+            if ($date < $expirationDate) {
379
+                $message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
380
+                throw new GenericShareException($message, $message, 404);
381
+            }
382
+        }
383
+
384
+        $accepted = true;
385
+        $message = '';
386
+        \OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [
387
+            'expirationDate' => &$expirationDate,
388
+            'accepted' => &$accepted,
389
+            'message' => &$message,
390
+            'passwordSet' => $share->getPassword() !== null,
391
+        ]);
392
+
393
+        if (!$accepted) {
394
+            throw new \Exception($message);
395
+        }
396
+
397
+        $share->setExpirationDate($expirationDate);
398
+
399
+        return $share;
400
+    }
401
+
402
+    /**
403
+     * Check for pre share requirements for user shares
404
+     *
405
+     * @param \OCP\Share\IShare $share
406
+     * @throws \Exception
407
+     */
408
+    protected function userCreateChecks(\OCP\Share\IShare $share) {
409
+        // Check if we can share with group members only
410
+        if ($this->shareWithGroupMembersOnly()) {
411
+            $sharedBy = $this->userManager->get($share->getSharedBy());
412
+            $sharedWith = $this->userManager->get($share->getSharedWith());
413
+            // Verify we can share with this user
414
+            $groups = array_intersect(
415
+                    $this->groupManager->getUserGroupIds($sharedBy),
416
+                    $this->groupManager->getUserGroupIds($sharedWith)
417
+            );
418
+            if (empty($groups)) {
419
+                throw new \Exception('Sharing is only allowed with group members');
420
+            }
421
+        }
422
+
423
+        /*
424 424
 		 * TODO: Could be costly, fix
425 425
 		 *
426 426
 		 * Also this is not what we want in the future.. then we want to squash identical shares.
427 427
 		 */
428
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_USER);
429
-		$existingShares = $provider->getSharesByPath($share->getNode());
430
-		foreach($existingShares as $existingShare) {
431
-			// Ignore if it is the same share
432
-			try {
433
-				if ($existingShare->getFullId() === $share->getFullId()) {
434
-					continue;
435
-				}
436
-			} catch (\UnexpectedValueException $e) {
437
-				//Shares are not identical
438
-			}
439
-
440
-			// Identical share already existst
441
-			if ($existingShare->getSharedWith() === $share->getSharedWith()) {
442
-				throw new \Exception('Path is already shared with this user');
443
-			}
444
-
445
-			// The share is already shared with this user via a group share
446
-			if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
447
-				$group = $this->groupManager->get($existingShare->getSharedWith());
448
-				if (!is_null($group)) {
449
-					$user = $this->userManager->get($share->getSharedWith());
450
-
451
-					if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
452
-						throw new \Exception('Path is already shared with this user');
453
-					}
454
-				}
455
-			}
456
-		}
457
-	}
458
-
459
-	/**
460
-	 * Check for pre share requirements for group shares
461
-	 *
462
-	 * @param \OCP\Share\IShare $share
463
-	 * @throws \Exception
464
-	 */
465
-	protected function groupCreateChecks(\OCP\Share\IShare $share) {
466
-		// Verify group shares are allowed
467
-		if (!$this->allowGroupSharing()) {
468
-			throw new \Exception('Group sharing is now allowed');
469
-		}
470
-
471
-		// Verify if the user can share with this group
472
-		if ($this->shareWithGroupMembersOnly()) {
473
-			$sharedBy = $this->userManager->get($share->getSharedBy());
474
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
475
-			if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
476
-				throw new \Exception('Sharing is only allowed within your own groups');
477
-			}
478
-		}
479
-
480
-		/*
428
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_USER);
429
+        $existingShares = $provider->getSharesByPath($share->getNode());
430
+        foreach($existingShares as $existingShare) {
431
+            // Ignore if it is the same share
432
+            try {
433
+                if ($existingShare->getFullId() === $share->getFullId()) {
434
+                    continue;
435
+                }
436
+            } catch (\UnexpectedValueException $e) {
437
+                //Shares are not identical
438
+            }
439
+
440
+            // Identical share already existst
441
+            if ($existingShare->getSharedWith() === $share->getSharedWith()) {
442
+                throw new \Exception('Path is already shared with this user');
443
+            }
444
+
445
+            // The share is already shared with this user via a group share
446
+            if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
447
+                $group = $this->groupManager->get($existingShare->getSharedWith());
448
+                if (!is_null($group)) {
449
+                    $user = $this->userManager->get($share->getSharedWith());
450
+
451
+                    if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
452
+                        throw new \Exception('Path is already shared with this user');
453
+                    }
454
+                }
455
+            }
456
+        }
457
+    }
458
+
459
+    /**
460
+     * Check for pre share requirements for group shares
461
+     *
462
+     * @param \OCP\Share\IShare $share
463
+     * @throws \Exception
464
+     */
465
+    protected function groupCreateChecks(\OCP\Share\IShare $share) {
466
+        // Verify group shares are allowed
467
+        if (!$this->allowGroupSharing()) {
468
+            throw new \Exception('Group sharing is now allowed');
469
+        }
470
+
471
+        // Verify if the user can share with this group
472
+        if ($this->shareWithGroupMembersOnly()) {
473
+            $sharedBy = $this->userManager->get($share->getSharedBy());
474
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
475
+            if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
476
+                throw new \Exception('Sharing is only allowed within your own groups');
477
+            }
478
+        }
479
+
480
+        /*
481 481
 		 * TODO: Could be costly, fix
482 482
 		 *
483 483
 		 * Also this is not what we want in the future.. then we want to squash identical shares.
484 484
 		 */
485
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
486
-		$existingShares = $provider->getSharesByPath($share->getNode());
487
-		foreach($existingShares as $existingShare) {
488
-			try {
489
-				if ($existingShare->getFullId() === $share->getFullId()) {
490
-					continue;
491
-				}
492
-			} catch (\UnexpectedValueException $e) {
493
-				//It is a new share so just continue
494
-			}
495
-
496
-			if ($existingShare->getSharedWith() === $share->getSharedWith()) {
497
-				throw new \Exception('Path is already shared with this group');
498
-			}
499
-		}
500
-	}
501
-
502
-	/**
503
-	 * Check for pre share requirements for link shares
504
-	 *
505
-	 * @param \OCP\Share\IShare $share
506
-	 * @throws \Exception
507
-	 */
508
-	protected function linkCreateChecks(\OCP\Share\IShare $share) {
509
-		// Are link shares allowed?
510
-		if (!$this->shareApiAllowLinks()) {
511
-			throw new \Exception('Link sharing is not allowed');
512
-		}
513
-
514
-		// Link shares by definition can't have share permissions
515
-		if ($share->getPermissions() & \OCP\Constants::PERMISSION_SHARE) {
516
-			throw new \InvalidArgumentException('Link shares can’t have reshare permissions');
517
-		}
518
-
519
-		// Check if public upload is allowed
520
-		if (!$this->shareApiLinkAllowPublicUpload() &&
521
-			($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
522
-			throw new \InvalidArgumentException('Public upload is not allowed');
523
-		}
524
-	}
525
-
526
-	/**
527
-	 * To make sure we don't get invisible link shares we set the parent
528
-	 * of a link if it is a reshare. This is a quick word around
529
-	 * until we can properly display multiple link shares in the UI
530
-	 *
531
-	 * See: https://github.com/owncloud/core/issues/22295
532
-	 *
533
-	 * FIXME: Remove once multiple link shares can be properly displayed
534
-	 *
535
-	 * @param \OCP\Share\IShare $share
536
-	 */
537
-	protected function setLinkParent(\OCP\Share\IShare $share) {
538
-
539
-		// No sense in checking if the method is not there.
540
-		if (method_exists($share, 'setParent')) {
541
-			$storage = $share->getNode()->getStorage();
542
-			if ($storage->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
543
-				/** @var \OCA\Files_Sharing\SharedStorage $storage */
544
-				$share->setParent($storage->getShareId());
545
-			}
546
-		}
547
-	}
548
-
549
-	/**
550
-	 * @param File|Folder $path
551
-	 */
552
-	protected function pathCreateChecks($path) {
553
-		// Make sure that we do not share a path that contains a shared mountpoint
554
-		if ($path instanceof \OCP\Files\Folder) {
555
-			$mounts = $this->mountManager->findIn($path->getPath());
556
-			foreach($mounts as $mount) {
557
-				if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
558
-					throw new \InvalidArgumentException('Path contains files shared with you');
559
-				}
560
-			}
561
-		}
562
-	}
563
-
564
-	/**
565
-	 * Check if the user that is sharing can actually share
566
-	 *
567
-	 * @param \OCP\Share\IShare $share
568
-	 * @throws \Exception
569
-	 */
570
-	protected function canShare(\OCP\Share\IShare $share) {
571
-		if (!$this->shareApiEnabled()) {
572
-			throw new \Exception('Sharing is disabled');
573
-		}
574
-
575
-		if ($this->sharingDisabledForUser($share->getSharedBy())) {
576
-			throw new \Exception('Sharing is disabled for you');
577
-		}
578
-	}
579
-
580
-	/**
581
-	 * Share a path
582
-	 *
583
-	 * @param \OCP\Share\IShare $share
584
-	 * @return Share The share object
585
-	 * @throws \Exception
586
-	 *
587
-	 * TODO: handle link share permissions or check them
588
-	 */
589
-	public function createShare(\OCP\Share\IShare $share) {
590
-		$this->canShare($share);
591
-
592
-		$this->generalCreateChecks($share);
593
-
594
-		// Verify if there are any issues with the path
595
-		$this->pathCreateChecks($share->getNode());
596
-
597
-		/*
485
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
486
+        $existingShares = $provider->getSharesByPath($share->getNode());
487
+        foreach($existingShares as $existingShare) {
488
+            try {
489
+                if ($existingShare->getFullId() === $share->getFullId()) {
490
+                    continue;
491
+                }
492
+            } catch (\UnexpectedValueException $e) {
493
+                //It is a new share so just continue
494
+            }
495
+
496
+            if ($existingShare->getSharedWith() === $share->getSharedWith()) {
497
+                throw new \Exception('Path is already shared with this group');
498
+            }
499
+        }
500
+    }
501
+
502
+    /**
503
+     * Check for pre share requirements for link shares
504
+     *
505
+     * @param \OCP\Share\IShare $share
506
+     * @throws \Exception
507
+     */
508
+    protected function linkCreateChecks(\OCP\Share\IShare $share) {
509
+        // Are link shares allowed?
510
+        if (!$this->shareApiAllowLinks()) {
511
+            throw new \Exception('Link sharing is not allowed');
512
+        }
513
+
514
+        // Link shares by definition can't have share permissions
515
+        if ($share->getPermissions() & \OCP\Constants::PERMISSION_SHARE) {
516
+            throw new \InvalidArgumentException('Link shares can’t have reshare permissions');
517
+        }
518
+
519
+        // Check if public upload is allowed
520
+        if (!$this->shareApiLinkAllowPublicUpload() &&
521
+            ($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) {
522
+            throw new \InvalidArgumentException('Public upload is not allowed');
523
+        }
524
+    }
525
+
526
+    /**
527
+     * To make sure we don't get invisible link shares we set the parent
528
+     * of a link if it is a reshare. This is a quick word around
529
+     * until we can properly display multiple link shares in the UI
530
+     *
531
+     * See: https://github.com/owncloud/core/issues/22295
532
+     *
533
+     * FIXME: Remove once multiple link shares can be properly displayed
534
+     *
535
+     * @param \OCP\Share\IShare $share
536
+     */
537
+    protected function setLinkParent(\OCP\Share\IShare $share) {
538
+
539
+        // No sense in checking if the method is not there.
540
+        if (method_exists($share, 'setParent')) {
541
+            $storage = $share->getNode()->getStorage();
542
+            if ($storage->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
543
+                /** @var \OCA\Files_Sharing\SharedStorage $storage */
544
+                $share->setParent($storage->getShareId());
545
+            }
546
+        }
547
+    }
548
+
549
+    /**
550
+     * @param File|Folder $path
551
+     */
552
+    protected function pathCreateChecks($path) {
553
+        // Make sure that we do not share a path that contains a shared mountpoint
554
+        if ($path instanceof \OCP\Files\Folder) {
555
+            $mounts = $this->mountManager->findIn($path->getPath());
556
+            foreach($mounts as $mount) {
557
+                if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
558
+                    throw new \InvalidArgumentException('Path contains files shared with you');
559
+                }
560
+            }
561
+        }
562
+    }
563
+
564
+    /**
565
+     * Check if the user that is sharing can actually share
566
+     *
567
+     * @param \OCP\Share\IShare $share
568
+     * @throws \Exception
569
+     */
570
+    protected function canShare(\OCP\Share\IShare $share) {
571
+        if (!$this->shareApiEnabled()) {
572
+            throw new \Exception('Sharing is disabled');
573
+        }
574
+
575
+        if ($this->sharingDisabledForUser($share->getSharedBy())) {
576
+            throw new \Exception('Sharing is disabled for you');
577
+        }
578
+    }
579
+
580
+    /**
581
+     * Share a path
582
+     *
583
+     * @param \OCP\Share\IShare $share
584
+     * @return Share The share object
585
+     * @throws \Exception
586
+     *
587
+     * TODO: handle link share permissions or check them
588
+     */
589
+    public function createShare(\OCP\Share\IShare $share) {
590
+        $this->canShare($share);
591
+
592
+        $this->generalCreateChecks($share);
593
+
594
+        // Verify if there are any issues with the path
595
+        $this->pathCreateChecks($share->getNode());
596
+
597
+        /*
598 598
 		 * On creation of a share the owner is always the owner of the path
599 599
 		 * Except for mounted federated shares.
600 600
 		 */
601
-		$storage = $share->getNode()->getStorage();
602
-		if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
603
-			$parent = $share->getNode()->getParent();
604
-			while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
605
-				$parent = $parent->getParent();
606
-			}
607
-			$share->setShareOwner($parent->getOwner()->getUID());
608
-		} else {
609
-			$share->setShareOwner($share->getNode()->getOwner()->getUID());
610
-		}
611
-
612
-		//Verify share type
613
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
614
-			$this->userCreateChecks($share);
615
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
616
-			$this->groupCreateChecks($share);
617
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
618
-			$this->linkCreateChecks($share);
619
-			$this->setLinkParent($share);
620
-
621
-			/*
601
+        $storage = $share->getNode()->getStorage();
602
+        if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
603
+            $parent = $share->getNode()->getParent();
604
+            while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
605
+                $parent = $parent->getParent();
606
+            }
607
+            $share->setShareOwner($parent->getOwner()->getUID());
608
+        } else {
609
+            $share->setShareOwner($share->getNode()->getOwner()->getUID());
610
+        }
611
+
612
+        //Verify share type
613
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
614
+            $this->userCreateChecks($share);
615
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
616
+            $this->groupCreateChecks($share);
617
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
618
+            $this->linkCreateChecks($share);
619
+            $this->setLinkParent($share);
620
+
621
+            /*
622 622
 			 * For now ignore a set token.
623 623
 			 */
624
-			$share->setToken(
625
-				$this->secureRandom->generate(
626
-					\OC\Share\Constants::TOKEN_LENGTH,
627
-					\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
628
-				)
629
-			);
630
-
631
-			//Verify the expiration date
632
-			$this->validateExpirationDate($share);
633
-
634
-			//Verify the password
635
-			$this->verifyPassword($share->getPassword());
636
-
637
-			// If a password is set. Hash it!
638
-			if ($share->getPassword() !== null) {
639
-				$share->setPassword($this->hasher->hash($share->getPassword()));
640
-			}
641
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
642
-			$share->setToken(
643
-				$this->secureRandom->generate(
644
-					\OC\Share\Constants::TOKEN_LENGTH,
645
-					\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
646
-				)
647
-			);
648
-		}
649
-
650
-		// Cannot share with the owner
651
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
652
-			$share->getSharedWith() === $share->getShareOwner()) {
653
-			throw new \InvalidArgumentException('Can’t share with the share owner');
654
-		}
655
-
656
-		// Generate the target
657
-		$target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
658
-		$target = \OC\Files\Filesystem::normalizePath($target);
659
-		$share->setTarget($target);
660
-
661
-		// Pre share event
662
-		$event = new GenericEvent($share);
663
-		$a = $this->eventDispatcher->dispatch('OCP\Share::preShare', $event);
664
-		if ($event->isPropagationStopped() && $event->hasArgument('error')) {
665
-			throw new \Exception($event->getArgument('error'));
666
-		}
667
-
668
-		$oldShare = $share;
669
-		$provider = $this->factory->getProviderForType($share->getShareType());
670
-		$share = $provider->create($share);
671
-		//reuse the node we already have
672
-		$share->setNode($oldShare->getNode());
673
-
674
-		// Post share event
675
-		$event = new GenericEvent($share);
676
-		$this->eventDispatcher->dispatch('OCP\Share::postShare', $event);
677
-
678
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
679
-			$mailSend = $share->getMailSend();
680
-			if($mailSend === true) {
681
-				$user = $this->userManager->get($share->getSharedWith());
682
-				if ($user !== null) {
683
-					$emailAddress = $user->getEMailAddress();
684
-					if ($emailAddress !== null && $emailAddress !== '') {
685
-						$userLang = $this->config->getUserValue($share->getSharedWith(), 'core', 'lang', null);
686
-						$l = $this->l10nFactory->get('lib', $userLang);
687
-						$this->sendMailNotification(
688
-							$l,
689
-							$share->getNode()->getName(),
690
-							$this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]),
691
-							$share->getSharedBy(),
692
-							$emailAddress,
693
-							$share->getExpirationDate()
694
-						);
695
-						$this->logger->debug('Send share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
696
-					} else {
697
-						$this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
698
-					}
699
-				} else {
700
-					$this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
701
-				}
702
-			} else {
703
-				$this->logger->debug('Share notification not send because mailsend is false.', ['app' => 'share']);
704
-			}
705
-		}
706
-
707
-		return $share;
708
-	}
709
-
710
-	/**
711
-	 * @param IL10N $l Language of the recipient
712
-	 * @param string $filename file/folder name
713
-	 * @param string $link link to the file/folder
714
-	 * @param string $initiator user ID of share sender
715
-	 * @param string $shareWith email address of share receiver
716
-	 * @param \DateTime|null $expiration
717
-	 * @throws \Exception If mail couldn't be sent
718
-	 */
719
-	protected function sendMailNotification(IL10N $l,
720
-											$filename,
721
-											$link,
722
-											$initiator,
723
-											$shareWith,
724
-											\DateTime $expiration = null) {
725
-		$initiatorUser = $this->userManager->get($initiator);
726
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
727
-
728
-		$message = $this->mailer->createMessage();
729
-
730
-		$emailTemplate = $this->mailer->createEMailTemplate('files_sharing.RecipientNotification', [
731
-			'filename' => $filename,
732
-			'link' => $link,
733
-			'initiator' => $initiatorDisplayName,
734
-			'expiration' => $expiration,
735
-			'shareWith' => $shareWith,
736
-		]);
737
-
738
-		$emailTemplate->setSubject($l->t('%1$s shared »%2$s« with you', array($initiatorDisplayName, $filename)));
739
-		$emailTemplate->addHeader();
740
-		$emailTemplate->addHeading($l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
741
-		$text = $l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
742
-
743
-		$emailTemplate->addBodyText(
744
-			htmlspecialchars($text . ' ' . $l->t('Click the button below to open it.')),
745
-			$text
746
-		);
747
-		$emailTemplate->addBodyButton(
748
-			$l->t('Open »%s«', [$filename]),
749
-			$link
750
-		);
751
-
752
-		$message->setTo([$shareWith]);
753
-
754
-		// The "From" contains the sharers name
755
-		$instanceName = $this->defaults->getName();
756
-		$senderName = $l->t(
757
-			'%1$s via %2$s',
758
-			[
759
-				$initiatorDisplayName,
760
-				$instanceName
761
-			]
762
-		);
763
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
764
-
765
-		// The "Reply-To" is set to the sharer if an mail address is configured
766
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
767
-		$initiatorEmail = $initiatorUser->getEMailAddress();
768
-		if($initiatorEmail !== null) {
769
-			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
770
-			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
771
-		} else {
772
-			$emailTemplate->addFooter();
773
-		}
774
-
775
-		$message->useTemplate($emailTemplate);
776
-		$this->mailer->send($message);
777
-	}
778
-
779
-	/**
780
-	 * Update a share
781
-	 *
782
-	 * @param \OCP\Share\IShare $share
783
-	 * @return \OCP\Share\IShare The share object
784
-	 * @throws \InvalidArgumentException
785
-	 */
786
-	public function updateShare(\OCP\Share\IShare $share) {
787
-		$expirationDateUpdated = false;
788
-
789
-		$this->canShare($share);
790
-
791
-		try {
792
-			$originalShare = $this->getShareById($share->getFullId());
793
-		} catch (\UnexpectedValueException $e) {
794
-			throw new \InvalidArgumentException('Share does not have a full id');
795
-		}
796
-
797
-		// We can't change the share type!
798
-		if ($share->getShareType() !== $originalShare->getShareType()) {
799
-			throw new \InvalidArgumentException('Can’t change share type');
800
-		}
801
-
802
-		// We can only change the recipient on user shares
803
-		if ($share->getSharedWith() !== $originalShare->getSharedWith() &&
804
-		    $share->getShareType() !== \OCP\Share::SHARE_TYPE_USER) {
805
-			throw new \InvalidArgumentException('Can only update recipient on user shares');
806
-		}
807
-
808
-		// Cannot share with the owner
809
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
810
-			$share->getSharedWith() === $share->getShareOwner()) {
811
-			throw new \InvalidArgumentException('Can’t share with the share owner');
812
-		}
813
-
814
-		$this->generalCreateChecks($share);
815
-
816
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
817
-			$this->userCreateChecks($share);
818
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
819
-			$this->groupCreateChecks($share);
820
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
821
-			$this->linkCreateChecks($share);
822
-
823
-			$this->updateSharePasswordIfNeeded($share, $originalShare);
824
-
825
-			if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
826
-				//Verify the expiration date
827
-				$this->validateExpirationDate($share);
828
-				$expirationDateUpdated = true;
829
-			}
830
-		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
831
-			// The new password is not set again if it is the same as the old
832
-			// one, unless when switching from sending by Talk to sending by
833
-			// mail.
834
-			$plainTextPassword = $share->getPassword();
835
-			if (!empty($plainTextPassword) && !$this->updateSharePasswordIfNeeded($share, $originalShare) &&
836
-					!($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk())) {
837
-				$plainTextPassword = null;
838
-			}
839
-			if (empty($plainTextPassword) && !$originalShare->getSendPasswordByTalk() && $share->getSendPasswordByTalk()) {
840
-				// If the same password was already sent by mail the recipient
841
-				// would already have access to the share without having to call
842
-				// the sharer to verify her identity
843
-				throw new \InvalidArgumentException('Can’t enable sending the password by Talk without setting a new password');
844
-			}
845
-		}
846
-
847
-		$this->pathCreateChecks($share->getNode());
848
-
849
-		// Now update the share!
850
-		$provider = $this->factory->getProviderForType($share->getShareType());
851
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
852
-			$share = $provider->update($share, $plainTextPassword);
853
-		} else {
854
-			$share = $provider->update($share);
855
-		}
856
-
857
-		if ($expirationDateUpdated === true) {
858
-			\OC_Hook::emit(Share::class, 'post_set_expiration_date', [
859
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
860
-				'itemSource' => $share->getNode()->getId(),
861
-				'date' => $share->getExpirationDate(),
862
-				'uidOwner' => $share->getSharedBy(),
863
-			]);
864
-		}
865
-
866
-		if ($share->getPassword() !== $originalShare->getPassword()) {
867
-			\OC_Hook::emit(Share::class, 'post_update_password', [
868
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
869
-				'itemSource' => $share->getNode()->getId(),
870
-				'uidOwner' => $share->getSharedBy(),
871
-				'token' => $share->getToken(),
872
-				'disabled' => is_null($share->getPassword()),
873
-			]);
874
-		}
875
-
876
-		if ($share->getPermissions() !== $originalShare->getPermissions()) {
877
-			if ($this->userManager->userExists($share->getShareOwner())) {
878
-				$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
879
-			} else {
880
-				$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
881
-			}
882
-			\OC_Hook::emit(Share::class, 'post_update_permissions', array(
883
-				'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
884
-				'itemSource' => $share->getNode()->getId(),
885
-				'shareType' => $share->getShareType(),
886
-				'shareWith' => $share->getSharedWith(),
887
-				'uidOwner' => $share->getSharedBy(),
888
-				'permissions' => $share->getPermissions(),
889
-				'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
890
-			));
891
-		}
892
-
893
-		return $share;
894
-	}
895
-
896
-	/**
897
-	 * Updates the password of the given share if it is not the same as the
898
-	 * password of the original share.
899
-	 *
900
-	 * @param \OCP\Share\IShare $share the share to update its password.
901
-	 * @param \OCP\Share\IShare $originalShare the original share to compare its
902
-	 *        password with.
903
-	 * @return boolean whether the password was updated or not.
904
-	 */
905
-	private function updateSharePasswordIfNeeded(\OCP\Share\IShare $share, \OCP\Share\IShare $originalShare) {
906
-		// Password updated.
907
-		if ($share->getPassword() !== $originalShare->getPassword()) {
908
-			//Verify the password
909
-			$this->verifyPassword($share->getPassword());
910
-
911
-			// If a password is set. Hash it!
912
-			if ($share->getPassword() !== null) {
913
-				$share->setPassword($this->hasher->hash($share->getPassword()));
914
-
915
-				return true;
916
-			}
917
-		}
918
-
919
-		return false;
920
-	}
921
-
922
-	/**
923
-	 * Delete all the children of this share
924
-	 * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
925
-	 *
926
-	 * @param \OCP\Share\IShare $share
927
-	 * @return \OCP\Share\IShare[] List of deleted shares
928
-	 */
929
-	protected function deleteChildren(\OCP\Share\IShare $share) {
930
-		$deletedShares = [];
931
-
932
-		$provider = $this->factory->getProviderForType($share->getShareType());
933
-
934
-		foreach ($provider->getChildren($share) as $child) {
935
-			$deletedChildren = $this->deleteChildren($child);
936
-			$deletedShares = array_merge($deletedShares, $deletedChildren);
937
-
938
-			$provider->delete($child);
939
-			$deletedShares[] = $child;
940
-		}
941
-
942
-		return $deletedShares;
943
-	}
944
-
945
-	/**
946
-	 * Delete a share
947
-	 *
948
-	 * @param \OCP\Share\IShare $share
949
-	 * @throws ShareNotFound
950
-	 * @throws \InvalidArgumentException
951
-	 */
952
-	public function deleteShare(\OCP\Share\IShare $share) {
953
-
954
-		try {
955
-			$share->getFullId();
956
-		} catch (\UnexpectedValueException $e) {
957
-			throw new \InvalidArgumentException('Share does not have a full id');
958
-		}
959
-
960
-		$event = new GenericEvent($share);
961
-		$this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event);
962
-
963
-		// Get all children and delete them as well
964
-		$deletedShares = $this->deleteChildren($share);
965
-
966
-		// Do the actual delete
967
-		$provider = $this->factory->getProviderForType($share->getShareType());
968
-		$provider->delete($share);
969
-
970
-		// All the deleted shares caused by this delete
971
-		$deletedShares[] = $share;
972
-
973
-		// Emit post hook
974
-		$event->setArgument('deletedShares', $deletedShares);
975
-		$this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event);
976
-	}
977
-
978
-
979
-	/**
980
-	 * Unshare a file as the recipient.
981
-	 * This can be different from a regular delete for example when one of
982
-	 * the users in a groups deletes that share. But the provider should
983
-	 * handle this.
984
-	 *
985
-	 * @param \OCP\Share\IShare $share
986
-	 * @param string $recipientId
987
-	 */
988
-	public function deleteFromSelf(\OCP\Share\IShare $share, $recipientId) {
989
-		list($providerId, ) = $this->splitFullId($share->getFullId());
990
-		$provider = $this->factory->getProvider($providerId);
991
-
992
-		$provider->deleteFromSelf($share, $recipientId);
993
-		$event = new GenericEvent($share);
994
-		$this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
995
-	}
996
-
997
-	public function restoreShare(IShare $share, string $recipientId): IShare {
998
-		list($providerId, ) = $this->splitFullId($share->getFullId());
999
-		$provider = $this->factory->getProvider($providerId);
1000
-
1001
-		return $provider->restore($share, $recipientId);
1002
-	}
1003
-
1004
-	/**
1005
-	 * @inheritdoc
1006
-	 */
1007
-	public function moveShare(\OCP\Share\IShare $share, $recipientId) {
1008
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
1009
-			throw new \InvalidArgumentException('Can’t change target of link share');
1010
-		}
1011
-
1012
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipientId) {
1013
-			throw new \InvalidArgumentException('Invalid recipient');
1014
-		}
1015
-
1016
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
1017
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
1018
-			if (is_null($sharedWith)) {
1019
-				throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
1020
-			}
1021
-			$recipient = $this->userManager->get($recipientId);
1022
-			if (!$sharedWith->inGroup($recipient)) {
1023
-				throw new \InvalidArgumentException('Invalid recipient');
1024
-			}
1025
-		}
1026
-
1027
-		list($providerId, ) = $this->splitFullId($share->getFullId());
1028
-		$provider = $this->factory->getProvider($providerId);
1029
-
1030
-		$provider->move($share, $recipientId);
1031
-	}
1032
-
1033
-	public function getSharesInFolder($userId, Folder $node, $reshares = false) {
1034
-		$providers = $this->factory->getAllProviders();
1035
-
1036
-		return array_reduce($providers, function($shares, IShareProvider $provider) use ($userId, $node, $reshares) {
1037
-			$newShares = $provider->getSharesInFolder($userId, $node, $reshares);
1038
-			foreach ($newShares as $fid => $data) {
1039
-				if (!isset($shares[$fid])) {
1040
-					$shares[$fid] = [];
1041
-				}
1042
-
1043
-				$shares[$fid] = array_merge($shares[$fid], $data);
1044
-			}
1045
-			return $shares;
1046
-		}, []);
1047
-	}
1048
-
1049
-	/**
1050
-	 * @inheritdoc
1051
-	 */
1052
-	public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
1053
-		if ($path !== null &&
1054
-				!($path instanceof \OCP\Files\File) &&
1055
-				!($path instanceof \OCP\Files\Folder)) {
1056
-			throw new \InvalidArgumentException('invalid path');
1057
-		}
1058
-
1059
-		try {
1060
-			$provider = $this->factory->getProviderForType($shareType);
1061
-		} catch (ProviderException $e) {
1062
-			return [];
1063
-		}
1064
-
1065
-		$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1066
-
1067
-		/*
624
+            $share->setToken(
625
+                $this->secureRandom->generate(
626
+                    \OC\Share\Constants::TOKEN_LENGTH,
627
+                    \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
628
+                )
629
+            );
630
+
631
+            //Verify the expiration date
632
+            $this->validateExpirationDate($share);
633
+
634
+            //Verify the password
635
+            $this->verifyPassword($share->getPassword());
636
+
637
+            // If a password is set. Hash it!
638
+            if ($share->getPassword() !== null) {
639
+                $share->setPassword($this->hasher->hash($share->getPassword()));
640
+            }
641
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
642
+            $share->setToken(
643
+                $this->secureRandom->generate(
644
+                    \OC\Share\Constants::TOKEN_LENGTH,
645
+                    \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
646
+                )
647
+            );
648
+        }
649
+
650
+        // Cannot share with the owner
651
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
652
+            $share->getSharedWith() === $share->getShareOwner()) {
653
+            throw new \InvalidArgumentException('Can’t share with the share owner');
654
+        }
655
+
656
+        // Generate the target
657
+        $target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
658
+        $target = \OC\Files\Filesystem::normalizePath($target);
659
+        $share->setTarget($target);
660
+
661
+        // Pre share event
662
+        $event = new GenericEvent($share);
663
+        $a = $this->eventDispatcher->dispatch('OCP\Share::preShare', $event);
664
+        if ($event->isPropagationStopped() && $event->hasArgument('error')) {
665
+            throw new \Exception($event->getArgument('error'));
666
+        }
667
+
668
+        $oldShare = $share;
669
+        $provider = $this->factory->getProviderForType($share->getShareType());
670
+        $share = $provider->create($share);
671
+        //reuse the node we already have
672
+        $share->setNode($oldShare->getNode());
673
+
674
+        // Post share event
675
+        $event = new GenericEvent($share);
676
+        $this->eventDispatcher->dispatch('OCP\Share::postShare', $event);
677
+
678
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
679
+            $mailSend = $share->getMailSend();
680
+            if($mailSend === true) {
681
+                $user = $this->userManager->get($share->getSharedWith());
682
+                if ($user !== null) {
683
+                    $emailAddress = $user->getEMailAddress();
684
+                    if ($emailAddress !== null && $emailAddress !== '') {
685
+                        $userLang = $this->config->getUserValue($share->getSharedWith(), 'core', 'lang', null);
686
+                        $l = $this->l10nFactory->get('lib', $userLang);
687
+                        $this->sendMailNotification(
688
+                            $l,
689
+                            $share->getNode()->getName(),
690
+                            $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]),
691
+                            $share->getSharedBy(),
692
+                            $emailAddress,
693
+                            $share->getExpirationDate()
694
+                        );
695
+                        $this->logger->debug('Send share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
696
+                    } else {
697
+                        $this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
698
+                    }
699
+                } else {
700
+                    $this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
701
+                }
702
+            } else {
703
+                $this->logger->debug('Share notification not send because mailsend is false.', ['app' => 'share']);
704
+            }
705
+        }
706
+
707
+        return $share;
708
+    }
709
+
710
+    /**
711
+     * @param IL10N $l Language of the recipient
712
+     * @param string $filename file/folder name
713
+     * @param string $link link to the file/folder
714
+     * @param string $initiator user ID of share sender
715
+     * @param string $shareWith email address of share receiver
716
+     * @param \DateTime|null $expiration
717
+     * @throws \Exception If mail couldn't be sent
718
+     */
719
+    protected function sendMailNotification(IL10N $l,
720
+                                            $filename,
721
+                                            $link,
722
+                                            $initiator,
723
+                                            $shareWith,
724
+                                            \DateTime $expiration = null) {
725
+        $initiatorUser = $this->userManager->get($initiator);
726
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
727
+
728
+        $message = $this->mailer->createMessage();
729
+
730
+        $emailTemplate = $this->mailer->createEMailTemplate('files_sharing.RecipientNotification', [
731
+            'filename' => $filename,
732
+            'link' => $link,
733
+            'initiator' => $initiatorDisplayName,
734
+            'expiration' => $expiration,
735
+            'shareWith' => $shareWith,
736
+        ]);
737
+
738
+        $emailTemplate->setSubject($l->t('%1$s shared »%2$s« with you', array($initiatorDisplayName, $filename)));
739
+        $emailTemplate->addHeader();
740
+        $emailTemplate->addHeading($l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
741
+        $text = $l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
742
+
743
+        $emailTemplate->addBodyText(
744
+            htmlspecialchars($text . ' ' . $l->t('Click the button below to open it.')),
745
+            $text
746
+        );
747
+        $emailTemplate->addBodyButton(
748
+            $l->t('Open »%s«', [$filename]),
749
+            $link
750
+        );
751
+
752
+        $message->setTo([$shareWith]);
753
+
754
+        // The "From" contains the sharers name
755
+        $instanceName = $this->defaults->getName();
756
+        $senderName = $l->t(
757
+            '%1$s via %2$s',
758
+            [
759
+                $initiatorDisplayName,
760
+                $instanceName
761
+            ]
762
+        );
763
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
764
+
765
+        // The "Reply-To" is set to the sharer if an mail address is configured
766
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
767
+        $initiatorEmail = $initiatorUser->getEMailAddress();
768
+        if($initiatorEmail !== null) {
769
+            $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
770
+            $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
771
+        } else {
772
+            $emailTemplate->addFooter();
773
+        }
774
+
775
+        $message->useTemplate($emailTemplate);
776
+        $this->mailer->send($message);
777
+    }
778
+
779
+    /**
780
+     * Update a share
781
+     *
782
+     * @param \OCP\Share\IShare $share
783
+     * @return \OCP\Share\IShare The share object
784
+     * @throws \InvalidArgumentException
785
+     */
786
+    public function updateShare(\OCP\Share\IShare $share) {
787
+        $expirationDateUpdated = false;
788
+
789
+        $this->canShare($share);
790
+
791
+        try {
792
+            $originalShare = $this->getShareById($share->getFullId());
793
+        } catch (\UnexpectedValueException $e) {
794
+            throw new \InvalidArgumentException('Share does not have a full id');
795
+        }
796
+
797
+        // We can't change the share type!
798
+        if ($share->getShareType() !== $originalShare->getShareType()) {
799
+            throw new \InvalidArgumentException('Can’t change share type');
800
+        }
801
+
802
+        // We can only change the recipient on user shares
803
+        if ($share->getSharedWith() !== $originalShare->getSharedWith() &&
804
+            $share->getShareType() !== \OCP\Share::SHARE_TYPE_USER) {
805
+            throw new \InvalidArgumentException('Can only update recipient on user shares');
806
+        }
807
+
808
+        // Cannot share with the owner
809
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER &&
810
+            $share->getSharedWith() === $share->getShareOwner()) {
811
+            throw new \InvalidArgumentException('Can’t share with the share owner');
812
+        }
813
+
814
+        $this->generalCreateChecks($share);
815
+
816
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
817
+            $this->userCreateChecks($share);
818
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
819
+            $this->groupCreateChecks($share);
820
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
821
+            $this->linkCreateChecks($share);
822
+
823
+            $this->updateSharePasswordIfNeeded($share, $originalShare);
824
+
825
+            if ($share->getExpirationDate() != $originalShare->getExpirationDate()) {
826
+                //Verify the expiration date
827
+                $this->validateExpirationDate($share);
828
+                $expirationDateUpdated = true;
829
+            }
830
+        } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
831
+            // The new password is not set again if it is the same as the old
832
+            // one, unless when switching from sending by Talk to sending by
833
+            // mail.
834
+            $plainTextPassword = $share->getPassword();
835
+            if (!empty($plainTextPassword) && !$this->updateSharePasswordIfNeeded($share, $originalShare) &&
836
+                    !($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk())) {
837
+                $plainTextPassword = null;
838
+            }
839
+            if (empty($plainTextPassword) && !$originalShare->getSendPasswordByTalk() && $share->getSendPasswordByTalk()) {
840
+                // If the same password was already sent by mail the recipient
841
+                // would already have access to the share without having to call
842
+                // the sharer to verify her identity
843
+                throw new \InvalidArgumentException('Can’t enable sending the password by Talk without setting a new password');
844
+            }
845
+        }
846
+
847
+        $this->pathCreateChecks($share->getNode());
848
+
849
+        // Now update the share!
850
+        $provider = $this->factory->getProviderForType($share->getShareType());
851
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
852
+            $share = $provider->update($share, $plainTextPassword);
853
+        } else {
854
+            $share = $provider->update($share);
855
+        }
856
+
857
+        if ($expirationDateUpdated === true) {
858
+            \OC_Hook::emit(Share::class, 'post_set_expiration_date', [
859
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
860
+                'itemSource' => $share->getNode()->getId(),
861
+                'date' => $share->getExpirationDate(),
862
+                'uidOwner' => $share->getSharedBy(),
863
+            ]);
864
+        }
865
+
866
+        if ($share->getPassword() !== $originalShare->getPassword()) {
867
+            \OC_Hook::emit(Share::class, 'post_update_password', [
868
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
869
+                'itemSource' => $share->getNode()->getId(),
870
+                'uidOwner' => $share->getSharedBy(),
871
+                'token' => $share->getToken(),
872
+                'disabled' => is_null($share->getPassword()),
873
+            ]);
874
+        }
875
+
876
+        if ($share->getPermissions() !== $originalShare->getPermissions()) {
877
+            if ($this->userManager->userExists($share->getShareOwner())) {
878
+                $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
879
+            } else {
880
+                $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
881
+            }
882
+            \OC_Hook::emit(Share::class, 'post_update_permissions', array(
883
+                'itemType' => $share->getNode() instanceof \OCP\Files\File ? 'file' : 'folder',
884
+                'itemSource' => $share->getNode()->getId(),
885
+                'shareType' => $share->getShareType(),
886
+                'shareWith' => $share->getSharedWith(),
887
+                'uidOwner' => $share->getSharedBy(),
888
+                'permissions' => $share->getPermissions(),
889
+                'path' => $userFolder->getRelativePath($share->getNode()->getPath()),
890
+            ));
891
+        }
892
+
893
+        return $share;
894
+    }
895
+
896
+    /**
897
+     * Updates the password of the given share if it is not the same as the
898
+     * password of the original share.
899
+     *
900
+     * @param \OCP\Share\IShare $share the share to update its password.
901
+     * @param \OCP\Share\IShare $originalShare the original share to compare its
902
+     *        password with.
903
+     * @return boolean whether the password was updated or not.
904
+     */
905
+    private function updateSharePasswordIfNeeded(\OCP\Share\IShare $share, \OCP\Share\IShare $originalShare) {
906
+        // Password updated.
907
+        if ($share->getPassword() !== $originalShare->getPassword()) {
908
+            //Verify the password
909
+            $this->verifyPassword($share->getPassword());
910
+
911
+            // If a password is set. Hash it!
912
+            if ($share->getPassword() !== null) {
913
+                $share->setPassword($this->hasher->hash($share->getPassword()));
914
+
915
+                return true;
916
+            }
917
+        }
918
+
919
+        return false;
920
+    }
921
+
922
+    /**
923
+     * Delete all the children of this share
924
+     * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
925
+     *
926
+     * @param \OCP\Share\IShare $share
927
+     * @return \OCP\Share\IShare[] List of deleted shares
928
+     */
929
+    protected function deleteChildren(\OCP\Share\IShare $share) {
930
+        $deletedShares = [];
931
+
932
+        $provider = $this->factory->getProviderForType($share->getShareType());
933
+
934
+        foreach ($provider->getChildren($share) as $child) {
935
+            $deletedChildren = $this->deleteChildren($child);
936
+            $deletedShares = array_merge($deletedShares, $deletedChildren);
937
+
938
+            $provider->delete($child);
939
+            $deletedShares[] = $child;
940
+        }
941
+
942
+        return $deletedShares;
943
+    }
944
+
945
+    /**
946
+     * Delete a share
947
+     *
948
+     * @param \OCP\Share\IShare $share
949
+     * @throws ShareNotFound
950
+     * @throws \InvalidArgumentException
951
+     */
952
+    public function deleteShare(\OCP\Share\IShare $share) {
953
+
954
+        try {
955
+            $share->getFullId();
956
+        } catch (\UnexpectedValueException $e) {
957
+            throw new \InvalidArgumentException('Share does not have a full id');
958
+        }
959
+
960
+        $event = new GenericEvent($share);
961
+        $this->eventDispatcher->dispatch('OCP\Share::preUnshare', $event);
962
+
963
+        // Get all children and delete them as well
964
+        $deletedShares = $this->deleteChildren($share);
965
+
966
+        // Do the actual delete
967
+        $provider = $this->factory->getProviderForType($share->getShareType());
968
+        $provider->delete($share);
969
+
970
+        // All the deleted shares caused by this delete
971
+        $deletedShares[] = $share;
972
+
973
+        // Emit post hook
974
+        $event->setArgument('deletedShares', $deletedShares);
975
+        $this->eventDispatcher->dispatch('OCP\Share::postUnshare', $event);
976
+    }
977
+
978
+
979
+    /**
980
+     * Unshare a file as the recipient.
981
+     * This can be different from a regular delete for example when one of
982
+     * the users in a groups deletes that share. But the provider should
983
+     * handle this.
984
+     *
985
+     * @param \OCP\Share\IShare $share
986
+     * @param string $recipientId
987
+     */
988
+    public function deleteFromSelf(\OCP\Share\IShare $share, $recipientId) {
989
+        list($providerId, ) = $this->splitFullId($share->getFullId());
990
+        $provider = $this->factory->getProvider($providerId);
991
+
992
+        $provider->deleteFromSelf($share, $recipientId);
993
+        $event = new GenericEvent($share);
994
+        $this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
995
+    }
996
+
997
+    public function restoreShare(IShare $share, string $recipientId): IShare {
998
+        list($providerId, ) = $this->splitFullId($share->getFullId());
999
+        $provider = $this->factory->getProvider($providerId);
1000
+
1001
+        return $provider->restore($share, $recipientId);
1002
+    }
1003
+
1004
+    /**
1005
+     * @inheritdoc
1006
+     */
1007
+    public function moveShare(\OCP\Share\IShare $share, $recipientId) {
1008
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) {
1009
+            throw new \InvalidArgumentException('Can’t change target of link share');
1010
+        }
1011
+
1012
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && $share->getSharedWith() !== $recipientId) {
1013
+            throw new \InvalidArgumentException('Invalid recipient');
1014
+        }
1015
+
1016
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
1017
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
1018
+            if (is_null($sharedWith)) {
1019
+                throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
1020
+            }
1021
+            $recipient = $this->userManager->get($recipientId);
1022
+            if (!$sharedWith->inGroup($recipient)) {
1023
+                throw new \InvalidArgumentException('Invalid recipient');
1024
+            }
1025
+        }
1026
+
1027
+        list($providerId, ) = $this->splitFullId($share->getFullId());
1028
+        $provider = $this->factory->getProvider($providerId);
1029
+
1030
+        $provider->move($share, $recipientId);
1031
+    }
1032
+
1033
+    public function getSharesInFolder($userId, Folder $node, $reshares = false) {
1034
+        $providers = $this->factory->getAllProviders();
1035
+
1036
+        return array_reduce($providers, function($shares, IShareProvider $provider) use ($userId, $node, $reshares) {
1037
+            $newShares = $provider->getSharesInFolder($userId, $node, $reshares);
1038
+            foreach ($newShares as $fid => $data) {
1039
+                if (!isset($shares[$fid])) {
1040
+                    $shares[$fid] = [];
1041
+                }
1042
+
1043
+                $shares[$fid] = array_merge($shares[$fid], $data);
1044
+            }
1045
+            return $shares;
1046
+        }, []);
1047
+    }
1048
+
1049
+    /**
1050
+     * @inheritdoc
1051
+     */
1052
+    public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0) {
1053
+        if ($path !== null &&
1054
+                !($path instanceof \OCP\Files\File) &&
1055
+                !($path instanceof \OCP\Files\Folder)) {
1056
+            throw new \InvalidArgumentException('invalid path');
1057
+        }
1058
+
1059
+        try {
1060
+            $provider = $this->factory->getProviderForType($shareType);
1061
+        } catch (ProviderException $e) {
1062
+            return [];
1063
+        }
1064
+
1065
+        $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1066
+
1067
+        /*
1068 1068
 		 * Work around so we don't return expired shares but still follow
1069 1069
 		 * proper pagination.
1070 1070
 		 */
1071 1071
 
1072
-		$shares2 = [];
1073
-
1074
-		while(true) {
1075
-			$added = 0;
1076
-			foreach ($shares as $share) {
1077
-
1078
-				try {
1079
-					$this->checkExpireDate($share);
1080
-				} catch (ShareNotFound $e) {
1081
-					//Ignore since this basically means the share is deleted
1082
-					continue;
1083
-				}
1084
-
1085
-				$added++;
1086
-				$shares2[] = $share;
1087
-
1088
-				if (count($shares2) === $limit) {
1089
-					break;
1090
-				}
1091
-			}
1092
-
1093
-			// If we did not fetch more shares than the limit then there are no more shares
1094
-			if (count($shares) < $limit) {
1095
-				break;
1096
-			}
1097
-
1098
-			if (count($shares2) === $limit) {
1099
-				break;
1100
-			}
1101
-
1102
-			// If there was no limit on the select we are done
1103
-			if ($limit === -1) {
1104
-				break;
1105
-			}
1106
-
1107
-			$offset += $added;
1108
-
1109
-			// Fetch again $limit shares
1110
-			$shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1111
-
1112
-			// No more shares means we are done
1113
-			if (empty($shares)) {
1114
-				break;
1115
-			}
1116
-		}
1117
-
1118
-		$shares = $shares2;
1119
-
1120
-		return $shares;
1121
-	}
1122
-
1123
-	/**
1124
-	 * @inheritdoc
1125
-	 */
1126
-	public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1127
-		try {
1128
-			$provider = $this->factory->getProviderForType($shareType);
1129
-		} catch (ProviderException $e) {
1130
-			return [];
1131
-		}
1132
-
1133
-		$shares = $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
1134
-
1135
-		// remove all shares which are already expired
1136
-		foreach ($shares as $key => $share) {
1137
-			try {
1138
-				$this->checkExpireDate($share);
1139
-			} catch (ShareNotFound $e) {
1140
-				unset($shares[$key]);
1141
-			}
1142
-		}
1143
-
1144
-		return $shares;
1145
-	}
1146
-
1147
-	/**
1148
-	 * @inheritdoc
1149
-	 */
1150
-	public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1151
-		$shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);
1152
-
1153
-		// Only get deleted shares
1154
-		$shares = array_filter($shares, function(IShare $share) {
1155
-			return $share->getPermissions() === 0;
1156
-		});
1157
-
1158
-		// Only get shares where the owner still exists
1159
-		$shares = array_filter($shares, function (IShare $share) {
1160
-			return $this->userManager->userExists($share->getShareOwner());
1161
-		});
1162
-
1163
-		return $shares;
1164
-	}
1165
-
1166
-	/**
1167
-	 * @inheritdoc
1168
-	 */
1169
-	public function getShareById($id, $recipient = null) {
1170
-		if ($id === null) {
1171
-			throw new ShareNotFound();
1172
-		}
1173
-
1174
-		list($providerId, $id) = $this->splitFullId($id);
1175
-
1176
-		try {
1177
-			$provider = $this->factory->getProvider($providerId);
1178
-		} catch (ProviderException $e) {
1179
-			throw new ShareNotFound();
1180
-		}
1181
-
1182
-		$share = $provider->getShareById($id, $recipient);
1183
-
1184
-		$this->checkExpireDate($share);
1185
-
1186
-		return $share;
1187
-	}
1188
-
1189
-	/**
1190
-	 * Get all the shares for a given path
1191
-	 *
1192
-	 * @param \OCP\Files\Node $path
1193
-	 * @param int $page
1194
-	 * @param int $perPage
1195
-	 *
1196
-	 * @return Share[]
1197
-	 */
1198
-	public function getSharesByPath(\OCP\Files\Node $path, $page=0, $perPage=50) {
1199
-		return [];
1200
-	}
1201
-
1202
-	/**
1203
-	 * Get the share by token possible with password
1204
-	 *
1205
-	 * @param string $token
1206
-	 * @return Share
1207
-	 *
1208
-	 * @throws ShareNotFound
1209
-	 */
1210
-	public function getShareByToken($token) {
1211
-		// tokens can't be valid local user names
1212
-		if ($this->userManager->userExists($token)) {
1213
-			throw new ShareNotFound();
1214
-		}
1215
-		$share = null;
1216
-		try {
1217
-			if($this->shareApiAllowLinks()) {
1218
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK);
1219
-				$share = $provider->getShareByToken($token);
1220
-			}
1221
-		} catch (ProviderException $e) {
1222
-		} catch (ShareNotFound $e) {
1223
-		}
1224
-
1225
-
1226
-		// If it is not a link share try to fetch a federated share by token
1227
-		if ($share === null) {
1228
-			try {
1229
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE);
1230
-				$share = $provider->getShareByToken($token);
1231
-			} catch (ProviderException $e) {
1232
-			} catch (ShareNotFound $e) {
1233
-			}
1234
-		}
1235
-
1236
-		// If it is not a link share try to fetch a mail share by token
1237
-		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
1238
-			try {
1239
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_EMAIL);
1240
-				$share = $provider->getShareByToken($token);
1241
-			} catch (ProviderException $e) {
1242
-			} catch (ShareNotFound $e) {
1243
-			}
1244
-		}
1245
-
1246
-		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) {
1247
-			try {
1248
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_CIRCLE);
1249
-				$share = $provider->getShareByToken($token);
1250
-			} catch (ProviderException $e) {
1251
-			} catch (ShareNotFound $e) {
1252
-			}
1253
-		}
1254
-
1255
-		if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_ROOM)) {
1256
-			try {
1257
-				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_ROOM);
1258
-				$share = $provider->getShareByToken($token);
1259
-			} catch (ProviderException $e) {
1260
-			} catch (ShareNotFound $e) {
1261
-			}
1262
-		}
1263
-
1264
-		if ($share === null) {
1265
-			throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1266
-		}
1267
-
1268
-		$this->checkExpireDate($share);
1269
-
1270
-		/*
1072
+        $shares2 = [];
1073
+
1074
+        while(true) {
1075
+            $added = 0;
1076
+            foreach ($shares as $share) {
1077
+
1078
+                try {
1079
+                    $this->checkExpireDate($share);
1080
+                } catch (ShareNotFound $e) {
1081
+                    //Ignore since this basically means the share is deleted
1082
+                    continue;
1083
+                }
1084
+
1085
+                $added++;
1086
+                $shares2[] = $share;
1087
+
1088
+                if (count($shares2) === $limit) {
1089
+                    break;
1090
+                }
1091
+            }
1092
+
1093
+            // If we did not fetch more shares than the limit then there are no more shares
1094
+            if (count($shares) < $limit) {
1095
+                break;
1096
+            }
1097
+
1098
+            if (count($shares2) === $limit) {
1099
+                break;
1100
+            }
1101
+
1102
+            // If there was no limit on the select we are done
1103
+            if ($limit === -1) {
1104
+                break;
1105
+            }
1106
+
1107
+            $offset += $added;
1108
+
1109
+            // Fetch again $limit shares
1110
+            $shares = $provider->getSharesBy($userId, $shareType, $path, $reshares, $limit, $offset);
1111
+
1112
+            // No more shares means we are done
1113
+            if (empty($shares)) {
1114
+                break;
1115
+            }
1116
+        }
1117
+
1118
+        $shares = $shares2;
1119
+
1120
+        return $shares;
1121
+    }
1122
+
1123
+    /**
1124
+     * @inheritdoc
1125
+     */
1126
+    public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1127
+        try {
1128
+            $provider = $this->factory->getProviderForType($shareType);
1129
+        } catch (ProviderException $e) {
1130
+            return [];
1131
+        }
1132
+
1133
+        $shares = $provider->getSharedWith($userId, $shareType, $node, $limit, $offset);
1134
+
1135
+        // remove all shares which are already expired
1136
+        foreach ($shares as $key => $share) {
1137
+            try {
1138
+                $this->checkExpireDate($share);
1139
+            } catch (ShareNotFound $e) {
1140
+                unset($shares[$key]);
1141
+            }
1142
+        }
1143
+
1144
+        return $shares;
1145
+    }
1146
+
1147
+    /**
1148
+     * @inheritdoc
1149
+     */
1150
+    public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
1151
+        $shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);
1152
+
1153
+        // Only get deleted shares
1154
+        $shares = array_filter($shares, function(IShare $share) {
1155
+            return $share->getPermissions() === 0;
1156
+        });
1157
+
1158
+        // Only get shares where the owner still exists
1159
+        $shares = array_filter($shares, function (IShare $share) {
1160
+            return $this->userManager->userExists($share->getShareOwner());
1161
+        });
1162
+
1163
+        return $shares;
1164
+    }
1165
+
1166
+    /**
1167
+     * @inheritdoc
1168
+     */
1169
+    public function getShareById($id, $recipient = null) {
1170
+        if ($id === null) {
1171
+            throw new ShareNotFound();
1172
+        }
1173
+
1174
+        list($providerId, $id) = $this->splitFullId($id);
1175
+
1176
+        try {
1177
+            $provider = $this->factory->getProvider($providerId);
1178
+        } catch (ProviderException $e) {
1179
+            throw new ShareNotFound();
1180
+        }
1181
+
1182
+        $share = $provider->getShareById($id, $recipient);
1183
+
1184
+        $this->checkExpireDate($share);
1185
+
1186
+        return $share;
1187
+    }
1188
+
1189
+    /**
1190
+     * Get all the shares for a given path
1191
+     *
1192
+     * @param \OCP\Files\Node $path
1193
+     * @param int $page
1194
+     * @param int $perPage
1195
+     *
1196
+     * @return Share[]
1197
+     */
1198
+    public function getSharesByPath(\OCP\Files\Node $path, $page=0, $perPage=50) {
1199
+        return [];
1200
+    }
1201
+
1202
+    /**
1203
+     * Get the share by token possible with password
1204
+     *
1205
+     * @param string $token
1206
+     * @return Share
1207
+     *
1208
+     * @throws ShareNotFound
1209
+     */
1210
+    public function getShareByToken($token) {
1211
+        // tokens can't be valid local user names
1212
+        if ($this->userManager->userExists($token)) {
1213
+            throw new ShareNotFound();
1214
+        }
1215
+        $share = null;
1216
+        try {
1217
+            if($this->shareApiAllowLinks()) {
1218
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK);
1219
+                $share = $provider->getShareByToken($token);
1220
+            }
1221
+        } catch (ProviderException $e) {
1222
+        } catch (ShareNotFound $e) {
1223
+        }
1224
+
1225
+
1226
+        // If it is not a link share try to fetch a federated share by token
1227
+        if ($share === null) {
1228
+            try {
1229
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_REMOTE);
1230
+                $share = $provider->getShareByToken($token);
1231
+            } catch (ProviderException $e) {
1232
+            } catch (ShareNotFound $e) {
1233
+            }
1234
+        }
1235
+
1236
+        // If it is not a link share try to fetch a mail share by token
1237
+        if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_EMAIL)) {
1238
+            try {
1239
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_EMAIL);
1240
+                $share = $provider->getShareByToken($token);
1241
+            } catch (ProviderException $e) {
1242
+            } catch (ShareNotFound $e) {
1243
+            }
1244
+        }
1245
+
1246
+        if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_CIRCLE)) {
1247
+            try {
1248
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_CIRCLE);
1249
+                $share = $provider->getShareByToken($token);
1250
+            } catch (ProviderException $e) {
1251
+            } catch (ShareNotFound $e) {
1252
+            }
1253
+        }
1254
+
1255
+        if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_ROOM)) {
1256
+            try {
1257
+                $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_ROOM);
1258
+                $share = $provider->getShareByToken($token);
1259
+            } catch (ProviderException $e) {
1260
+            } catch (ShareNotFound $e) {
1261
+            }
1262
+        }
1263
+
1264
+        if ($share === null) {
1265
+            throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1266
+        }
1267
+
1268
+        $this->checkExpireDate($share);
1269
+
1270
+        /*
1271 1271
 		 * Reduce the permissions for link shares if public upload is not enabled
1272 1272
 		 */
1273
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
1274
-			!$this->shareApiLinkAllowPublicUpload()) {
1275
-			$share->setPermissions($share->getPermissions() & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE));
1276
-		}
1277
-
1278
-		return $share;
1279
-	}
1280
-
1281
-	protected function checkExpireDate($share) {
1282
-		if ($share->getExpirationDate() !== null &&
1283
-			$share->getExpirationDate() <= new \DateTime()) {
1284
-			$this->deleteShare($share);
1285
-			throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1286
-		}
1287
-
1288
-	}
1289
-
1290
-	/**
1291
-	 * Verify the password of a public share
1292
-	 *
1293
-	 * @param \OCP\Share\IShare $share
1294
-	 * @param string $password
1295
-	 * @return bool
1296
-	 */
1297
-	public function checkPassword(\OCP\Share\IShare $share, $password) {
1298
-		$passwordProtected = $share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK
1299
-			|| $share->getShareType() !== \OCP\Share::SHARE_TYPE_EMAIL;
1300
-		if (!$passwordProtected) {
1301
-			//TODO maybe exception?
1302
-			return false;
1303
-		}
1304
-
1305
-		if ($password === null || $share->getPassword() === null) {
1306
-			return false;
1307
-		}
1308
-
1309
-		$newHash = '';
1310
-		if (!$this->hasher->verify($password, $share->getPassword(), $newHash)) {
1311
-			return false;
1312
-		}
1313
-
1314
-		if (!empty($newHash)) {
1315
-			$share->setPassword($newHash);
1316
-			$provider = $this->factory->getProviderForType($share->getShareType());
1317
-			$provider->update($share);
1318
-		}
1319
-
1320
-		return true;
1321
-	}
1322
-
1323
-	/**
1324
-	 * @inheritdoc
1325
-	 */
1326
-	public function userDeleted($uid) {
1327
-		$types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];
1328
-
1329
-		foreach ($types as $type) {
1330
-			try {
1331
-				$provider = $this->factory->getProviderForType($type);
1332
-			} catch (ProviderException $e) {
1333
-				continue;
1334
-			}
1335
-			$provider->userDeleted($uid, $type);
1336
-		}
1337
-	}
1338
-
1339
-	/**
1340
-	 * @inheritdoc
1341
-	 */
1342
-	public function groupDeleted($gid) {
1343
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1344
-		$provider->groupDeleted($gid);
1345
-	}
1346
-
1347
-	/**
1348
-	 * @inheritdoc
1349
-	 */
1350
-	public function userDeletedFromGroup($uid, $gid) {
1351
-		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1352
-		$provider->userDeletedFromGroup($uid, $gid);
1353
-	}
1354
-
1355
-	/**
1356
-	 * Get access list to a path. This means
1357
-	 * all the users that can access a given path.
1358
-	 *
1359
-	 * Consider:
1360
-	 * -root
1361
-	 * |-folder1 (23)
1362
-	 *  |-folder2 (32)
1363
-	 *   |-fileA (42)
1364
-	 *
1365
-	 * fileA is shared with user1 and user1@server1
1366
-	 * folder2 is shared with group2 (user4 is a member of group2)
1367
-	 * folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
1368
-	 *
1369
-	 * Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
1370
-	 * [
1371
-	 *  users  => [
1372
-	 *      'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
1373
-	 *      'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
1374
-	 *      'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
1375
-	 *  ],
1376
-	 *  remote => [
1377
-	 *      'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
1378
-	 *      'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
1379
-	 *  ],
1380
-	 *  public => bool
1381
-	 *  mail => bool
1382
-	 * ]
1383
-	 *
1384
-	 * The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
1385
-	 * [
1386
-	 *  users  => ['user1', 'user2', 'user4'],
1387
-	 *  remote => bool,
1388
-	 *  public => bool
1389
-	 *  mail => bool
1390
-	 * ]
1391
-	 *
1392
-	 * This is required for encryption/activity
1393
-	 *
1394
-	 * @param \OCP\Files\Node $path
1395
-	 * @param bool $recursive Should we check all parent folders as well
1396
-	 * @param bool $currentAccess Ensure the recipient has access to the file (e.g. did not unshare it)
1397
-	 * @return array
1398
-	 */
1399
-	public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
1400
-		$owner = $path->getOwner()->getUID();
1401
-
1402
-		if ($currentAccess) {
1403
-			$al = ['users' => [], 'remote' => [], 'public' => false];
1404
-		} else {
1405
-			$al = ['users' => [], 'remote' => false, 'public' => false];
1406
-		}
1407
-		if (!$this->userManager->userExists($owner)) {
1408
-			return $al;
1409
-		}
1410
-
1411
-		//Get node for the owner
1412
-		$userFolder = $this->rootFolder->getUserFolder($owner);
1413
-		if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) {
1414
-			$path = $userFolder->getById($path->getId())[0];
1415
-		}
1416
-
1417
-		$providers = $this->factory->getAllProviders();
1418
-
1419
-		/** @var Node[] $nodes */
1420
-		$nodes = [];
1421
-
1422
-
1423
-		if ($currentAccess) {
1424
-			$ownerPath = $path->getPath();
1425
-			$ownerPath = explode('/', $ownerPath, 4);
1426
-			if (count($ownerPath) < 4) {
1427
-				$ownerPath = '';
1428
-			} else {
1429
-				$ownerPath = $ownerPath[3];
1430
-			}
1431
-			$al['users'][$owner] = [
1432
-				'node_id' => $path->getId(),
1433
-				'node_path' => '/' . $ownerPath,
1434
-			];
1435
-		} else {
1436
-			$al['users'][] = $owner;
1437
-		}
1438
-
1439
-		// Collect all the shares
1440
-		while ($path->getPath() !== $userFolder->getPath()) {
1441
-			$nodes[] = $path;
1442
-			if (!$recursive) {
1443
-				break;
1444
-			}
1445
-			$path = $path->getParent();
1446
-		}
1447
-
1448
-		foreach ($providers as $provider) {
1449
-			$tmp = $provider->getAccessList($nodes, $currentAccess);
1450
-
1451
-			foreach ($tmp as $k => $v) {
1452
-				if (isset($al[$k])) {
1453
-					if (is_array($al[$k])) {
1454
-						if ($currentAccess) {
1455
-							$al[$k] += $v;
1456
-						} else {
1457
-							$al[$k] = array_merge($al[$k], $v);
1458
-							$al[$k] = array_unique($al[$k]);
1459
-							$al[$k] = array_values($al[$k]);
1460
-						}
1461
-					} else {
1462
-						$al[$k] = $al[$k] || $v;
1463
-					}
1464
-				} else {
1465
-					$al[$k] = $v;
1466
-				}
1467
-			}
1468
-		}
1469
-
1470
-		return $al;
1471
-	}
1472
-
1473
-	/**
1474
-	 * Create a new share
1475
-	 * @return \OCP\Share\IShare
1476
-	 */
1477
-	public function newShare() {
1478
-		return new \OC\Share20\Share($this->rootFolder, $this->userManager);
1479
-	}
1480
-
1481
-	/**
1482
-	 * Is the share API enabled
1483
-	 *
1484
-	 * @return bool
1485
-	 */
1486
-	public function shareApiEnabled() {
1487
-		return $this->config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes';
1488
-	}
1489
-
1490
-	/**
1491
-	 * Is public link sharing enabled
1492
-	 *
1493
-	 * @return bool
1494
-	 */
1495
-	public function shareApiAllowLinks() {
1496
-		return $this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes';
1497
-	}
1498
-
1499
-	/**
1500
-	 * Is password on public link requires
1501
-	 *
1502
-	 * @return bool
1503
-	 */
1504
-	public function shareApiLinkEnforcePassword() {
1505
-		return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes';
1506
-	}
1507
-
1508
-	/**
1509
-	 * Is default expire date enabled
1510
-	 *
1511
-	 * @return bool
1512
-	 */
1513
-	public function shareApiLinkDefaultExpireDate() {
1514
-		return $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
1515
-	}
1516
-
1517
-	/**
1518
-	 * Is default expire date enforced
1519
-	 *`
1520
-	 * @return bool
1521
-	 */
1522
-	public function shareApiLinkDefaultExpireDateEnforced() {
1523
-		return $this->shareApiLinkDefaultExpireDate() &&
1524
-			$this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
1525
-	}
1526
-
1527
-	/**
1528
-	 * Number of default expire days
1529
-	 *shareApiLinkAllowPublicUpload
1530
-	 * @return int
1531
-	 */
1532
-	public function shareApiLinkDefaultExpireDays() {
1533
-		return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1534
-	}
1535
-
1536
-	/**
1537
-	 * Allow public upload on link shares
1538
-	 *
1539
-	 * @return bool
1540
-	 */
1541
-	public function shareApiLinkAllowPublicUpload() {
1542
-		return $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
1543
-	}
1544
-
1545
-	/**
1546
-	 * check if user can only share with group members
1547
-	 * @return bool
1548
-	 */
1549
-	public function shareWithGroupMembersOnly() {
1550
-		return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
1551
-	}
1552
-
1553
-	/**
1554
-	 * Check if users can share with groups
1555
-	 * @return bool
1556
-	 */
1557
-	public function allowGroupSharing() {
1558
-		return $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes';
1559
-	}
1560
-
1561
-	/**
1562
-	 * Copied from \OC_Util::isSharingDisabledForUser
1563
-	 *
1564
-	 * TODO: Deprecate fuction from OC_Util
1565
-	 *
1566
-	 * @param string $userId
1567
-	 * @return bool
1568
-	 */
1569
-	public function sharingDisabledForUser($userId) {
1570
-		if ($userId === null) {
1571
-			return false;
1572
-		}
1573
-
1574
-		if (isset($this->sharingDisabledForUsersCache[$userId])) {
1575
-			return $this->sharingDisabledForUsersCache[$userId];
1576
-		}
1577
-
1578
-		if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
1579
-			$groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
1580
-			$excludedGroups = json_decode($groupsList);
1581
-			if (is_null($excludedGroups)) {
1582
-				$excludedGroups = explode(',', $groupsList);
1583
-				$newValue = json_encode($excludedGroups);
1584
-				$this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
1585
-			}
1586
-			$user = $this->userManager->get($userId);
1587
-			$usersGroups = $this->groupManager->getUserGroupIds($user);
1588
-			if (!empty($usersGroups)) {
1589
-				$remainingGroups = array_diff($usersGroups, $excludedGroups);
1590
-				// if the user is only in groups which are disabled for sharing then
1591
-				// sharing is also disabled for the user
1592
-				if (empty($remainingGroups)) {
1593
-					$this->sharingDisabledForUsersCache[$userId] = true;
1594
-					return true;
1595
-				}
1596
-			}
1597
-		}
1598
-
1599
-		$this->sharingDisabledForUsersCache[$userId] = false;
1600
-		return false;
1601
-	}
1602
-
1603
-	/**
1604
-	 * @inheritdoc
1605
-	 */
1606
-	public function outgoingServer2ServerSharesAllowed() {
1607
-		return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
1608
-	}
1609
-
1610
-	/**
1611
-	 * @inheritdoc
1612
-	 */
1613
-	public function outgoingServer2ServerGroupSharesAllowed() {
1614
-		return $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no') === 'yes';
1615
-	}
1616
-
1617
-	/**
1618
-	 * @inheritdoc
1619
-	 */
1620
-	public function shareProviderExists($shareType) {
1621
-		try {
1622
-			$this->factory->getProviderForType($shareType);
1623
-		} catch (ProviderException $e) {
1624
-			return false;
1625
-		}
1626
-
1627
-		return true;
1628
-	}
1273
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK &&
1274
+            !$this->shareApiLinkAllowPublicUpload()) {
1275
+            $share->setPermissions($share->getPermissions() & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE));
1276
+        }
1277
+
1278
+        return $share;
1279
+    }
1280
+
1281
+    protected function checkExpireDate($share) {
1282
+        if ($share->getExpirationDate() !== null &&
1283
+            $share->getExpirationDate() <= new \DateTime()) {
1284
+            $this->deleteShare($share);
1285
+            throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
1286
+        }
1287
+
1288
+    }
1289
+
1290
+    /**
1291
+     * Verify the password of a public share
1292
+     *
1293
+     * @param \OCP\Share\IShare $share
1294
+     * @param string $password
1295
+     * @return bool
1296
+     */
1297
+    public function checkPassword(\OCP\Share\IShare $share, $password) {
1298
+        $passwordProtected = $share->getShareType() !== \OCP\Share::SHARE_TYPE_LINK
1299
+            || $share->getShareType() !== \OCP\Share::SHARE_TYPE_EMAIL;
1300
+        if (!$passwordProtected) {
1301
+            //TODO maybe exception?
1302
+            return false;
1303
+        }
1304
+
1305
+        if ($password === null || $share->getPassword() === null) {
1306
+            return false;
1307
+        }
1308
+
1309
+        $newHash = '';
1310
+        if (!$this->hasher->verify($password, $share->getPassword(), $newHash)) {
1311
+            return false;
1312
+        }
1313
+
1314
+        if (!empty($newHash)) {
1315
+            $share->setPassword($newHash);
1316
+            $provider = $this->factory->getProviderForType($share->getShareType());
1317
+            $provider->update($share);
1318
+        }
1319
+
1320
+        return true;
1321
+    }
1322
+
1323
+    /**
1324
+     * @inheritdoc
1325
+     */
1326
+    public function userDeleted($uid) {
1327
+        $types = [\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_EMAIL];
1328
+
1329
+        foreach ($types as $type) {
1330
+            try {
1331
+                $provider = $this->factory->getProviderForType($type);
1332
+            } catch (ProviderException $e) {
1333
+                continue;
1334
+            }
1335
+            $provider->userDeleted($uid, $type);
1336
+        }
1337
+    }
1338
+
1339
+    /**
1340
+     * @inheritdoc
1341
+     */
1342
+    public function groupDeleted($gid) {
1343
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1344
+        $provider->groupDeleted($gid);
1345
+    }
1346
+
1347
+    /**
1348
+     * @inheritdoc
1349
+     */
1350
+    public function userDeletedFromGroup($uid, $gid) {
1351
+        $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
1352
+        $provider->userDeletedFromGroup($uid, $gid);
1353
+    }
1354
+
1355
+    /**
1356
+     * Get access list to a path. This means
1357
+     * all the users that can access a given path.
1358
+     *
1359
+     * Consider:
1360
+     * -root
1361
+     * |-folder1 (23)
1362
+     *  |-folder2 (32)
1363
+     *   |-fileA (42)
1364
+     *
1365
+     * fileA is shared with user1 and user1@server1
1366
+     * folder2 is shared with group2 (user4 is a member of group2)
1367
+     * folder1 is shared with user2 (renamed to "folder (1)") and user2@server2
1368
+     *
1369
+     * Then the access list to '/folder1/folder2/fileA' with $currentAccess is:
1370
+     * [
1371
+     *  users  => [
1372
+     *      'user1' => ['node_id' => 42, 'node_path' => '/fileA'],
1373
+     *      'user4' => ['node_id' => 32, 'node_path' => '/folder2'],
1374
+     *      'user2' => ['node_id' => 23, 'node_path' => '/folder (1)'],
1375
+     *  ],
1376
+     *  remote => [
1377
+     *      'user1@server1' => ['node_id' => 42, 'token' => 'SeCr3t'],
1378
+     *      'user2@server2' => ['node_id' => 23, 'token' => 'FooBaR'],
1379
+     *  ],
1380
+     *  public => bool
1381
+     *  mail => bool
1382
+     * ]
1383
+     *
1384
+     * The access list to '/folder1/folder2/fileA' **without** $currentAccess is:
1385
+     * [
1386
+     *  users  => ['user1', 'user2', 'user4'],
1387
+     *  remote => bool,
1388
+     *  public => bool
1389
+     *  mail => bool
1390
+     * ]
1391
+     *
1392
+     * This is required for encryption/activity
1393
+     *
1394
+     * @param \OCP\Files\Node $path
1395
+     * @param bool $recursive Should we check all parent folders as well
1396
+     * @param bool $currentAccess Ensure the recipient has access to the file (e.g. did not unshare it)
1397
+     * @return array
1398
+     */
1399
+    public function getAccessList(\OCP\Files\Node $path, $recursive = true, $currentAccess = false) {
1400
+        $owner = $path->getOwner()->getUID();
1401
+
1402
+        if ($currentAccess) {
1403
+            $al = ['users' => [], 'remote' => [], 'public' => false];
1404
+        } else {
1405
+            $al = ['users' => [], 'remote' => false, 'public' => false];
1406
+        }
1407
+        if (!$this->userManager->userExists($owner)) {
1408
+            return $al;
1409
+        }
1410
+
1411
+        //Get node for the owner
1412
+        $userFolder = $this->rootFolder->getUserFolder($owner);
1413
+        if ($path->getId() !== $userFolder->getId() && !$userFolder->isSubNode($path)) {
1414
+            $path = $userFolder->getById($path->getId())[0];
1415
+        }
1416
+
1417
+        $providers = $this->factory->getAllProviders();
1418
+
1419
+        /** @var Node[] $nodes */
1420
+        $nodes = [];
1421
+
1422
+
1423
+        if ($currentAccess) {
1424
+            $ownerPath = $path->getPath();
1425
+            $ownerPath = explode('/', $ownerPath, 4);
1426
+            if (count($ownerPath) < 4) {
1427
+                $ownerPath = '';
1428
+            } else {
1429
+                $ownerPath = $ownerPath[3];
1430
+            }
1431
+            $al['users'][$owner] = [
1432
+                'node_id' => $path->getId(),
1433
+                'node_path' => '/' . $ownerPath,
1434
+            ];
1435
+        } else {
1436
+            $al['users'][] = $owner;
1437
+        }
1438
+
1439
+        // Collect all the shares
1440
+        while ($path->getPath() !== $userFolder->getPath()) {
1441
+            $nodes[] = $path;
1442
+            if (!$recursive) {
1443
+                break;
1444
+            }
1445
+            $path = $path->getParent();
1446
+        }
1447
+
1448
+        foreach ($providers as $provider) {
1449
+            $tmp = $provider->getAccessList($nodes, $currentAccess);
1450
+
1451
+            foreach ($tmp as $k => $v) {
1452
+                if (isset($al[$k])) {
1453
+                    if (is_array($al[$k])) {
1454
+                        if ($currentAccess) {
1455
+                            $al[$k] += $v;
1456
+                        } else {
1457
+                            $al[$k] = array_merge($al[$k], $v);
1458
+                            $al[$k] = array_unique($al[$k]);
1459
+                            $al[$k] = array_values($al[$k]);
1460
+                        }
1461
+                    } else {
1462
+                        $al[$k] = $al[$k] || $v;
1463
+                    }
1464
+                } else {
1465
+                    $al[$k] = $v;
1466
+                }
1467
+            }
1468
+        }
1469
+
1470
+        return $al;
1471
+    }
1472
+
1473
+    /**
1474
+     * Create a new share
1475
+     * @return \OCP\Share\IShare
1476
+     */
1477
+    public function newShare() {
1478
+        return new \OC\Share20\Share($this->rootFolder, $this->userManager);
1479
+    }
1480
+
1481
+    /**
1482
+     * Is the share API enabled
1483
+     *
1484
+     * @return bool
1485
+     */
1486
+    public function shareApiEnabled() {
1487
+        return $this->config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes';
1488
+    }
1489
+
1490
+    /**
1491
+     * Is public link sharing enabled
1492
+     *
1493
+     * @return bool
1494
+     */
1495
+    public function shareApiAllowLinks() {
1496
+        return $this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes';
1497
+    }
1498
+
1499
+    /**
1500
+     * Is password on public link requires
1501
+     *
1502
+     * @return bool
1503
+     */
1504
+    public function shareApiLinkEnforcePassword() {
1505
+        return $this->config->getAppValue('core', 'shareapi_enforce_links_password', 'no') === 'yes';
1506
+    }
1507
+
1508
+    /**
1509
+     * Is default expire date enabled
1510
+     *
1511
+     * @return bool
1512
+     */
1513
+    public function shareApiLinkDefaultExpireDate() {
1514
+        return $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no') === 'yes';
1515
+    }
1516
+
1517
+    /**
1518
+     * Is default expire date enforced
1519
+     *`
1520
+     * @return bool
1521
+     */
1522
+    public function shareApiLinkDefaultExpireDateEnforced() {
1523
+        return $this->shareApiLinkDefaultExpireDate() &&
1524
+            $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes';
1525
+    }
1526
+
1527
+    /**
1528
+     * Number of default expire days
1529
+     *shareApiLinkAllowPublicUpload
1530
+     * @return int
1531
+     */
1532
+    public function shareApiLinkDefaultExpireDays() {
1533
+        return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1534
+    }
1535
+
1536
+    /**
1537
+     * Allow public upload on link shares
1538
+     *
1539
+     * @return bool
1540
+     */
1541
+    public function shareApiLinkAllowPublicUpload() {
1542
+        return $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes') === 'yes';
1543
+    }
1544
+
1545
+    /**
1546
+     * check if user can only share with group members
1547
+     * @return bool
1548
+     */
1549
+    public function shareWithGroupMembersOnly() {
1550
+        return $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
1551
+    }
1552
+
1553
+    /**
1554
+     * Check if users can share with groups
1555
+     * @return bool
1556
+     */
1557
+    public function allowGroupSharing() {
1558
+        return $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes') === 'yes';
1559
+    }
1560
+
1561
+    /**
1562
+     * Copied from \OC_Util::isSharingDisabledForUser
1563
+     *
1564
+     * TODO: Deprecate fuction from OC_Util
1565
+     *
1566
+     * @param string $userId
1567
+     * @return bool
1568
+     */
1569
+    public function sharingDisabledForUser($userId) {
1570
+        if ($userId === null) {
1571
+            return false;
1572
+        }
1573
+
1574
+        if (isset($this->sharingDisabledForUsersCache[$userId])) {
1575
+            return $this->sharingDisabledForUsersCache[$userId];
1576
+        }
1577
+
1578
+        if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
1579
+            $groupsList = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
1580
+            $excludedGroups = json_decode($groupsList);
1581
+            if (is_null($excludedGroups)) {
1582
+                $excludedGroups = explode(',', $groupsList);
1583
+                $newValue = json_encode($excludedGroups);
1584
+                $this->config->setAppValue('core', 'shareapi_exclude_groups_list', $newValue);
1585
+            }
1586
+            $user = $this->userManager->get($userId);
1587
+            $usersGroups = $this->groupManager->getUserGroupIds($user);
1588
+            if (!empty($usersGroups)) {
1589
+                $remainingGroups = array_diff($usersGroups, $excludedGroups);
1590
+                // if the user is only in groups which are disabled for sharing then
1591
+                // sharing is also disabled for the user
1592
+                if (empty($remainingGroups)) {
1593
+                    $this->sharingDisabledForUsersCache[$userId] = true;
1594
+                    return true;
1595
+                }
1596
+            }
1597
+        }
1598
+
1599
+        $this->sharingDisabledForUsersCache[$userId] = false;
1600
+        return false;
1601
+    }
1602
+
1603
+    /**
1604
+     * @inheritdoc
1605
+     */
1606
+    public function outgoingServer2ServerSharesAllowed() {
1607
+        return $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
1608
+    }
1609
+
1610
+    /**
1611
+     * @inheritdoc
1612
+     */
1613
+    public function outgoingServer2ServerGroupSharesAllowed() {
1614
+        return $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no') === 'yes';
1615
+    }
1616
+
1617
+    /**
1618
+     * @inheritdoc
1619
+     */
1620
+    public function shareProviderExists($shareType) {
1621
+        try {
1622
+            $this->factory->getProviderForType($shareType);
1623
+        } catch (ProviderException $e) {
1624
+            return false;
1625
+        }
1626
+
1627
+        return true;
1628
+    }
1629 1629
 
1630 1630
 }
Please login to merge, or discard this patch.
Spacing   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -226,7 +226,7 @@  discard block
 block discarded – undo
226 226
 			if ($share->getSharedWith() === null) {
227 227
 				throw new \InvalidArgumentException('SharedWith should not be empty');
228 228
 			}
229
-		}  else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
229
+		} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
230 230
 			if ($share->getSharedWith() === null) {
231 231
 				throw new \InvalidArgumentException('SharedWith should not be empty');
232 232
 			}
@@ -362,7 +362,7 @@  discard block
 block discarded – undo
362 362
 
363 363
 		if ($fullId === null && $expirationDate === null && $this->shareApiLinkDefaultExpireDate()) {
364 364
 			$expirationDate = new \DateTime();
365
-			$expirationDate->setTime(0,0,0);
365
+			$expirationDate->setTime(0, 0, 0);
366 366
 			$expirationDate->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
367 367
 		}
368 368
 
@@ -374,7 +374,7 @@  discard block
 block discarded – undo
374 374
 
375 375
 			$date = new \DateTime();
376 376
 			$date->setTime(0, 0, 0);
377
-			$date->add(new \DateInterval('P' . $this->shareApiLinkDefaultExpireDays() . 'D'));
377
+			$date->add(new \DateInterval('P'.$this->shareApiLinkDefaultExpireDays().'D'));
378 378
 			if ($date < $expirationDate) {
379 379
 				$message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiLinkDefaultExpireDays()]);
380 380
 				throw new GenericShareException($message, $message, 404);
@@ -427,7 +427,7 @@  discard block
 block discarded – undo
427 427
 		 */
428 428
 		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_USER);
429 429
 		$existingShares = $provider->getSharesByPath($share->getNode());
430
-		foreach($existingShares as $existingShare) {
430
+		foreach ($existingShares as $existingShare) {
431 431
 			// Ignore if it is the same share
432 432
 			try {
433 433
 				if ($existingShare->getFullId() === $share->getFullId()) {
@@ -484,7 +484,7 @@  discard block
 block discarded – undo
484 484
 		 */
485 485
 		$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_GROUP);
486 486
 		$existingShares = $provider->getSharesByPath($share->getNode());
487
-		foreach($existingShares as $existingShare) {
487
+		foreach ($existingShares as $existingShare) {
488 488
 			try {
489 489
 				if ($existingShare->getFullId() === $share->getFullId()) {
490 490
 					continue;
@@ -553,7 +553,7 @@  discard block
 block discarded – undo
553 553
 		// Make sure that we do not share a path that contains a shared mountpoint
554 554
 		if ($path instanceof \OCP\Files\Folder) {
555 555
 			$mounts = $this->mountManager->findIn($path->getPath());
556
-			foreach($mounts as $mount) {
556
+			foreach ($mounts as $mount) {
557 557
 				if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
558 558
 					throw new \InvalidArgumentException('Path contains files shared with you');
559 559
 				}
@@ -601,7 +601,7 @@  discard block
 block discarded – undo
601 601
 		$storage = $share->getNode()->getStorage();
602 602
 		if ($storage->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
603 603
 			$parent = $share->getNode()->getParent();
604
-			while($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
604
+			while ($parent->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) {
605 605
 				$parent = $parent->getParent();
606 606
 			}
607 607
 			$share->setShareOwner($parent->getOwner()->getUID());
@@ -654,7 +654,7 @@  discard block
 block discarded – undo
654 654
 		}
655 655
 
656 656
 		// Generate the target
657
-		$target = $this->config->getSystemValue('share_folder', '/') .'/'. $share->getNode()->getName();
657
+		$target = $this->config->getSystemValue('share_folder', '/').'/'.$share->getNode()->getName();
658 658
 		$target = \OC\Files\Filesystem::normalizePath($target);
659 659
 		$share->setTarget($target);
660 660
 
@@ -677,7 +677,7 @@  discard block
 block discarded – undo
677 677
 
678 678
 		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
679 679
 			$mailSend = $share->getMailSend();
680
-			if($mailSend === true) {
680
+			if ($mailSend === true) {
681 681
 				$user = $this->userManager->get($share->getSharedWith());
682 682
 				if ($user !== null) {
683 683
 					$emailAddress = $user->getEMailAddress();
@@ -692,12 +692,12 @@  discard block
 block discarded – undo
692 692
 							$emailAddress,
693 693
 							$share->getExpirationDate()
694 694
 						);
695
-						$this->logger->debug('Send share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']);
695
+						$this->logger->debug('Send share notification to '.$emailAddress.' for share with ID '.$share->getId(), ['app' => 'share']);
696 696
 					} else {
697
-						$this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']);
697
+						$this->logger->debug('Share notification not send to '.$share->getSharedWith().' because email address is not set.', ['app' => 'share']);
698 698
 					}
699 699
 				} else {
700
-					$this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']);
700
+					$this->logger->debug('Share notification not send to '.$share->getSharedWith().' because user could not be found.', ['app' => 'share']);
701 701
 				}
702 702
 			} else {
703 703
 				$this->logger->debug('Share notification not send because mailsend is false.', ['app' => 'share']);
@@ -741,7 +741,7 @@  discard block
 block discarded – undo
741 741
 		$text = $l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
742 742
 
743 743
 		$emailTemplate->addBodyText(
744
-			htmlspecialchars($text . ' ' . $l->t('Click the button below to open it.')),
744
+			htmlspecialchars($text.' '.$l->t('Click the button below to open it.')),
745 745
 			$text
746 746
 		);
747 747
 		$emailTemplate->addBodyButton(
@@ -765,9 +765,9 @@  discard block
 block discarded – undo
765 765
 		// The "Reply-To" is set to the sharer if an mail address is configured
766 766
 		// also the default footer contains a "Do not reply" which needs to be adjusted.
767 767
 		$initiatorEmail = $initiatorUser->getEMailAddress();
768
-		if($initiatorEmail !== null) {
768
+		if ($initiatorEmail !== null) {
769 769
 			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
770
-			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
770
+			$emailTemplate->addFooter($instanceName.($this->defaults->getSlogan() !== '' ? ' - '.$this->defaults->getSlogan() : ''));
771 771
 		} else {
772 772
 			$emailTemplate->addFooter();
773 773
 		}
@@ -986,7 +986,7 @@  discard block
 block discarded – undo
986 986
 	 * @param string $recipientId
987 987
 	 */
988 988
 	public function deleteFromSelf(\OCP\Share\IShare $share, $recipientId) {
989
-		list($providerId, ) = $this->splitFullId($share->getFullId());
989
+		list($providerId,) = $this->splitFullId($share->getFullId());
990 990
 		$provider = $this->factory->getProvider($providerId);
991 991
 
992 992
 		$provider->deleteFromSelf($share, $recipientId);
@@ -995,7 +995,7 @@  discard block
 block discarded – undo
995 995
 	}
996 996
 
997 997
 	public function restoreShare(IShare $share, string $recipientId): IShare {
998
-		list($providerId, ) = $this->splitFullId($share->getFullId());
998
+		list($providerId,) = $this->splitFullId($share->getFullId());
999 999
 		$provider = $this->factory->getProvider($providerId);
1000 1000
 
1001 1001
 		return $provider->restore($share, $recipientId);
@@ -1016,7 +1016,7 @@  discard block
 block discarded – undo
1016 1016
 		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
1017 1017
 			$sharedWith = $this->groupManager->get($share->getSharedWith());
1018 1018
 			if (is_null($sharedWith)) {
1019
-				throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
1019
+				throw new \InvalidArgumentException('Group "'.$share->getSharedWith().'" does not exist');
1020 1020
 			}
1021 1021
 			$recipient = $this->userManager->get($recipientId);
1022 1022
 			if (!$sharedWith->inGroup($recipient)) {
@@ -1024,7 +1024,7 @@  discard block
 block discarded – undo
1024 1024
 			}
1025 1025
 		}
1026 1026
 
1027
-		list($providerId, ) = $this->splitFullId($share->getFullId());
1027
+		list($providerId,) = $this->splitFullId($share->getFullId());
1028 1028
 		$provider = $this->factory->getProvider($providerId);
1029 1029
 
1030 1030
 		$provider->move($share, $recipientId);
@@ -1071,7 +1071,7 @@  discard block
 block discarded – undo
1071 1071
 
1072 1072
 		$shares2 = [];
1073 1073
 
1074
-		while(true) {
1074
+		while (true) {
1075 1075
 			$added = 0;
1076 1076
 			foreach ($shares as $share) {
1077 1077
 
@@ -1156,7 +1156,7 @@  discard block
 block discarded – undo
1156 1156
 		});
1157 1157
 
1158 1158
 		// Only get shares where the owner still exists
1159
-		$shares = array_filter($shares, function (IShare $share) {
1159
+		$shares = array_filter($shares, function(IShare $share) {
1160 1160
 			return $this->userManager->userExists($share->getShareOwner());
1161 1161
 		});
1162 1162
 
@@ -1195,7 +1195,7 @@  discard block
 block discarded – undo
1195 1195
 	 *
1196 1196
 	 * @return Share[]
1197 1197
 	 */
1198
-	public function getSharesByPath(\OCP\Files\Node $path, $page=0, $perPage=50) {
1198
+	public function getSharesByPath(\OCP\Files\Node $path, $page = 0, $perPage = 50) {
1199 1199
 		return [];
1200 1200
 	}
1201 1201
 
@@ -1214,7 +1214,7 @@  discard block
 block discarded – undo
1214 1214
 		}
1215 1215
 		$share = null;
1216 1216
 		try {
1217
-			if($this->shareApiAllowLinks()) {
1217
+			if ($this->shareApiAllowLinks()) {
1218 1218
 				$provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_LINK);
1219 1219
 				$share = $provider->getShareByToken($token);
1220 1220
 			}
@@ -1430,7 +1430,7 @@  discard block
 block discarded – undo
1430 1430
 			}
1431 1431
 			$al['users'][$owner] = [
1432 1432
 				'node_id' => $path->getId(),
1433
-				'node_path' => '/' . $ownerPath,
1433
+				'node_path' => '/'.$ownerPath,
1434 1434
 			];
1435 1435
 		} else {
1436 1436
 			$al['users'][] = $owner;
@@ -1530,7 +1530,7 @@  discard block
 block discarded – undo
1530 1530
 	 * @return int
1531 1531
 	 */
1532 1532
 	public function shareApiLinkDefaultExpireDays() {
1533
-		return (int)$this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1533
+		return (int) $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1534 1534
 	}
1535 1535
 
1536 1536
 	/**
Please login to merge, or discard this patch.
lib/private/Share/Share.php 2 patches
Indentation   +2067 added lines, -2067 removed lines patch added patch discarded remove patch
@@ -53,2081 +53,2081 @@
 block discarded – undo
53 53
  */
54 54
 class Share extends Constants {
55 55
 
56
-	/** CRUDS permissions (Create, Read, Update, Delete, Share) using a bitmask
57
-	 * Construct permissions for share() and setPermissions with Or (|) e.g.
58
-	 * Give user read and update permissions: PERMISSION_READ | PERMISSION_UPDATE
59
-	 *
60
-	 * Check if permission is granted with And (&) e.g. Check if delete is
61
-	 * granted: if ($permissions & PERMISSION_DELETE)
62
-	 *
63
-	 * Remove permissions with And (&) and Not (~) e.g. Remove the update
64
-	 * permission: $permissions &= ~PERMISSION_UPDATE
65
-	 *
66
-	 * Apps are required to handle permissions on their own, this class only
67
-	 * stores and manages the permissions of shares
68
-	 * @see lib/public/constants.php
69
-	 */
70
-
71
-	/**
72
-	 * Register a sharing backend class that implements OCP\Share_Backend for an item type
73
-	 * @param string $itemType Item type
74
-	 * @param string $class Backend class
75
-	 * @param string $collectionOf (optional) Depends on item type
76
-	 * @param array $supportedFileExtensions (optional) List of supported file extensions if this item type depends on files
77
-	 * @return boolean true if backend is registered or false if error
78
-	 */
79
-	public static function registerBackend($itemType, $class, $collectionOf = null, $supportedFileExtensions = null) {
80
-		if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_enabled', 'yes') == 'yes') {
81
-			if (!isset(self::$backendTypes[$itemType])) {
82
-				self::$backendTypes[$itemType] = array(
83
-					'class' => $class,
84
-					'collectionOf' => $collectionOf,
85
-					'supportedFileExtensions' => $supportedFileExtensions
86
-				);
87
-				if(count(self::$backendTypes) === 1) {
88
-					Util::addScript('core', 'merged-share-backend');
89
-				}
90
-				return true;
91
-			}
92
-			\OCP\Util::writeLog('OCP\Share',
93
-				'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class']
94
-				.' is already registered for '.$itemType,
95
-				ILogger::WARN);
96
-		}
97
-		return false;
98
-	}
99
-
100
-	/**
101
-	 * Get the items of item type shared with the current user
102
-	 * @param string $itemType
103
-	 * @param int $format (optional) Format type must be defined by the backend
104
-	 * @param mixed $parameters (optional)
105
-	 * @param int $limit Number of items to return (optional) Returns all by default
106
-	 * @param boolean $includeCollections (optional)
107
-	 * @return mixed Return depends on format
108
-	 */
109
-	public static function getItemsSharedWith($itemType, $format = self::FORMAT_NONE,
110
-											  $parameters = null, $limit = -1, $includeCollections = false) {
111
-		return self::getItems($itemType, null, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format,
112
-			$parameters, $limit, $includeCollections);
113
-	}
114
-
115
-	/**
116
-	 * Get the items of item type shared with a user
117
-	 * @param string $itemType
118
-	 * @param string $user id for which user we want the shares
119
-	 * @param int $format (optional) Format type must be defined by the backend
120
-	 * @param mixed $parameters (optional)
121
-	 * @param int $limit Number of items to return (optional) Returns all by default
122
-	 * @param boolean $includeCollections (optional)
123
-	 * @return mixed Return depends on format
124
-	 */
125
-	public static function getItemsSharedWithUser($itemType, $user, $format = self::FORMAT_NONE,
126
-												  $parameters = null, $limit = -1, $includeCollections = false) {
127
-		return self::getItems($itemType, null, self::$shareTypeUserAndGroups, $user, null, $format,
128
-			$parameters, $limit, $includeCollections);
129
-	}
130
-
131
-	/**
132
-	 * Get the item of item type shared with a given user by source
133
-	 * @param string $itemType
134
-	 * @param string $itemSource
135
-	 * @param string $user User to whom the item was shared
136
-	 * @param string $owner Owner of the share
137
-	 * @param int $shareType only look for a specific share type
138
-	 * @return array Return list of items with file_target, permissions and expiration
139
-	 */
140
-	public static function getItemSharedWithUser($itemType, $itemSource, $user, $owner = null, $shareType = null) {
141
-		$shares = array();
142
-		$fileDependent = false;
143
-
144
-		$where = 'WHERE';
145
-		$fileDependentWhere = '';
146
-		if ($itemType === 'file' || $itemType === 'folder') {
147
-			$fileDependent = true;
148
-			$column = 'file_source';
149
-			$fileDependentWhere = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` ';
150
-			$fileDependentWhere .= 'INNER JOIN `*PREFIX*storages` ON `numeric_id` = `*PREFIX*filecache`.`storage` ';
151
-		} else {
152
-			$column = 'item_source';
153
-		}
154
-
155
-		$select = self::createSelectStatement(self::FORMAT_NONE, $fileDependent);
156
-
157
-		$where .= ' `' . $column . '` = ? AND `item_type` = ? ';
158
-		$arguments = array($itemSource, $itemType);
159
-		// for link shares $user === null
160
-		if ($user !== null) {
161
-			$where .= ' AND `share_with` = ? ';
162
-			$arguments[] = $user;
163
-		}
164
-
165
-		if ($shareType !== null) {
166
-			$where .= ' AND `share_type` = ? ';
167
-			$arguments[] = $shareType;
168
-		}
169
-
170
-		if ($owner !== null) {
171
-			$where .= ' AND `uid_owner` = ? ';
172
-			$arguments[] = $owner;
173
-		}
174
-
175
-		$query = \OC_DB::prepare('SELECT ' . $select . ' FROM `*PREFIX*share` '. $fileDependentWhere . $where);
176
-
177
-		$result = \OC_DB::executeAudited($query, $arguments);
178
-
179
-		while ($row = $result->fetchRow()) {
180
-			if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
181
-				continue;
182
-			}
183
-			if ($fileDependent && (int)$row['file_parent'] === -1) {
184
-				// if it is a mount point we need to get the path from the mount manager
185
-				$mountManager = \OC\Files\Filesystem::getMountManager();
186
-				$mountPoint = $mountManager->findByStorageId($row['storage_id']);
187
-				if (!empty($mountPoint)) {
188
-					$path = $mountPoint[0]->getMountPoint();
189
-					$path = trim($path, '/');
190
-					$path = substr($path, strlen($owner) + 1); //normalize path to 'files/foo.txt`
191
-					$row['path'] = $path;
192
-				} else {
193
-					\OC::$server->getLogger()->warning(
194
-						'Could not resolve mount point for ' . $row['storage_id'],
195
-						['app' => 'OCP\Share']
196
-					);
197
-				}
198
-			}
199
-			$shares[] = $row;
200
-		}
201
-
202
-		//if didn't found a result than let's look for a group share.
203
-		if(empty($shares) && $user !== null) {
204
-			$userObject = \OC::$server->getUserManager()->get($user);
205
-			$groups = [];
206
-			if ($userObject) {
207
-				$groups = \OC::$server->getGroupManager()->getUserGroupIds($userObject);
208
-			}
209
-
210
-			if (!empty($groups)) {
211
-				$where = $fileDependentWhere . ' WHERE `' . $column . '` = ? AND `item_type` = ? AND `share_with` in (?)';
212
-				$arguments = array($itemSource, $itemType, $groups);
213
-				$types = array(null, null, IQueryBuilder::PARAM_STR_ARRAY);
214
-
215
-				if ($owner !== null) {
216
-					$where .= ' AND `uid_owner` = ?';
217
-					$arguments[] = $owner;
218
-					$types[] = null;
219
-				}
220
-
221
-				// TODO: inject connection, hopefully one day in the future when this
222
-				// class isn't static anymore...
223
-				$conn = \OC::$server->getDatabaseConnection();
224
-				$result = $conn->executeQuery(
225
-					'SELECT ' . $select . ' FROM `*PREFIX*share` ' . $where,
226
-					$arguments,
227
-					$types
228
-				);
229
-
230
-				while ($row = $result->fetch()) {
231
-					$shares[] = $row;
232
-				}
233
-			}
234
-		}
235
-
236
-		return $shares;
237
-
238
-	}
239
-
240
-	/**
241
-	 * Get the item of item type shared with the current user by source
242
-	 * @param string $itemType
243
-	 * @param string $itemSource
244
-	 * @param int $format (optional) Format type must be defined by the backend
245
-	 * @param mixed $parameters
246
-	 * @param boolean $includeCollections
247
-	 * @param string $shareWith (optional) define against which user should be checked, default: current user
248
-	 * @return array
249
-	 */
250
-	public static function getItemSharedWithBySource($itemType, $itemSource, $format = self::FORMAT_NONE,
251
-													 $parameters = null, $includeCollections = false, $shareWith = null) {
252
-		$shareWith = ($shareWith === null) ? \OC_User::getUser() : $shareWith;
253
-		return self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, $shareWith, null, $format,
254
-			$parameters, 1, $includeCollections, true);
255
-	}
256
-
257
-	/**
258
-	 * Based on the given token the share information will be returned - password protected shares will be verified
259
-	 * @param string $token
260
-	 * @param bool $checkPasswordProtection
261
-	 * @return array|boolean false will be returned in case the token is unknown or unauthorized
262
-	 */
263
-	public static function getShareByToken($token, $checkPasswordProtection = true) {
264
-		$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `token` = ?', 1);
265
-		$result = $query->execute(array($token));
266
-		if ($result === false) {
267
-			\OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage() . ', token=' . $token, ILogger::ERROR);
268
-		}
269
-		$row = $result->fetchRow();
270
-		if ($row === false) {
271
-			return false;
272
-		}
273
-		if (is_array($row) and self::expireItem($row)) {
274
-			return false;
275
-		}
276
-
277
-		// password protected shares need to be authenticated
278
-		if ($checkPasswordProtection && !\OC\Share\Share::checkPasswordProtectedShare($row)) {
279
-			return false;
280
-		}
281
-
282
-		return $row;
283
-	}
284
-
285
-	/**
286
-	 * Get the shared items of item type owned by the current user
287
-	 * @param string $itemType
288
-	 * @param int $format (optional) Format type must be defined by the backend
289
-	 * @param mixed $parameters
290
-	 * @param int $limit Number of items to return (optional) Returns all by default
291
-	 * @param boolean $includeCollections
292
-	 * @return mixed Return depends on format
293
-	 */
294
-	public static function getItemsShared($itemType, $format = self::FORMAT_NONE, $parameters = null,
295
-										  $limit = -1, $includeCollections = false) {
296
-		return self::getItems($itemType, null, null, null, \OC_User::getUser(), $format,
297
-			$parameters, $limit, $includeCollections);
298
-	}
299
-
300
-	/**
301
-	 * Get the shared item of item type owned by the current user
302
-	 * @param string $itemType
303
-	 * @param string $itemSource
304
-	 * @param int $format (optional) Format type must be defined by the backend
305
-	 * @param mixed $parameters
306
-	 * @param boolean $includeCollections
307
-	 * @return mixed Return depends on format
308
-	 */
309
-	public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE,
310
-										 $parameters = null, $includeCollections = false) {
311
-		return self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), $format,
312
-			$parameters, -1, $includeCollections);
313
-	}
314
-
315
-	/**
316
-	 * Share an item with a user, group, or via private link
317
-	 * @param string $itemType
318
-	 * @param string $itemSource
319
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
320
-	 * @param string $shareWith User or group the item is being shared with
321
-	 * @param int $permissions CRUDS
322
-	 * @param string $itemSourceName
323
-	 * @param \DateTime|null $expirationDate
324
-	 * @param bool|null $passwordChanged
325
-	 * @return boolean|string Returns true on success or false on failure, Returns token on success for links
326
-	 * @throws \OC\HintException when the share type is remote and the shareWith is invalid
327
-	 * @throws \Exception
328
-	 * @since 5.0.0 - parameter $itemSourceName was added in 6.0.0, parameter $expirationDate was added in 7.0.0, parameter $passwordChanged added in 9.0.0
329
-	 * @deprecated 14.0.0 TESTS ONLY - this methods is as of 2018-06 only used by tests
330
-	 */
331
-	public static function shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions, $itemSourceName = null, \DateTime $expirationDate = null, $passwordChanged = null) {
332
-
333
-		$backend = self::getBackend($itemType);
334
-		$l = \OC::$server->getL10N('lib');
335
-
336
-		if ($backend->isShareTypeAllowed($shareType) === false) {
337
-			$message = 'Sharing %s failed, because the backend does not allow shares from type %i';
338
-			$message_t = $l->t('Sharing %s failed, because the backend does not allow shares from type %i', array($itemSourceName, $shareType));
339
-			\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareType), ILogger::DEBUG);
340
-			throw new \Exception($message_t);
341
-		}
342
-
343
-		$uidOwner = \OC_User::getUser();
344
-		$shareWithinGroupOnly = self::shareWithGroupMembersOnly();
345
-
346
-		if (is_null($itemSourceName)) {
347
-			$itemSourceName = $itemSource;
348
-		}
349
-		$itemName = $itemSourceName;
350
-
351
-		// check if file can be shared
352
-		if ($itemType === 'file' or $itemType === 'folder') {
353
-			$path = \OC\Files\Filesystem::getPath($itemSource);
354
-			$itemName = $path;
355
-
356
-			// verify that the file exists before we try to share it
357
-			if (!$path) {
358
-				$message = 'Sharing %s failed, because the file does not exist';
359
-				$message_t = $l->t('Sharing %s failed, because the file does not exist', array($itemSourceName));
360
-				\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
361
-				throw new \Exception($message_t);
362
-			}
363
-			// verify that the user has share permission
364
-			if (!\OC\Files\Filesystem::isSharable($path) || \OCP\Util::isSharingDisabledForUser()) {
365
-				$message = 'You are not allowed to share %s';
366
-				$message_t = $l->t('You are not allowed to share %s', [$path]);
367
-				\OCP\Util::writeLog('OCP\Share', sprintf($message, $path), ILogger::DEBUG);
368
-				throw new \Exception($message_t);
369
-			}
370
-		}
371
-
372
-		//verify that we don't share a folder which already contains a share mount point
373
-		if ($itemType === 'folder') {
374
-			$path = '/' . $uidOwner . '/files' . \OC\Files\Filesystem::getPath($itemSource) . '/';
375
-			$mountManager = \OC\Files\Filesystem::getMountManager();
376
-			$mounts = $mountManager->findIn($path);
377
-			foreach ($mounts as $mount) {
378
-				if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
379
-					$message = 'Sharing "' . $itemSourceName . '" failed, because it contains files shared with you!';
380
-					\OCP\Util::writeLog('OCP\Share', $message, ILogger::DEBUG);
381
-					throw new \Exception($message);
382
-				}
383
-
384
-			}
385
-		}
386
-
387
-		// single file shares should never have delete permissions
388
-		if ($itemType === 'file') {
389
-			$permissions = (int)$permissions & ~\OCP\Constants::PERMISSION_DELETE;
390
-		}
391
-
392
-		//Validate expirationDate
393
-		if ($expirationDate !== null) {
394
-			try {
395
-				/*
56
+    /** CRUDS permissions (Create, Read, Update, Delete, Share) using a bitmask
57
+     * Construct permissions for share() and setPermissions with Or (|) e.g.
58
+     * Give user read and update permissions: PERMISSION_READ | PERMISSION_UPDATE
59
+     *
60
+     * Check if permission is granted with And (&) e.g. Check if delete is
61
+     * granted: if ($permissions & PERMISSION_DELETE)
62
+     *
63
+     * Remove permissions with And (&) and Not (~) e.g. Remove the update
64
+     * permission: $permissions &= ~PERMISSION_UPDATE
65
+     *
66
+     * Apps are required to handle permissions on their own, this class only
67
+     * stores and manages the permissions of shares
68
+     * @see lib/public/constants.php
69
+     */
70
+
71
+    /**
72
+     * Register a sharing backend class that implements OCP\Share_Backend for an item type
73
+     * @param string $itemType Item type
74
+     * @param string $class Backend class
75
+     * @param string $collectionOf (optional) Depends on item type
76
+     * @param array $supportedFileExtensions (optional) List of supported file extensions if this item type depends on files
77
+     * @return boolean true if backend is registered or false if error
78
+     */
79
+    public static function registerBackend($itemType, $class, $collectionOf = null, $supportedFileExtensions = null) {
80
+        if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_enabled', 'yes') == 'yes') {
81
+            if (!isset(self::$backendTypes[$itemType])) {
82
+                self::$backendTypes[$itemType] = array(
83
+                    'class' => $class,
84
+                    'collectionOf' => $collectionOf,
85
+                    'supportedFileExtensions' => $supportedFileExtensions
86
+                );
87
+                if(count(self::$backendTypes) === 1) {
88
+                    Util::addScript('core', 'merged-share-backend');
89
+                }
90
+                return true;
91
+            }
92
+            \OCP\Util::writeLog('OCP\Share',
93
+                'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class']
94
+                .' is already registered for '.$itemType,
95
+                ILogger::WARN);
96
+        }
97
+        return false;
98
+    }
99
+
100
+    /**
101
+     * Get the items of item type shared with the current user
102
+     * @param string $itemType
103
+     * @param int $format (optional) Format type must be defined by the backend
104
+     * @param mixed $parameters (optional)
105
+     * @param int $limit Number of items to return (optional) Returns all by default
106
+     * @param boolean $includeCollections (optional)
107
+     * @return mixed Return depends on format
108
+     */
109
+    public static function getItemsSharedWith($itemType, $format = self::FORMAT_NONE,
110
+                                                $parameters = null, $limit = -1, $includeCollections = false) {
111
+        return self::getItems($itemType, null, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format,
112
+            $parameters, $limit, $includeCollections);
113
+    }
114
+
115
+    /**
116
+     * Get the items of item type shared with a user
117
+     * @param string $itemType
118
+     * @param string $user id for which user we want the shares
119
+     * @param int $format (optional) Format type must be defined by the backend
120
+     * @param mixed $parameters (optional)
121
+     * @param int $limit Number of items to return (optional) Returns all by default
122
+     * @param boolean $includeCollections (optional)
123
+     * @return mixed Return depends on format
124
+     */
125
+    public static function getItemsSharedWithUser($itemType, $user, $format = self::FORMAT_NONE,
126
+                                                    $parameters = null, $limit = -1, $includeCollections = false) {
127
+        return self::getItems($itemType, null, self::$shareTypeUserAndGroups, $user, null, $format,
128
+            $parameters, $limit, $includeCollections);
129
+    }
130
+
131
+    /**
132
+     * Get the item of item type shared with a given user by source
133
+     * @param string $itemType
134
+     * @param string $itemSource
135
+     * @param string $user User to whom the item was shared
136
+     * @param string $owner Owner of the share
137
+     * @param int $shareType only look for a specific share type
138
+     * @return array Return list of items with file_target, permissions and expiration
139
+     */
140
+    public static function getItemSharedWithUser($itemType, $itemSource, $user, $owner = null, $shareType = null) {
141
+        $shares = array();
142
+        $fileDependent = false;
143
+
144
+        $where = 'WHERE';
145
+        $fileDependentWhere = '';
146
+        if ($itemType === 'file' || $itemType === 'folder') {
147
+            $fileDependent = true;
148
+            $column = 'file_source';
149
+            $fileDependentWhere = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` ';
150
+            $fileDependentWhere .= 'INNER JOIN `*PREFIX*storages` ON `numeric_id` = `*PREFIX*filecache`.`storage` ';
151
+        } else {
152
+            $column = 'item_source';
153
+        }
154
+
155
+        $select = self::createSelectStatement(self::FORMAT_NONE, $fileDependent);
156
+
157
+        $where .= ' `' . $column . '` = ? AND `item_type` = ? ';
158
+        $arguments = array($itemSource, $itemType);
159
+        // for link shares $user === null
160
+        if ($user !== null) {
161
+            $where .= ' AND `share_with` = ? ';
162
+            $arguments[] = $user;
163
+        }
164
+
165
+        if ($shareType !== null) {
166
+            $where .= ' AND `share_type` = ? ';
167
+            $arguments[] = $shareType;
168
+        }
169
+
170
+        if ($owner !== null) {
171
+            $where .= ' AND `uid_owner` = ? ';
172
+            $arguments[] = $owner;
173
+        }
174
+
175
+        $query = \OC_DB::prepare('SELECT ' . $select . ' FROM `*PREFIX*share` '. $fileDependentWhere . $where);
176
+
177
+        $result = \OC_DB::executeAudited($query, $arguments);
178
+
179
+        while ($row = $result->fetchRow()) {
180
+            if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
181
+                continue;
182
+            }
183
+            if ($fileDependent && (int)$row['file_parent'] === -1) {
184
+                // if it is a mount point we need to get the path from the mount manager
185
+                $mountManager = \OC\Files\Filesystem::getMountManager();
186
+                $mountPoint = $mountManager->findByStorageId($row['storage_id']);
187
+                if (!empty($mountPoint)) {
188
+                    $path = $mountPoint[0]->getMountPoint();
189
+                    $path = trim($path, '/');
190
+                    $path = substr($path, strlen($owner) + 1); //normalize path to 'files/foo.txt`
191
+                    $row['path'] = $path;
192
+                } else {
193
+                    \OC::$server->getLogger()->warning(
194
+                        'Could not resolve mount point for ' . $row['storage_id'],
195
+                        ['app' => 'OCP\Share']
196
+                    );
197
+                }
198
+            }
199
+            $shares[] = $row;
200
+        }
201
+
202
+        //if didn't found a result than let's look for a group share.
203
+        if(empty($shares) && $user !== null) {
204
+            $userObject = \OC::$server->getUserManager()->get($user);
205
+            $groups = [];
206
+            if ($userObject) {
207
+                $groups = \OC::$server->getGroupManager()->getUserGroupIds($userObject);
208
+            }
209
+
210
+            if (!empty($groups)) {
211
+                $where = $fileDependentWhere . ' WHERE `' . $column . '` = ? AND `item_type` = ? AND `share_with` in (?)';
212
+                $arguments = array($itemSource, $itemType, $groups);
213
+                $types = array(null, null, IQueryBuilder::PARAM_STR_ARRAY);
214
+
215
+                if ($owner !== null) {
216
+                    $where .= ' AND `uid_owner` = ?';
217
+                    $arguments[] = $owner;
218
+                    $types[] = null;
219
+                }
220
+
221
+                // TODO: inject connection, hopefully one day in the future when this
222
+                // class isn't static anymore...
223
+                $conn = \OC::$server->getDatabaseConnection();
224
+                $result = $conn->executeQuery(
225
+                    'SELECT ' . $select . ' FROM `*PREFIX*share` ' . $where,
226
+                    $arguments,
227
+                    $types
228
+                );
229
+
230
+                while ($row = $result->fetch()) {
231
+                    $shares[] = $row;
232
+                }
233
+            }
234
+        }
235
+
236
+        return $shares;
237
+
238
+    }
239
+
240
+    /**
241
+     * Get the item of item type shared with the current user by source
242
+     * @param string $itemType
243
+     * @param string $itemSource
244
+     * @param int $format (optional) Format type must be defined by the backend
245
+     * @param mixed $parameters
246
+     * @param boolean $includeCollections
247
+     * @param string $shareWith (optional) define against which user should be checked, default: current user
248
+     * @return array
249
+     */
250
+    public static function getItemSharedWithBySource($itemType, $itemSource, $format = self::FORMAT_NONE,
251
+                                                        $parameters = null, $includeCollections = false, $shareWith = null) {
252
+        $shareWith = ($shareWith === null) ? \OC_User::getUser() : $shareWith;
253
+        return self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, $shareWith, null, $format,
254
+            $parameters, 1, $includeCollections, true);
255
+    }
256
+
257
+    /**
258
+     * Based on the given token the share information will be returned - password protected shares will be verified
259
+     * @param string $token
260
+     * @param bool $checkPasswordProtection
261
+     * @return array|boolean false will be returned in case the token is unknown or unauthorized
262
+     */
263
+    public static function getShareByToken($token, $checkPasswordProtection = true) {
264
+        $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `token` = ?', 1);
265
+        $result = $query->execute(array($token));
266
+        if ($result === false) {
267
+            \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage() . ', token=' . $token, ILogger::ERROR);
268
+        }
269
+        $row = $result->fetchRow();
270
+        if ($row === false) {
271
+            return false;
272
+        }
273
+        if (is_array($row) and self::expireItem($row)) {
274
+            return false;
275
+        }
276
+
277
+        // password protected shares need to be authenticated
278
+        if ($checkPasswordProtection && !\OC\Share\Share::checkPasswordProtectedShare($row)) {
279
+            return false;
280
+        }
281
+
282
+        return $row;
283
+    }
284
+
285
+    /**
286
+     * Get the shared items of item type owned by the current user
287
+     * @param string $itemType
288
+     * @param int $format (optional) Format type must be defined by the backend
289
+     * @param mixed $parameters
290
+     * @param int $limit Number of items to return (optional) Returns all by default
291
+     * @param boolean $includeCollections
292
+     * @return mixed Return depends on format
293
+     */
294
+    public static function getItemsShared($itemType, $format = self::FORMAT_NONE, $parameters = null,
295
+                                            $limit = -1, $includeCollections = false) {
296
+        return self::getItems($itemType, null, null, null, \OC_User::getUser(), $format,
297
+            $parameters, $limit, $includeCollections);
298
+    }
299
+
300
+    /**
301
+     * Get the shared item of item type owned by the current user
302
+     * @param string $itemType
303
+     * @param string $itemSource
304
+     * @param int $format (optional) Format type must be defined by the backend
305
+     * @param mixed $parameters
306
+     * @param boolean $includeCollections
307
+     * @return mixed Return depends on format
308
+     */
309
+    public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE,
310
+                                            $parameters = null, $includeCollections = false) {
311
+        return self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), $format,
312
+            $parameters, -1, $includeCollections);
313
+    }
314
+
315
+    /**
316
+     * Share an item with a user, group, or via private link
317
+     * @param string $itemType
318
+     * @param string $itemSource
319
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
320
+     * @param string $shareWith User or group the item is being shared with
321
+     * @param int $permissions CRUDS
322
+     * @param string $itemSourceName
323
+     * @param \DateTime|null $expirationDate
324
+     * @param bool|null $passwordChanged
325
+     * @return boolean|string Returns true on success or false on failure, Returns token on success for links
326
+     * @throws \OC\HintException when the share type is remote and the shareWith is invalid
327
+     * @throws \Exception
328
+     * @since 5.0.0 - parameter $itemSourceName was added in 6.0.0, parameter $expirationDate was added in 7.0.0, parameter $passwordChanged added in 9.0.0
329
+     * @deprecated 14.0.0 TESTS ONLY - this methods is as of 2018-06 only used by tests
330
+     */
331
+    public static function shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions, $itemSourceName = null, \DateTime $expirationDate = null, $passwordChanged = null) {
332
+
333
+        $backend = self::getBackend($itemType);
334
+        $l = \OC::$server->getL10N('lib');
335
+
336
+        if ($backend->isShareTypeAllowed($shareType) === false) {
337
+            $message = 'Sharing %s failed, because the backend does not allow shares from type %i';
338
+            $message_t = $l->t('Sharing %s failed, because the backend does not allow shares from type %i', array($itemSourceName, $shareType));
339
+            \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareType), ILogger::DEBUG);
340
+            throw new \Exception($message_t);
341
+        }
342
+
343
+        $uidOwner = \OC_User::getUser();
344
+        $shareWithinGroupOnly = self::shareWithGroupMembersOnly();
345
+
346
+        if (is_null($itemSourceName)) {
347
+            $itemSourceName = $itemSource;
348
+        }
349
+        $itemName = $itemSourceName;
350
+
351
+        // check if file can be shared
352
+        if ($itemType === 'file' or $itemType === 'folder') {
353
+            $path = \OC\Files\Filesystem::getPath($itemSource);
354
+            $itemName = $path;
355
+
356
+            // verify that the file exists before we try to share it
357
+            if (!$path) {
358
+                $message = 'Sharing %s failed, because the file does not exist';
359
+                $message_t = $l->t('Sharing %s failed, because the file does not exist', array($itemSourceName));
360
+                \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
361
+                throw new \Exception($message_t);
362
+            }
363
+            // verify that the user has share permission
364
+            if (!\OC\Files\Filesystem::isSharable($path) || \OCP\Util::isSharingDisabledForUser()) {
365
+                $message = 'You are not allowed to share %s';
366
+                $message_t = $l->t('You are not allowed to share %s', [$path]);
367
+                \OCP\Util::writeLog('OCP\Share', sprintf($message, $path), ILogger::DEBUG);
368
+                throw new \Exception($message_t);
369
+            }
370
+        }
371
+
372
+        //verify that we don't share a folder which already contains a share mount point
373
+        if ($itemType === 'folder') {
374
+            $path = '/' . $uidOwner . '/files' . \OC\Files\Filesystem::getPath($itemSource) . '/';
375
+            $mountManager = \OC\Files\Filesystem::getMountManager();
376
+            $mounts = $mountManager->findIn($path);
377
+            foreach ($mounts as $mount) {
378
+                if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
379
+                    $message = 'Sharing "' . $itemSourceName . '" failed, because it contains files shared with you!';
380
+                    \OCP\Util::writeLog('OCP\Share', $message, ILogger::DEBUG);
381
+                    throw new \Exception($message);
382
+                }
383
+
384
+            }
385
+        }
386
+
387
+        // single file shares should never have delete permissions
388
+        if ($itemType === 'file') {
389
+            $permissions = (int)$permissions & ~\OCP\Constants::PERMISSION_DELETE;
390
+        }
391
+
392
+        //Validate expirationDate
393
+        if ($expirationDate !== null) {
394
+            try {
395
+                /*
396 396
 				 * Reuse the validateExpireDate.
397 397
 				 * We have to pass time() since the second arg is the time
398 398
 				 * the file was shared, since it is not shared yet we just use
399 399
 				 * the current time.
400 400
 				 */
401
-				$expirationDate = self::validateExpireDate($expirationDate->format('Y-m-d'), time(), $itemType, $itemSource);
402
-			} catch (\Exception $e) {
403
-				throw new \OC\HintException($e->getMessage(), $e->getMessage(), 404);
404
-			}
405
-		}
406
-
407
-		// Verify share type and sharing conditions are met
408
-		if ($shareType === self::SHARE_TYPE_USER) {
409
-			if ($shareWith == $uidOwner) {
410
-				$message = 'Sharing %s failed, because you can not share with yourself';
411
-				$message_t = $l->t('Sharing %s failed, because you can not share with yourself', [$itemName]);
412
-				\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
413
-				throw new \Exception($message_t);
414
-			}
415
-			if (!\OC::$server->getUserManager()->userExists($shareWith)) {
416
-				$message = 'Sharing %1$s failed, because the user %2$s does not exist';
417
-				$message_t = $l->t('Sharing %1$s failed, because the user %2$s does not exist', array($itemSourceName, $shareWith));
418
-				\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
419
-				throw new \Exception($message_t);
420
-			}
421
-			if ($shareWithinGroupOnly) {
422
-				$userManager = \OC::$server->getUserManager();
423
-				$groupManager = \OC::$server->getGroupManager();
424
-				$userOwner = $userManager->get($uidOwner);
425
-				$userShareWith = $userManager->get($shareWith);
426
-				$groupsOwner = [];
427
-				$groupsShareWith = [];
428
-				if ($userOwner) {
429
-					$groupsOwner = $groupManager->getUserGroupIds($userOwner);
430
-				}
431
-				if ($userShareWith) {
432
-					$groupsShareWith = $groupManager->getUserGroupIds($userShareWith);
433
-				}
434
-				$inGroup = array_intersect($groupsOwner, $groupsShareWith);
435
-				if (empty($inGroup)) {
436
-					$message = 'Sharing %1$s failed, because the user '
437
-						.'%2$s is not a member of any groups that %3$s is a member of';
438
-					$message_t = $l->t('Sharing %1$s failed, because the user %2$s is not a member of any groups that %3$s is a member of', array($itemName, $shareWith, $uidOwner));
439
-					\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemName, $shareWith, $uidOwner), ILogger::DEBUG);
440
-					throw new \Exception($message_t);
441
-				}
442
-			}
443
-			// Check if the item source is already shared with the user, either from the same owner or a different user
444
-			if ($checkExists = self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups,
445
-				$shareWith, null, self::FORMAT_NONE, null, 1, true, true)) {
446
-				// Only allow the same share to occur again if it is the same
447
-				// owner and is not a user share, this use case is for increasing
448
-				// permissions for a specific user
449
-				if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
450
-					$message = 'Sharing %1$s failed, because this item is already shared with %2$s';
451
-					$message_t = $l->t('Sharing %1$s failed, because this item is already shared with %2$s', array($itemSourceName, $shareWith));
452
-					\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
453
-					throw new \Exception($message_t);
454
-				}
455
-			}
456
-			if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_USER,
457
-				$shareWith, null, self::FORMAT_NONE, null, 1, true, true)) {
458
-				// Only allow the same share to occur again if it is the same
459
-				// owner and is not a user share, this use case is for increasing
460
-				// permissions for a specific user
461
-				if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
462
-					$message = 'Sharing %1$s failed, because this item is already shared with user %2$s';
463
-					$message_t = $l->t('Sharing %1$s failed, because this item is already shared with user %2$s', array($itemSourceName, $shareWith));
464
-					\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::ERROR);
465
-					throw new \Exception($message_t);
466
-				}
467
-			}
468
-		} else if ($shareType === self::SHARE_TYPE_GROUP) {
469
-			if (!\OC::$server->getGroupManager()->groupExists($shareWith)) {
470
-				$message = 'Sharing %1$s failed, because the group %2$s does not exist';
471
-				$message_t = $l->t('Sharing %1$s failed, because the group %2$s does not exist', array($itemSourceName, $shareWith));
472
-				\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
473
-				throw new \Exception($message_t);
474
-			}
475
-			if ($shareWithinGroupOnly) {
476
-				$group = \OC::$server->getGroupManager()->get($shareWith);
477
-				$user = \OC::$server->getUserManager()->get($uidOwner);
478
-				if (!$group || !$user || !$group->inGroup($user)) {
479
-					$message = 'Sharing %1$s failed, because '
480
-						. '%2$s is not a member of the group %3$s';
481
-					$message_t = $l->t('Sharing %1$s failed, because %2$s is not a member of the group %3$s', array($itemSourceName, $uidOwner, $shareWith));
482
-					\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $uidOwner, $shareWith), ILogger::DEBUG);
483
-					throw new \Exception($message_t);
484
-				}
485
-			}
486
-			// Check if the item source is already shared with the group, either from the same owner or a different user
487
-			// The check for each user in the group is done inside the put() function
488
-			if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_GROUP, $shareWith,
489
-				null, self::FORMAT_NONE, null, 1, true, true)) {
490
-
491
-				if ($checkExists['share_with'] === $shareWith && $checkExists['share_type'] === \OCP\Share::SHARE_TYPE_GROUP) {
492
-					$message = 'Sharing %1$s failed, because this item is already shared with %2$s';
493
-					$message_t = $l->t('Sharing %1$s failed, because this item is already shared with %2$s', array($itemSourceName, $shareWith));
494
-					\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
495
-					throw new \Exception($message_t);
496
-				}
497
-			}
498
-			// Convert share with into an array with the keys group and users
499
-			$group = $shareWith;
500
-			$shareWith = array();
501
-			$shareWith['group'] = $group;
502
-
503
-
504
-			$groupObject = \OC::$server->getGroupManager()->get($group);
505
-			$userIds = [];
506
-			if ($groupObject) {
507
-				$users = $groupObject->searchUsers('', -1, 0);
508
-				foreach ($users as $user) {
509
-					$userIds[] = $user->getUID();
510
-				}
511
-			}
512
-
513
-			$shareWith['users'] = array_diff($userIds, array($uidOwner));
514
-		} else if ($shareType === self::SHARE_TYPE_LINK) {
515
-			$updateExistingShare = false;
516
-			if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_links', 'yes') == 'yes') {
517
-
518
-				// IF the password is changed via the old ajax endpoint verify it before deleting the old share
519
-				if ($passwordChanged === true) {
520
-					self::verifyPassword($shareWith);
521
-				}
522
-
523
-				// when updating a link share
524
-				// FIXME Don't delete link if we update it
525
-				if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_LINK, null,
526
-					$uidOwner, self::FORMAT_NONE, null, 1)) {
527
-					// remember old token
528
-					$oldToken = $checkExists['token'];
529
-					$oldPermissions = $checkExists['permissions'];
530
-					//delete the old share
531
-					Helper::delete($checkExists['id']);
532
-					$updateExistingShare = true;
533
-				}
534
-
535
-				if ($passwordChanged === null) {
536
-					// Generate hash of password - same method as user passwords
537
-					if (is_string($shareWith) && $shareWith !== '') {
538
-						self::verifyPassword($shareWith);
539
-						$shareWith = \OC::$server->getHasher()->hash($shareWith);
540
-					} else {
541
-						// reuse the already set password, but only if we change permissions
542
-						// otherwise the user disabled the password protection
543
-						if ($checkExists && (int)$permissions !== (int)$oldPermissions) {
544
-							$shareWith = $checkExists['share_with'];
545
-						}
546
-					}
547
-				} else {
548
-					if ($passwordChanged === true) {
549
-						if (is_string($shareWith) && $shareWith !== '') {
550
-							self::verifyPassword($shareWith);
551
-							$shareWith = \OC::$server->getHasher()->hash($shareWith);
552
-						}
553
-					} else if ($updateExistingShare) {
554
-						$shareWith = $checkExists['share_with'];
555
-					}
556
-				}
557
-
558
-				if (\OCP\Util::isPublicLinkPasswordRequired() && empty($shareWith)) {
559
-					$message = 'You need to provide a password to create a public link, only protected links are allowed';
560
-					$message_t = $l->t('You need to provide a password to create a public link, only protected links are allowed');
561
-					\OCP\Util::writeLog('OCP\Share', $message, ILogger::DEBUG);
562
-					throw new \Exception($message_t);
563
-				}
564
-
565
-				if ($updateExistingShare === false &&
566
-					self::isDefaultExpireDateEnabled() &&
567
-					empty($expirationDate)) {
568
-					$expirationDate = Helper::calcExpireDate();
569
-				}
570
-
571
-				// Generate token
572
-				if (isset($oldToken)) {
573
-					$token = $oldToken;
574
-				} else {
575
-					$token = \OC::$server->getSecureRandom()->generate(self::TOKEN_LENGTH,
576
-						\OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
577
-					);
578
-				}
579
-				$result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions,
580
-					null, $token, $itemSourceName, $expirationDate);
581
-				if ($result) {
582
-					return $token;
583
-				} else {
584
-					return false;
585
-				}
586
-			}
587
-			$message = 'Sharing %s failed, because sharing with links is not allowed';
588
-			$message_t = $l->t('Sharing %s failed, because sharing with links is not allowed', array($itemSourceName));
589
-			\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
590
-			throw new \Exception($message_t);
591
-		} else if ($shareType === self::SHARE_TYPE_REMOTE) {
592
-
593
-			/*
401
+                $expirationDate = self::validateExpireDate($expirationDate->format('Y-m-d'), time(), $itemType, $itemSource);
402
+            } catch (\Exception $e) {
403
+                throw new \OC\HintException($e->getMessage(), $e->getMessage(), 404);
404
+            }
405
+        }
406
+
407
+        // Verify share type and sharing conditions are met
408
+        if ($shareType === self::SHARE_TYPE_USER) {
409
+            if ($shareWith == $uidOwner) {
410
+                $message = 'Sharing %s failed, because you can not share with yourself';
411
+                $message_t = $l->t('Sharing %s failed, because you can not share with yourself', [$itemName]);
412
+                \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
413
+                throw new \Exception($message_t);
414
+            }
415
+            if (!\OC::$server->getUserManager()->userExists($shareWith)) {
416
+                $message = 'Sharing %1$s failed, because the user %2$s does not exist';
417
+                $message_t = $l->t('Sharing %1$s failed, because the user %2$s does not exist', array($itemSourceName, $shareWith));
418
+                \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
419
+                throw new \Exception($message_t);
420
+            }
421
+            if ($shareWithinGroupOnly) {
422
+                $userManager = \OC::$server->getUserManager();
423
+                $groupManager = \OC::$server->getGroupManager();
424
+                $userOwner = $userManager->get($uidOwner);
425
+                $userShareWith = $userManager->get($shareWith);
426
+                $groupsOwner = [];
427
+                $groupsShareWith = [];
428
+                if ($userOwner) {
429
+                    $groupsOwner = $groupManager->getUserGroupIds($userOwner);
430
+                }
431
+                if ($userShareWith) {
432
+                    $groupsShareWith = $groupManager->getUserGroupIds($userShareWith);
433
+                }
434
+                $inGroup = array_intersect($groupsOwner, $groupsShareWith);
435
+                if (empty($inGroup)) {
436
+                    $message = 'Sharing %1$s failed, because the user '
437
+                        .'%2$s is not a member of any groups that %3$s is a member of';
438
+                    $message_t = $l->t('Sharing %1$s failed, because the user %2$s is not a member of any groups that %3$s is a member of', array($itemName, $shareWith, $uidOwner));
439
+                    \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemName, $shareWith, $uidOwner), ILogger::DEBUG);
440
+                    throw new \Exception($message_t);
441
+                }
442
+            }
443
+            // Check if the item source is already shared with the user, either from the same owner or a different user
444
+            if ($checkExists = self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups,
445
+                $shareWith, null, self::FORMAT_NONE, null, 1, true, true)) {
446
+                // Only allow the same share to occur again if it is the same
447
+                // owner and is not a user share, this use case is for increasing
448
+                // permissions for a specific user
449
+                if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
450
+                    $message = 'Sharing %1$s failed, because this item is already shared with %2$s';
451
+                    $message_t = $l->t('Sharing %1$s failed, because this item is already shared with %2$s', array($itemSourceName, $shareWith));
452
+                    \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
453
+                    throw new \Exception($message_t);
454
+                }
455
+            }
456
+            if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_USER,
457
+                $shareWith, null, self::FORMAT_NONE, null, 1, true, true)) {
458
+                // Only allow the same share to occur again if it is the same
459
+                // owner and is not a user share, this use case is for increasing
460
+                // permissions for a specific user
461
+                if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
462
+                    $message = 'Sharing %1$s failed, because this item is already shared with user %2$s';
463
+                    $message_t = $l->t('Sharing %1$s failed, because this item is already shared with user %2$s', array($itemSourceName, $shareWith));
464
+                    \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::ERROR);
465
+                    throw new \Exception($message_t);
466
+                }
467
+            }
468
+        } else if ($shareType === self::SHARE_TYPE_GROUP) {
469
+            if (!\OC::$server->getGroupManager()->groupExists($shareWith)) {
470
+                $message = 'Sharing %1$s failed, because the group %2$s does not exist';
471
+                $message_t = $l->t('Sharing %1$s failed, because the group %2$s does not exist', array($itemSourceName, $shareWith));
472
+                \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
473
+                throw new \Exception($message_t);
474
+            }
475
+            if ($shareWithinGroupOnly) {
476
+                $group = \OC::$server->getGroupManager()->get($shareWith);
477
+                $user = \OC::$server->getUserManager()->get($uidOwner);
478
+                if (!$group || !$user || !$group->inGroup($user)) {
479
+                    $message = 'Sharing %1$s failed, because '
480
+                        . '%2$s is not a member of the group %3$s';
481
+                    $message_t = $l->t('Sharing %1$s failed, because %2$s is not a member of the group %3$s', array($itemSourceName, $uidOwner, $shareWith));
482
+                    \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $uidOwner, $shareWith), ILogger::DEBUG);
483
+                    throw new \Exception($message_t);
484
+                }
485
+            }
486
+            // Check if the item source is already shared with the group, either from the same owner or a different user
487
+            // The check for each user in the group is done inside the put() function
488
+            if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_GROUP, $shareWith,
489
+                null, self::FORMAT_NONE, null, 1, true, true)) {
490
+
491
+                if ($checkExists['share_with'] === $shareWith && $checkExists['share_type'] === \OCP\Share::SHARE_TYPE_GROUP) {
492
+                    $message = 'Sharing %1$s failed, because this item is already shared with %2$s';
493
+                    $message_t = $l->t('Sharing %1$s failed, because this item is already shared with %2$s', array($itemSourceName, $shareWith));
494
+                    \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
495
+                    throw new \Exception($message_t);
496
+                }
497
+            }
498
+            // Convert share with into an array with the keys group and users
499
+            $group = $shareWith;
500
+            $shareWith = array();
501
+            $shareWith['group'] = $group;
502
+
503
+
504
+            $groupObject = \OC::$server->getGroupManager()->get($group);
505
+            $userIds = [];
506
+            if ($groupObject) {
507
+                $users = $groupObject->searchUsers('', -1, 0);
508
+                foreach ($users as $user) {
509
+                    $userIds[] = $user->getUID();
510
+                }
511
+            }
512
+
513
+            $shareWith['users'] = array_diff($userIds, array($uidOwner));
514
+        } else if ($shareType === self::SHARE_TYPE_LINK) {
515
+            $updateExistingShare = false;
516
+            if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_links', 'yes') == 'yes') {
517
+
518
+                // IF the password is changed via the old ajax endpoint verify it before deleting the old share
519
+                if ($passwordChanged === true) {
520
+                    self::verifyPassword($shareWith);
521
+                }
522
+
523
+                // when updating a link share
524
+                // FIXME Don't delete link if we update it
525
+                if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_LINK, null,
526
+                    $uidOwner, self::FORMAT_NONE, null, 1)) {
527
+                    // remember old token
528
+                    $oldToken = $checkExists['token'];
529
+                    $oldPermissions = $checkExists['permissions'];
530
+                    //delete the old share
531
+                    Helper::delete($checkExists['id']);
532
+                    $updateExistingShare = true;
533
+                }
534
+
535
+                if ($passwordChanged === null) {
536
+                    // Generate hash of password - same method as user passwords
537
+                    if (is_string($shareWith) && $shareWith !== '') {
538
+                        self::verifyPassword($shareWith);
539
+                        $shareWith = \OC::$server->getHasher()->hash($shareWith);
540
+                    } else {
541
+                        // reuse the already set password, but only if we change permissions
542
+                        // otherwise the user disabled the password protection
543
+                        if ($checkExists && (int)$permissions !== (int)$oldPermissions) {
544
+                            $shareWith = $checkExists['share_with'];
545
+                        }
546
+                    }
547
+                } else {
548
+                    if ($passwordChanged === true) {
549
+                        if (is_string($shareWith) && $shareWith !== '') {
550
+                            self::verifyPassword($shareWith);
551
+                            $shareWith = \OC::$server->getHasher()->hash($shareWith);
552
+                        }
553
+                    } else if ($updateExistingShare) {
554
+                        $shareWith = $checkExists['share_with'];
555
+                    }
556
+                }
557
+
558
+                if (\OCP\Util::isPublicLinkPasswordRequired() && empty($shareWith)) {
559
+                    $message = 'You need to provide a password to create a public link, only protected links are allowed';
560
+                    $message_t = $l->t('You need to provide a password to create a public link, only protected links are allowed');
561
+                    \OCP\Util::writeLog('OCP\Share', $message, ILogger::DEBUG);
562
+                    throw new \Exception($message_t);
563
+                }
564
+
565
+                if ($updateExistingShare === false &&
566
+                    self::isDefaultExpireDateEnabled() &&
567
+                    empty($expirationDate)) {
568
+                    $expirationDate = Helper::calcExpireDate();
569
+                }
570
+
571
+                // Generate token
572
+                if (isset($oldToken)) {
573
+                    $token = $oldToken;
574
+                } else {
575
+                    $token = \OC::$server->getSecureRandom()->generate(self::TOKEN_LENGTH,
576
+                        \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE
577
+                    );
578
+                }
579
+                $result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions,
580
+                    null, $token, $itemSourceName, $expirationDate);
581
+                if ($result) {
582
+                    return $token;
583
+                } else {
584
+                    return false;
585
+                }
586
+            }
587
+            $message = 'Sharing %s failed, because sharing with links is not allowed';
588
+            $message_t = $l->t('Sharing %s failed, because sharing with links is not allowed', array($itemSourceName));
589
+            \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
590
+            throw new \Exception($message_t);
591
+        } else if ($shareType === self::SHARE_TYPE_REMOTE) {
592
+
593
+            /*
594 594
 			 * Check if file is not already shared with the remote user
595 595
 			 */
596
-			if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_REMOTE,
597
-				$shareWith, $uidOwner, self::FORMAT_NONE, null, 1, true, true)) {
598
-					$message = 'Sharing %1$s failed, because this item is already shared with %2$s';
599
-					$message_t = $l->t('Sharing %1$s failed, because this item is already shared with %2$s', array($itemSourceName, $shareWith));
600
-					\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
601
-					throw new \Exception($message_t);
602
-			}
603
-
604
-			// don't allow federated shares if source and target server are the same
605
-			list($user, $remote) = Helper::splitUserRemote($shareWith);
606
-			$currentServer = self::removeProtocolFromUrl(\OC::$server->getURLGenerator()->getAbsoluteURL('/'));
607
-			$currentUser = \OC::$server->getUserSession()->getUser()->getUID();
608
-			if (Helper::isSameUserOnSameServer($user, $remote, $currentUser, $currentServer)) {
609
-				$message = 'Not allowed to create a federated share with the same user.';
610
-				$message_t = $l->t('Not allowed to create a federated share with the same user');
611
-				\OCP\Util::writeLog('OCP\Share', $message, ILogger::DEBUG);
612
-				throw new \Exception($message_t);
613
-			}
614
-
615
-			$token = \OC::$server->getSecureRandom()->generate(self::TOKEN_LENGTH, \OCP\Security\ISecureRandom::CHAR_LOWER . \OCP\Security\ISecureRandom::CHAR_UPPER .
616
-				\OCP\Security\ISecureRandom::CHAR_DIGITS);
617
-
618
-			$shareWith = $user . '@' . $remote;
619
-			$shareId = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, $token, $itemSourceName);
620
-
621
-			$send = false;
622
-			if ($shareId) {
623
-				$send = self::sendRemoteShare($token, $shareWith, $itemSourceName, $shareId, $uidOwner);
624
-			}
625
-
626
-			if ($send === false) {
627
-				$currentUser = \OC::$server->getUserSession()->getUser()->getUID();
628
-				self::unshare($itemType, $itemSource, $shareType, $shareWith, $currentUser);
629
-				$message_t = $l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable.', array($itemSourceName, $shareWith));
630
-				throw new \Exception($message_t);
631
-			}
632
-
633
-			return $send;
634
-		} else {
635
-			// Future share types need to include their own conditions
636
-			$message = 'Share type %1$s is not valid for %2$s';
637
-			$message_t = $l->t('Share type %1$s is not valid for %2$s', array($shareType, $itemSource));
638
-			\OCP\Util::writeLog('OCP\Share', sprintf($message, $shareType, $itemSource), ILogger::DEBUG);
639
-			throw new \Exception($message_t);
640
-		}
641
-
642
-		// Put the item into the database
643
-		$result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, null, $itemSourceName, $expirationDate);
644
-
645
-		return $result ? true : false;
646
-	}
647
-
648
-	/**
649
-	 * Unshare an item from a user, group, or delete a private link
650
-	 * @param string $itemType
651
-	 * @param string $itemSource
652
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
653
-	 * @param string $shareWith User or group the item is being shared with
654
-	 * @param string $owner owner of the share, if null the current user is used
655
-	 * @return boolean true on success or false on failure
656
-	 */
657
-	public static function unshare($itemType, $itemSource, $shareType, $shareWith, $owner = null) {
658
-
659
-		// check if it is a valid itemType
660
-		self::getBackend($itemType);
661
-
662
-		$items = self::getItemSharedWithUser($itemType, $itemSource, $shareWith, $owner, $shareType);
663
-
664
-		$toDelete = array();
665
-		$newParent = null;
666
-		$currentUser = $owner ? $owner : \OC_User::getUser();
667
-		foreach ($items as $item) {
668
-			// delete the item with the expected share_type and owner
669
-			if ((int)$item['share_type'] === (int)$shareType && $item['uid_owner'] === $currentUser) {
670
-				$toDelete = $item;
671
-				// if there is more then one result we don't have to delete the children
672
-				// but update their parent. For group shares the new parent should always be
673
-				// the original group share and not the db entry with the unique name
674
-			} else if ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) {
675
-				$newParent = $item['parent'];
676
-			} else {
677
-				$newParent = $item['id'];
678
-			}
679
-		}
680
-
681
-		if (!empty($toDelete)) {
682
-			self::unshareItem($toDelete, $newParent);
683
-			return true;
684
-		}
685
-		return false;
686
-	}
687
-
688
-	/**
689
-	 * sent status if users got informed by mail about share
690
-	 * @param string $itemType
691
-	 * @param string $itemSource
692
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
693
-	 * @param string $recipient with whom was the file shared
694
-	 * @param boolean $status
695
-	 */
696
-	public static function setSendMailStatus($itemType, $itemSource, $shareType, $recipient, $status) {
697
-		$status = $status ? 1 : 0;
698
-
699
-		$query = \OC_DB::prepare(
700
-			'UPDATE `*PREFIX*share`
596
+            if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_REMOTE,
597
+                $shareWith, $uidOwner, self::FORMAT_NONE, null, 1, true, true)) {
598
+                    $message = 'Sharing %1$s failed, because this item is already shared with %2$s';
599
+                    $message_t = $l->t('Sharing %1$s failed, because this item is already shared with %2$s', array($itemSourceName, $shareWith));
600
+                    \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
601
+                    throw new \Exception($message_t);
602
+            }
603
+
604
+            // don't allow federated shares if source and target server are the same
605
+            list($user, $remote) = Helper::splitUserRemote($shareWith);
606
+            $currentServer = self::removeProtocolFromUrl(\OC::$server->getURLGenerator()->getAbsoluteURL('/'));
607
+            $currentUser = \OC::$server->getUserSession()->getUser()->getUID();
608
+            if (Helper::isSameUserOnSameServer($user, $remote, $currentUser, $currentServer)) {
609
+                $message = 'Not allowed to create a federated share with the same user.';
610
+                $message_t = $l->t('Not allowed to create a federated share with the same user');
611
+                \OCP\Util::writeLog('OCP\Share', $message, ILogger::DEBUG);
612
+                throw new \Exception($message_t);
613
+            }
614
+
615
+            $token = \OC::$server->getSecureRandom()->generate(self::TOKEN_LENGTH, \OCP\Security\ISecureRandom::CHAR_LOWER . \OCP\Security\ISecureRandom::CHAR_UPPER .
616
+                \OCP\Security\ISecureRandom::CHAR_DIGITS);
617
+
618
+            $shareWith = $user . '@' . $remote;
619
+            $shareId = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, $token, $itemSourceName);
620
+
621
+            $send = false;
622
+            if ($shareId) {
623
+                $send = self::sendRemoteShare($token, $shareWith, $itemSourceName, $shareId, $uidOwner);
624
+            }
625
+
626
+            if ($send === false) {
627
+                $currentUser = \OC::$server->getUserSession()->getUser()->getUID();
628
+                self::unshare($itemType, $itemSource, $shareType, $shareWith, $currentUser);
629
+                $message_t = $l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable.', array($itemSourceName, $shareWith));
630
+                throw new \Exception($message_t);
631
+            }
632
+
633
+            return $send;
634
+        } else {
635
+            // Future share types need to include their own conditions
636
+            $message = 'Share type %1$s is not valid for %2$s';
637
+            $message_t = $l->t('Share type %1$s is not valid for %2$s', array($shareType, $itemSource));
638
+            \OCP\Util::writeLog('OCP\Share', sprintf($message, $shareType, $itemSource), ILogger::DEBUG);
639
+            throw new \Exception($message_t);
640
+        }
641
+
642
+        // Put the item into the database
643
+        $result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, null, $itemSourceName, $expirationDate);
644
+
645
+        return $result ? true : false;
646
+    }
647
+
648
+    /**
649
+     * Unshare an item from a user, group, or delete a private link
650
+     * @param string $itemType
651
+     * @param string $itemSource
652
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
653
+     * @param string $shareWith User or group the item is being shared with
654
+     * @param string $owner owner of the share, if null the current user is used
655
+     * @return boolean true on success or false on failure
656
+     */
657
+    public static function unshare($itemType, $itemSource, $shareType, $shareWith, $owner = null) {
658
+
659
+        // check if it is a valid itemType
660
+        self::getBackend($itemType);
661
+
662
+        $items = self::getItemSharedWithUser($itemType, $itemSource, $shareWith, $owner, $shareType);
663
+
664
+        $toDelete = array();
665
+        $newParent = null;
666
+        $currentUser = $owner ? $owner : \OC_User::getUser();
667
+        foreach ($items as $item) {
668
+            // delete the item with the expected share_type and owner
669
+            if ((int)$item['share_type'] === (int)$shareType && $item['uid_owner'] === $currentUser) {
670
+                $toDelete = $item;
671
+                // if there is more then one result we don't have to delete the children
672
+                // but update their parent. For group shares the new parent should always be
673
+                // the original group share and not the db entry with the unique name
674
+            } else if ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) {
675
+                $newParent = $item['parent'];
676
+            } else {
677
+                $newParent = $item['id'];
678
+            }
679
+        }
680
+
681
+        if (!empty($toDelete)) {
682
+            self::unshareItem($toDelete, $newParent);
683
+            return true;
684
+        }
685
+        return false;
686
+    }
687
+
688
+    /**
689
+     * sent status if users got informed by mail about share
690
+     * @param string $itemType
691
+     * @param string $itemSource
692
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
693
+     * @param string $recipient with whom was the file shared
694
+     * @param boolean $status
695
+     */
696
+    public static function setSendMailStatus($itemType, $itemSource, $shareType, $recipient, $status) {
697
+        $status = $status ? 1 : 0;
698
+
699
+        $query = \OC_DB::prepare(
700
+            'UPDATE `*PREFIX*share`
701 701
 					SET `mail_send` = ?
702 702
 					WHERE `item_type` = ? AND `item_source` = ? AND `share_type` = ? AND `share_with` = ?');
703 703
 
704
-		$result = $query->execute(array($status, $itemType, $itemSource, $shareType, $recipient));
705
-
706
-		if($result === false) {
707
-			\OCP\Util::writeLog('OCP\Share', 'Couldn\'t set send mail status', ILogger::ERROR);
708
-		}
709
-	}
710
-
711
-	/**
712
-	 * validate expiration date if it meets all constraints
713
-	 *
714
-	 * @param string $expireDate well formatted date string, e.g. "DD-MM-YYYY"
715
-	 * @param string $shareTime timestamp when the file was shared
716
-	 * @param string $itemType
717
-	 * @param string $itemSource
718
-	 * @return \DateTime validated date
719
-	 * @throws \Exception when the expire date is in the past or further in the future then the enforced date
720
-	 */
721
-	private static function validateExpireDate($expireDate, $shareTime, $itemType, $itemSource) {
722
-		$l = \OC::$server->getL10N('lib');
723
-		$date = new \DateTime($expireDate);
724
-		$today = new \DateTime('now');
725
-
726
-		// if the user doesn't provide a share time we need to get it from the database
727
-		// fall-back mode to keep API stable, because the $shareTime parameter was added later
728
-		$defaultExpireDateEnforced = \OCP\Util::isDefaultExpireDateEnforced();
729
-		if ($defaultExpireDateEnforced && $shareTime === null) {
730
-			$items = self::getItemShared($itemType, $itemSource);
731
-			$firstItem = reset($items);
732
-			$shareTime = (int)$firstItem['stime'];
733
-		}
734
-
735
-		if ($defaultExpireDateEnforced) {
736
-			// initialize max date with share time
737
-			$maxDate = new \DateTime();
738
-			$maxDate->setTimestamp($shareTime);
739
-			$maxDays = \OC::$server->getConfig()->getAppValue('core', 'shareapi_expire_after_n_days', '7');
740
-			$maxDate->add(new \DateInterval('P' . $maxDays . 'D'));
741
-			if ($date > $maxDate) {
742
-				$warning = 'Cannot set expiration date. Shares cannot expire later than ' . $maxDays . ' after they have been shared';
743
-				$warning_t = $l->t('Cannot set expiration date. Shares cannot expire later than %s after they have been shared', array($maxDays));
744
-				\OCP\Util::writeLog('OCP\Share', $warning, ILogger::WARN);
745
-				throw new \Exception($warning_t);
746
-			}
747
-		}
748
-
749
-		if ($date < $today) {
750
-			$message = 'Cannot set expiration date. Expiration date is in the past';
751
-			$message_t = $l->t('Cannot set expiration date. Expiration date is in the past');
752
-			\OCP\Util::writeLog('OCP\Share', $message, ILogger::WARN);
753
-			throw new \Exception($message_t);
754
-		}
755
-
756
-		return $date;
757
-	}
758
-
759
-	/**
760
-	 * Checks whether a share has expired, calls unshareItem() if yes.
761
-	 * @param array $item Share data (usually database row)
762
-	 * @return boolean True if item was expired, false otherwise.
763
-	 */
764
-	protected static function expireItem(array $item) {
765
-
766
-		$result = false;
767
-
768
-		// only use default expiration date for link shares
769
-		if ((int) $item['share_type'] === self::SHARE_TYPE_LINK) {
770
-
771
-			// calculate expiration date
772
-			if (!empty($item['expiration'])) {
773
-				$userDefinedExpire = new \DateTime($item['expiration']);
774
-				$expires = $userDefinedExpire->getTimestamp();
775
-			} else {
776
-				$expires = null;
777
-			}
778
-
779
-
780
-			// get default expiration settings
781
-			$defaultSettings = Helper::getDefaultExpireSetting();
782
-			$expires = Helper::calculateExpireDate($defaultSettings, $item['stime'], $expires);
783
-
784
-
785
-			if (is_int($expires)) {
786
-				$now = time();
787
-				if ($now > $expires) {
788
-					self::unshareItem($item);
789
-					$result = true;
790
-				}
791
-			}
792
-		}
793
-		return $result;
794
-	}
795
-
796
-	/**
797
-	 * Unshares a share given a share data array
798
-	 * @param array $item Share data (usually database row)
799
-	 * @param int $newParent parent ID
800
-	 * @return null
801
-	 */
802
-	protected static function unshareItem(array $item, $newParent = null) {
803
-
804
-		$shareType = (int)$item['share_type'];
805
-		$shareWith = null;
806
-		if ($shareType !== \OCP\Share::SHARE_TYPE_LINK) {
807
-			$shareWith = $item['share_with'];
808
-		}
809
-
810
-		// Pass all the vars we have for now, they may be useful
811
-		$hookParams = array(
812
-			'id'            => $item['id'],
813
-			'itemType'      => $item['item_type'],
814
-			'itemSource'    => $item['item_source'],
815
-			'shareType'     => $shareType,
816
-			'shareWith'     => $shareWith,
817
-			'itemParent'    => $item['parent'],
818
-			'uidOwner'      => $item['uid_owner'],
819
-		);
820
-		if($item['item_type'] === 'file' || $item['item_type'] === 'folder') {
821
-			$hookParams['fileSource'] = $item['file_source'];
822
-			$hookParams['fileTarget'] = $item['file_target'];
823
-		}
824
-
825
-		\OC_Hook::emit(\OCP\Share::class, 'pre_unshare', $hookParams);
826
-		$deletedShares = Helper::delete($item['id'], false, null, $newParent);
827
-		$deletedShares[] = $hookParams;
828
-		$hookParams['deletedShares'] = $deletedShares;
829
-		\OC_Hook::emit(\OCP\Share::class, 'post_unshare', $hookParams);
830
-		if ((int)$item['share_type'] === \OCP\Share::SHARE_TYPE_REMOTE && \OC::$server->getUserSession()->getUser()) {
831
-			list(, $remote) = Helper::splitUserRemote($item['share_with']);
832
-			self::sendRemoteUnshare($remote, $item['id'], $item['token']);
833
-		}
834
-	}
835
-
836
-	/**
837
-	 * Get the backend class for the specified item type
838
-	 * @param string $itemType
839
-	 * @throws \Exception
840
-	 * @return \OCP\Share_Backend
841
-	 */
842
-	public static function getBackend($itemType) {
843
-		$l = \OC::$server->getL10N('lib');
844
-		if (isset(self::$backends[$itemType])) {
845
-			return self::$backends[$itemType];
846
-		} else if (isset(self::$backendTypes[$itemType]['class'])) {
847
-			$class = self::$backendTypes[$itemType]['class'];
848
-			if (class_exists($class)) {
849
-				self::$backends[$itemType] = new $class;
850
-				if (!(self::$backends[$itemType] instanceof \OCP\Share_Backend)) {
851
-					$message = 'Sharing backend %s must implement the interface OCP\Share_Backend';
852
-					$message_t = $l->t('Sharing backend %s must implement the interface OCP\Share_Backend', array($class));
853
-					\OCP\Util::writeLog('OCP\Share', sprintf($message, $class), ILogger::ERROR);
854
-					throw new \Exception($message_t);
855
-				}
856
-				return self::$backends[$itemType];
857
-			} else {
858
-				$message = 'Sharing backend %s not found';
859
-				$message_t = $l->t('Sharing backend %s not found', array($class));
860
-				\OCP\Util::writeLog('OCP\Share', sprintf($message, $class), ILogger::ERROR);
861
-				throw new \Exception($message_t);
862
-			}
863
-		}
864
-		$message = 'Sharing backend for %s not found';
865
-		$message_t = $l->t('Sharing backend for %s not found', array($itemType));
866
-		\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemType), ILogger::ERROR);
867
-		throw new \Exception($message_t);
868
-	}
869
-
870
-	/**
871
-	 * Check if resharing is allowed
872
-	 * @return boolean true if allowed or false
873
-	 *
874
-	 * Resharing is allowed by default if not configured
875
-	 */
876
-	public static function isResharingAllowed() {
877
-		if (!isset(self::$isResharingAllowed)) {
878
-			if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_resharing', 'yes') == 'yes') {
879
-				self::$isResharingAllowed = true;
880
-			} else {
881
-				self::$isResharingAllowed = false;
882
-			}
883
-		}
884
-		return self::$isResharingAllowed;
885
-	}
886
-
887
-	/**
888
-	 * Get a list of collection item types for the specified item type
889
-	 * @param string $itemType
890
-	 * @return array
891
-	 */
892
-	private static function getCollectionItemTypes($itemType) {
893
-		$collectionTypes = array($itemType);
894
-		foreach (self::$backendTypes as $type => $backend) {
895
-			if (in_array($backend['collectionOf'], $collectionTypes)) {
896
-				$collectionTypes[] = $type;
897
-			}
898
-		}
899
-		// TODO Add option for collections to be collection of themselves, only 'folder' does it now...
900
-		if (isset(self::$backendTypes[$itemType]) && (!self::getBackend($itemType) instanceof \OCP\Share_Backend_Collection || $itemType != 'folder')) {
901
-			unset($collectionTypes[0]);
902
-		}
903
-		// Return array if collections were found or the item type is a
904
-		// collection itself - collections can be inside collections
905
-		if (count($collectionTypes) > 0) {
906
-			return $collectionTypes;
907
-		}
908
-		return false;
909
-	}
910
-
911
-	/**
912
-	 * Get the owners of items shared with a user.
913
-	 *
914
-	 * @param string $user The user the items are shared with.
915
-	 * @param string $type The type of the items shared with the user.
916
-	 * @param boolean $includeCollections Include collection item types (optional)
917
-	 * @param boolean $includeOwner include owner in the list of users the item is shared with (optional)
918
-	 * @return array
919
-	 */
920
-	public static function getSharedItemsOwners($user, $type, $includeCollections = false, $includeOwner = false) {
921
-		// First, we find out if $type is part of a collection (and if that collection is part of
922
-		// another one and so on).
923
-		$collectionTypes = array();
924
-		if (!$includeCollections || !$collectionTypes = self::getCollectionItemTypes($type)) {
925
-			$collectionTypes[] = $type;
926
-		}
927
-
928
-		// Of these collection types, along with our original $type, we make a
929
-		// list of the ones for which a sharing backend has been registered.
930
-		// FIXME: Ideally, we wouldn't need to nest getItemsSharedWith in this loop but just call it
931
-		// with its $includeCollections parameter set to true. Unfortunately, this fails currently.
932
-		$allMaybeSharedItems = array();
933
-		foreach ($collectionTypes as $collectionType) {
934
-			if (isset(self::$backends[$collectionType])) {
935
-				$allMaybeSharedItems[$collectionType] = self::getItemsSharedWithUser(
936
-					$collectionType,
937
-					$user,
938
-					self::FORMAT_NONE
939
-				);
940
-			}
941
-		}
942
-
943
-		$owners = array();
944
-		if ($includeOwner) {
945
-			$owners[] = $user;
946
-		}
947
-
948
-		// We take a look at all shared items of the given $type (or of the collections it is part of)
949
-		// and find out their owners. Then, we gather the tags for the original $type from all owners,
950
-		// and return them as elements of a list that look like "Tag (owner)".
951
-		foreach ($allMaybeSharedItems as $collectionType => $maybeSharedItems) {
952
-			foreach ($maybeSharedItems as $sharedItem) {
953
-				if (isset($sharedItem['id'])) { //workaround for https://github.com/owncloud/core/issues/2814
954
-					$owners[] = $sharedItem['uid_owner'];
955
-				}
956
-			}
957
-		}
958
-
959
-		return $owners;
960
-	}
961
-
962
-	/**
963
-	 * Get shared items from the database
964
-	 * @param string $itemType
965
-	 * @param string $item Item source or target (optional)
966
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique
967
-	 * @param string $shareWith User or group the item is being shared with
968
-	 * @param string $uidOwner User that is the owner of shared items (optional)
969
-	 * @param int $format Format to convert items to with formatItems() (optional)
970
-	 * @param mixed $parameters to pass to formatItems() (optional)
971
-	 * @param int $limit Number of items to return, -1 to return all matches (optional)
972
-	 * @param boolean $includeCollections Include collection item types (optional)
973
-	 * @param boolean $itemShareWithBySource (optional)
974
-	 * @param boolean $checkExpireDate
975
-	 * @return array
976
-	 *
977
-	 * See public functions getItem(s)... for parameter usage
978
-	 *
979
-	 */
980
-	public static function getItems($itemType, $item = null, $shareType = null, $shareWith = null,
981
-									$uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1,
982
-									$includeCollections = false, $itemShareWithBySource = false, $checkExpireDate  = true) {
983
-		if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_enabled', 'yes') != 'yes') {
984
-			return array();
985
-		}
986
-		$backend = self::getBackend($itemType);
987
-		$collectionTypes = false;
988
-		// Get filesystem root to add it to the file target and remove from the
989
-		// file source, match file_source with the file cache
990
-		if ($itemType == 'file' || $itemType == 'folder') {
991
-			if(!is_null($uidOwner)) {
992
-				$root = \OC\Files\Filesystem::getRoot();
993
-			} else {
994
-				$root = '';
995
-			}
996
-			$where = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` ';
997
-			if (!isset($item)) {
998
-				$where .= ' AND `file_target` IS NOT NULL ';
999
-			}
1000
-			$where .= 'INNER JOIN `*PREFIX*storages` ON `numeric_id` = `*PREFIX*filecache`.`storage` ';
1001
-			$fileDependent = true;
1002
-			$queryArgs = array();
1003
-		} else {
1004
-			$fileDependent = false;
1005
-			$root = '';
1006
-			$collectionTypes = self::getCollectionItemTypes($itemType);
1007
-			if ($includeCollections && !isset($item) && $collectionTypes) {
1008
-				// If includeCollections is true, find collections of this item type, e.g. a music album contains songs
1009
-				if (!in_array($itemType, $collectionTypes)) {
1010
-					$itemTypes = array_merge(array($itemType), $collectionTypes);
1011
-				} else {
1012
-					$itemTypes = $collectionTypes;
1013
-				}
1014
-				$placeholders = implode(',', array_fill(0, count($itemTypes), '?'));
1015
-				$where = ' WHERE `item_type` IN ('.$placeholders.'))';
1016
-				$queryArgs = $itemTypes;
1017
-			} else {
1018
-				$where = ' WHERE `item_type` = ?';
1019
-				$queryArgs = array($itemType);
1020
-			}
1021
-		}
1022
-		if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
1023
-			$where .= ' AND `share_type` != ?';
1024
-			$queryArgs[] = self::SHARE_TYPE_LINK;
1025
-		}
1026
-		if (isset($shareType)) {
1027
-			// Include all user and group items
1028
-			if ($shareType == self::$shareTypeUserAndGroups && isset($shareWith)) {
1029
-				$where .= ' AND ((`share_type` in (?, ?) AND `share_with` = ?) ';
1030
-				$queryArgs[] = self::SHARE_TYPE_USER;
1031
-				$queryArgs[] = self::$shareTypeGroupUserUnique;
1032
-				$queryArgs[] = $shareWith;
1033
-
1034
-				$user = \OC::$server->getUserManager()->get($shareWith);
1035
-				$groups = [];
1036
-				if ($user) {
1037
-					$groups = \OC::$server->getGroupManager()->getUserGroupIds($user);
1038
-				}
1039
-				if (!empty($groups)) {
1040
-					$placeholders = implode(',', array_fill(0, count($groups), '?'));
1041
-					$where .= ' OR (`share_type` = ? AND `share_with` IN ('.$placeholders.')) ';
1042
-					$queryArgs[] = self::SHARE_TYPE_GROUP;
1043
-					$queryArgs = array_merge($queryArgs, $groups);
1044
-				}
1045
-				$where .= ')';
1046
-				// Don't include own group shares
1047
-				$where .= ' AND `uid_owner` != ?';
1048
-				$queryArgs[] = $shareWith;
1049
-			} else {
1050
-				$where .= ' AND `share_type` = ?';
1051
-				$queryArgs[] = $shareType;
1052
-				if (isset($shareWith)) {
1053
-					$where .= ' AND `share_with` = ?';
1054
-					$queryArgs[] = $shareWith;
1055
-				}
1056
-			}
1057
-		}
1058
-		if (isset($uidOwner)) {
1059
-			$where .= ' AND `uid_owner` = ?';
1060
-			$queryArgs[] = $uidOwner;
1061
-			if (!isset($shareType)) {
1062
-				// Prevent unique user targets for group shares from being selected
1063
-				$where .= ' AND `share_type` != ?';
1064
-				$queryArgs[] = self::$shareTypeGroupUserUnique;
1065
-			}
1066
-			if ($fileDependent) {
1067
-				$column = 'file_source';
1068
-			} else {
1069
-				$column = 'item_source';
1070
-			}
1071
-		} else {
1072
-			if ($fileDependent) {
1073
-				$column = 'file_target';
1074
-			} else {
1075
-				$column = 'item_target';
1076
-			}
1077
-		}
1078
-		if (isset($item)) {
1079
-			$collectionTypes = self::getCollectionItemTypes($itemType);
1080
-			if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
1081
-				$where .= ' AND (';
1082
-			} else {
1083
-				$where .= ' AND';
1084
-			}
1085
-			// If looking for own shared items, check item_source else check item_target
1086
-			if (isset($uidOwner) || $itemShareWithBySource) {
1087
-				// If item type is a file, file source needs to be checked in case the item was converted
1088
-				if ($fileDependent) {
1089
-					$where .= ' `file_source` = ?';
1090
-					$column = 'file_source';
1091
-				} else {
1092
-					$where .= ' `item_source` = ?';
1093
-					$column = 'item_source';
1094
-				}
1095
-			} else {
1096
-				if ($fileDependent) {
1097
-					$where .= ' `file_target` = ?';
1098
-					$item = \OC\Files\Filesystem::normalizePath($item);
1099
-				} else {
1100
-					$where .= ' `item_target` = ?';
1101
-				}
1102
-			}
1103
-			$queryArgs[] = $item;
1104
-			if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
1105
-				$placeholders = implode(',', array_fill(0, count($collectionTypes), '?'));
1106
-				$where .= ' OR `item_type` IN ('.$placeholders.'))';
1107
-				$queryArgs = array_merge($queryArgs, $collectionTypes);
1108
-			}
1109
-		}
1110
-
1111
-		if ($shareType == self::$shareTypeUserAndGroups && $limit === 1) {
1112
-			// Make sure the unique user target is returned if it exists,
1113
-			// unique targets should follow the group share in the database
1114
-			// If the limit is not 1, the filtering can be done later
1115
-			$where .= ' ORDER BY `*PREFIX*share`.`id` DESC';
1116
-		} else {
1117
-			$where .= ' ORDER BY `*PREFIX*share`.`id` ASC';
1118
-		}
1119
-
1120
-		if ($limit != -1 && !$includeCollections) {
1121
-			// The limit must be at least 3, because filtering needs to be done
1122
-			if ($limit < 3) {
1123
-				$queryLimit = 3;
1124
-			} else {
1125
-				$queryLimit = $limit;
1126
-			}
1127
-		} else {
1128
-			$queryLimit = null;
1129
-		}
1130
-		$select = self::createSelectStatement($format, $fileDependent, $uidOwner);
1131
-		$root = strlen($root);
1132
-		$query = \OC_DB::prepare('SELECT '.$select.' FROM `*PREFIX*share` '.$where, $queryLimit);
1133
-		$result = $query->execute($queryArgs);
1134
-		if ($result === false) {
1135
-			\OCP\Util::writeLog('OCP\Share',
1136
-				\OC_DB::getErrorMessage() . ', select=' . $select . ' where=',
1137
-				ILogger::ERROR);
1138
-		}
1139
-		$items = array();
1140
-		$targets = array();
1141
-		$switchedItems = array();
1142
-		$mounts = array();
1143
-		while ($row = $result->fetchRow()) {
1144
-			self::transformDBResults($row);
1145
-			// Filter out duplicate group shares for users with unique targets
1146
-			if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
1147
-				continue;
1148
-			}
1149
-			if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) {
1150
-				$row['share_type'] = self::SHARE_TYPE_GROUP;
1151
-				$row['unique_name'] = true; // remember that we use a unique name for this user
1152
-				$row['share_with'] = $items[$row['parent']]['share_with'];
1153
-				// if the group share was unshared from the user we keep the permission, otherwise
1154
-				// we take the permission from the parent because this is always the up-to-date
1155
-				// permission for the group share
1156
-				if ($row['permissions'] > 0) {
1157
-					$row['permissions'] = $items[$row['parent']]['permissions'];
1158
-				}
1159
-				// Remove the parent group share
1160
-				unset($items[$row['parent']]);
1161
-				if ($row['permissions'] == 0) {
1162
-					continue;
1163
-				}
1164
-			} else if (!isset($uidOwner)) {
1165
-				// Check if the same target already exists
1166
-				if (isset($targets[$row['id']])) {
1167
-					// Check if the same owner shared with the user twice
1168
-					// through a group and user share - this is allowed
1169
-					$id = $targets[$row['id']];
1170
-					if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) {
1171
-						// Switch to group share type to ensure resharing conditions aren't bypassed
1172
-						if ($items[$id]['share_type'] != self::SHARE_TYPE_GROUP) {
1173
-							$items[$id]['share_type'] = self::SHARE_TYPE_GROUP;
1174
-							$items[$id]['share_with'] = $row['share_with'];
1175
-						}
1176
-						// Switch ids if sharing permission is granted on only
1177
-						// one share to ensure correct parent is used if resharing
1178
-						if (~(int)$items[$id]['permissions'] & \OCP\Constants::PERMISSION_SHARE
1179
-							&& (int)$row['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
1180
-							$items[$row['id']] = $items[$id];
1181
-							$switchedItems[$id] = $row['id'];
1182
-							unset($items[$id]);
1183
-							$id = $row['id'];
1184
-						}
1185
-						$items[$id]['permissions'] |= (int)$row['permissions'];
1186
-
1187
-					}
1188
-					continue;
1189
-				} elseif (!empty($row['parent'])) {
1190
-					$targets[$row['parent']] = $row['id'];
1191
-				}
1192
-			}
1193
-			// Remove root from file source paths if retrieving own shared items
1194
-			if (isset($uidOwner) && isset($row['path'])) {
1195
-				if (isset($row['parent'])) {
1196
-					$query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?');
1197
-					$parentResult = $query->execute(array($row['parent']));
1198
-					if ($result === false) {
1199
-						\OCP\Util::writeLog('OCP\Share', 'Can\'t select parent: ' .
1200
-							\OC_DB::getErrorMessage() . ', select=' . $select . ' where=' . $where,
1201
-							ILogger::ERROR);
1202
-					} else {
1203
-						$parentRow = $parentResult->fetchRow();
1204
-						$tmpPath = $parentRow['file_target'];
1205
-						// find the right position where the row path continues from the target path
1206
-						$pos = strrpos($row['path'], $parentRow['file_target']);
1207
-						$subPath = substr($row['path'], $pos);
1208
-						$splitPath = explode('/', $subPath);
1209
-						foreach (array_slice($splitPath, 2) as $pathPart) {
1210
-							$tmpPath = $tmpPath . '/' . $pathPart;
1211
-						}
1212
-						$row['path'] = $tmpPath;
1213
-					}
1214
-				} else {
1215
-					if (!isset($mounts[$row['storage']])) {
1216
-						$mountPoints = \OC\Files\Filesystem::getMountByNumericId($row['storage']);
1217
-						if (is_array($mountPoints) && !empty($mountPoints)) {
1218
-							$mounts[$row['storage']] = current($mountPoints);
1219
-						}
1220
-					}
1221
-					if (!empty($mounts[$row['storage']])) {
1222
-						$path = $mounts[$row['storage']]->getMountPoint().$row['path'];
1223
-						$relPath = substr($path, $root); // path relative to data/user
1224
-						$row['path'] = rtrim($relPath, '/');
1225
-					}
1226
-				}
1227
-			}
1228
-
1229
-			if($checkExpireDate) {
1230
-				if (self::expireItem($row)) {
1231
-					continue;
1232
-				}
1233
-			}
1234
-			// Check if resharing is allowed, if not remove share permission
1235
-			if (isset($row['permissions']) && (!self::isResharingAllowed() | \OCP\Util::isSharingDisabledForUser())) {
1236
-				$row['permissions'] &= ~\OCP\Constants::PERMISSION_SHARE;
1237
-			}
1238
-			// Add display names to result
1239
-			$row['share_with_displayname'] = $row['share_with'];
1240
-			if ( isset($row['share_with']) && $row['share_with'] != '' &&
1241
-				$row['share_type'] === self::SHARE_TYPE_USER) {
1242
-				$shareWithUser = \OC::$server->getUserManager()->get($row['share_with']);
1243
-				$row['share_with_displayname'] = $shareWithUser === null ? $row['share_with'] : $shareWithUser->getDisplayName();
1244
-			} else if(isset($row['share_with']) && $row['share_with'] != '' &&
1245
-				$row['share_type'] === self::SHARE_TYPE_REMOTE) {
1246
-				$addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD']);
1247
-				foreach ($addressBookEntries as $entry) {
1248
-					foreach ($entry['CLOUD'] as $cloudID) {
1249
-						if ($cloudID === $row['share_with']) {
1250
-							$row['share_with_displayname'] = $entry['FN'];
1251
-						}
1252
-					}
1253
-				}
1254
-			}
1255
-			if ( isset($row['uid_owner']) && $row['uid_owner'] != '') {
1256
-				$ownerUser = \OC::$server->getUserManager()->get($row['uid_owner']);
1257
-				$row['displayname_owner'] = $ownerUser === null ? $row['uid_owner'] : $ownerUser->getDisplayName();
1258
-			}
1259
-
1260
-			if ($row['permissions'] > 0) {
1261
-				$items[$row['id']] = $row;
1262
-			}
1263
-
1264
-		}
1265
-
1266
-		// group items if we are looking for items shared with the current user
1267
-		if (isset($shareWith) && $shareWith === \OCP\User::getUser()) {
1268
-			$items = self::groupItems($items, $itemType);
1269
-		}
1270
-
1271
-		if (!empty($items)) {
1272
-			$collectionItems = array();
1273
-			foreach ($items as &$row) {
1274
-				// Return only the item instead of a 2-dimensional array
1275
-				if ($limit == 1 && $row[$column] == $item && ($row['item_type'] == $itemType || $itemType == 'file')) {
1276
-					if ($format == self::FORMAT_NONE) {
1277
-						return $row;
1278
-					} else {
1279
-						break;
1280
-					}
1281
-				}
1282
-				// Check if this is a collection of the requested item type
1283
-				if ($includeCollections && $collectionTypes && $row['item_type'] !== 'folder' && in_array($row['item_type'], $collectionTypes)) {
1284
-					if (($collectionBackend = self::getBackend($row['item_type']))
1285
-						&& $collectionBackend instanceof \OCP\Share_Backend_Collection) {
1286
-						// Collections can be inside collections, check if the item is a collection
1287
-						if (isset($item) && $row['item_type'] == $itemType && $row[$column] == $item) {
1288
-							$collectionItems[] = $row;
1289
-						} else {
1290
-							$collection = array();
1291
-							$collection['item_type'] = $row['item_type'];
1292
-							if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
1293
-								$collection['path'] = basename($row['path']);
1294
-							}
1295
-							$row['collection'] = $collection;
1296
-							// Fetch all of the children sources
1297
-							$children = $collectionBackend->getChildren($row[$column]);
1298
-							foreach ($children as $child) {
1299
-								$childItem = $row;
1300
-								$childItem['item_type'] = $itemType;
1301
-								if ($row['item_type'] != 'file' && $row['item_type'] != 'folder') {
1302
-									$childItem['item_source'] = $child['source'];
1303
-									$childItem['item_target'] = $child['target'];
1304
-								}
1305
-								if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
1306
-									if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
1307
-										$childItem['file_source'] = $child['source'];
1308
-									} else { // TODO is this really needed if we already know that we use the file backend?
1309
-										$meta = \OC\Files\Filesystem::getFileInfo($child['file_path']);
1310
-										$childItem['file_source'] = $meta['fileid'];
1311
-									}
1312
-									$childItem['file_target'] =
1313
-										\OC\Files\Filesystem::normalizePath($child['file_path']);
1314
-								}
1315
-								if (isset($item)) {
1316
-									if ($childItem[$column] == $item) {
1317
-										// Return only the item instead of a 2-dimensional array
1318
-										if ($limit == 1) {
1319
-											if ($format == self::FORMAT_NONE) {
1320
-												return $childItem;
1321
-											} else {
1322
-												// Unset the items array and break out of both loops
1323
-												$items = array();
1324
-												$items[] = $childItem;
1325
-												break 2;
1326
-											}
1327
-										} else {
1328
-											$collectionItems[] = $childItem;
1329
-										}
1330
-									}
1331
-								} else {
1332
-									$collectionItems[] = $childItem;
1333
-								}
1334
-							}
1335
-						}
1336
-					}
1337
-					// Remove collection item
1338
-					$toRemove = $row['id'];
1339
-					if (array_key_exists($toRemove, $switchedItems)) {
1340
-						$toRemove = $switchedItems[$toRemove];
1341
-					}
1342
-					unset($items[$toRemove]);
1343
-				} elseif ($includeCollections && $collectionTypes && in_array($row['item_type'], $collectionTypes)) {
1344
-					// FIXME: Thats a dirty hack to improve file sharing performance,
1345
-					// see github issue #10588 for more details
1346
-					// Need to find a solution which works for all back-ends
1347
-					$collectionBackend = self::getBackend($row['item_type']);
1348
-					$sharedParents = $collectionBackend->getParents($row['item_source']);
1349
-					foreach ($sharedParents as $parent) {
1350
-						$collectionItems[] = $parent;
1351
-					}
1352
-				}
1353
-			}
1354
-			if (!empty($collectionItems)) {
1355
-				$collectionItems = array_unique($collectionItems, SORT_REGULAR);
1356
-				$items = array_merge($items, $collectionItems);
1357
-			}
1358
-
1359
-			// filter out invalid items, these can appear when subshare entries exist
1360
-			// for a group in which the requested user isn't a member any more
1361
-			$items = array_filter($items, function($item) {
1362
-				return $item['share_type'] !== self::$shareTypeGroupUserUnique;
1363
-			});
1364
-
1365
-			return self::formatResult($items, $column, $backend, $format, $parameters);
1366
-		} elseif ($includeCollections && $collectionTypes && in_array('folder', $collectionTypes)) {
1367
-			// FIXME: Thats a dirty hack to improve file sharing performance,
1368
-			// see github issue #10588 for more details
1369
-			// Need to find a solution which works for all back-ends
1370
-			$collectionItems = array();
1371
-			$collectionBackend = self::getBackend('folder');
1372
-			$sharedParents = $collectionBackend->getParents($item, $shareWith, $uidOwner);
1373
-			foreach ($sharedParents as $parent) {
1374
-				$collectionItems[] = $parent;
1375
-			}
1376
-			if ($limit === 1) {
1377
-				return reset($collectionItems);
1378
-			}
1379
-			return self::formatResult($collectionItems, $column, $backend, $format, $parameters);
1380
-		}
1381
-
1382
-		return array();
1383
-	}
1384
-
1385
-	/**
1386
-	 * group items with link to the same source
1387
-	 *
1388
-	 * @param array $items
1389
-	 * @param string $itemType
1390
-	 * @return array of grouped items
1391
-	 */
1392
-	protected static function groupItems($items, $itemType) {
1393
-
1394
-		$fileSharing = $itemType === 'file' || $itemType === 'folder';
1395
-
1396
-		$result = array();
1397
-
1398
-		foreach ($items as $item) {
1399
-			$grouped = false;
1400
-			foreach ($result as $key => $r) {
1401
-				// for file/folder shares we need to compare file_source, otherwise we compare item_source
1402
-				// only group shares if they already point to the same target, otherwise the file where shared
1403
-				// before grouping of shares was added. In this case we don't group them toi avoid confusions
1404
-				if (( $fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) ||
1405
-					(!$fileSharing && $item['item_source'] === $r['item_source'] && $item['item_target'] === $r['item_target'])) {
1406
-					// add the first item to the list of grouped shares
1407
-					if (!isset($result[$key]['grouped'])) {
1408
-						$result[$key]['grouped'][] = $result[$key];
1409
-					}
1410
-					$result[$key]['permissions'] = (int) $item['permissions'] | (int) $r['permissions'];
1411
-					$result[$key]['grouped'][] = $item;
1412
-					$grouped = true;
1413
-					break;
1414
-				}
1415
-			}
1416
-
1417
-			if (!$grouped) {
1418
-				$result[] = $item;
1419
-			}
1420
-
1421
-		}
1422
-
1423
-		return $result;
1424
-	}
1425
-
1426
-	/**
1427
-	 * Put shared item into the database
1428
-	 * @param string $itemType Item type
1429
-	 * @param string $itemSource Item source
1430
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
1431
-	 * @param string $shareWith User or group the item is being shared with
1432
-	 * @param string $uidOwner User that is the owner of shared item
1433
-	 * @param int $permissions CRUDS permissions
1434
-	 * @param boolean|array $parentFolder Parent folder target (optional)
1435
-	 * @param string $token (optional)
1436
-	 * @param string $itemSourceName name of the source item (optional)
1437
-	 * @param \DateTime $expirationDate (optional)
1438
-	 * @throws \Exception
1439
-	 * @return mixed id of the new share or false
1440
-	 */
1441
-	private static function put($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
1442
-								$permissions, $parentFolder = null, $token = null, $itemSourceName = null, \DateTime $expirationDate = null) {
1443
-
1444
-		$queriesToExecute = array();
1445
-		$suggestedItemTarget = null;
1446
-		$groupFileTarget = $fileTarget = $suggestedFileTarget = $filePath = '';
1447
-		$groupItemTarget = $itemTarget = $fileSource = $parent = 0;
1448
-
1449
-		$result = self::checkReshare($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, $itemSourceName, $expirationDate);
1450
-		if(!empty($result)) {
1451
-			$parent = $result['parent'];
1452
-			$itemSource = $result['itemSource'];
1453
-			$fileSource = $result['fileSource'];
1454
-			$suggestedItemTarget = $result['suggestedItemTarget'];
1455
-			$suggestedFileTarget = $result['suggestedFileTarget'];
1456
-			$filePath = $result['filePath'];
1457
-		}
1458
-
1459
-		$isGroupShare = false;
1460
-		if ($shareType == self::SHARE_TYPE_GROUP) {
1461
-			$isGroupShare = true;
1462
-			if (isset($shareWith['users'])) {
1463
-				$users = $shareWith['users'];
1464
-			} else {
1465
-				$group = \OC::$server->getGroupManager()->get($shareWith['group']);
1466
-				if ($group) {
1467
-					$users = $group->searchUsers('', -1, 0);
1468
-					$userIds = [];
1469
-					foreach ($users as $user) {
1470
-						$userIds[] = $user->getUID();
1471
-					}
1472
-					$users = $userIds;
1473
-				} else {
1474
-					$users = [];
1475
-				}
1476
-			}
1477
-			// remove current user from list
1478
-			if (in_array(\OCP\User::getUser(), $users)) {
1479
-				unset($users[array_search(\OCP\User::getUser(), $users)]);
1480
-			}
1481
-			$groupItemTarget = Helper::generateTarget($itemType, $itemSource,
1482
-				$shareType, $shareWith['group'], $uidOwner, $suggestedItemTarget);
1483
-			$groupFileTarget = Helper::generateTarget($itemType, $itemSource,
1484
-				$shareType, $shareWith['group'], $uidOwner, $filePath);
1485
-
1486
-			// add group share to table and remember the id as parent
1487
-			$queriesToExecute['groupShare'] = array(
1488
-				'itemType'			=> $itemType,
1489
-				'itemSource'		=> $itemSource,
1490
-				'itemTarget'		=> $groupItemTarget,
1491
-				'shareType'			=> $shareType,
1492
-				'shareWith'			=> $shareWith['group'],
1493
-				'uidOwner'			=> $uidOwner,
1494
-				'permissions'		=> $permissions,
1495
-				'shareTime'			=> time(),
1496
-				'fileSource'		=> $fileSource,
1497
-				'fileTarget'		=> $groupFileTarget,
1498
-				'token'				=> $token,
1499
-				'parent'			=> $parent,
1500
-				'expiration'		=> $expirationDate,
1501
-			);
1502
-
1503
-		} else {
1504
-			$users = array($shareWith);
1505
-			$itemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
1506
-				$suggestedItemTarget);
1507
-		}
1508
-
1509
-		$run = true;
1510
-		$error = '';
1511
-		$preHookData = array(
1512
-			'itemType' => $itemType,
1513
-			'itemSource' => $itemSource,
1514
-			'shareType' => $shareType,
1515
-			'uidOwner' => $uidOwner,
1516
-			'permissions' => $permissions,
1517
-			'fileSource' => $fileSource,
1518
-			'expiration' => $expirationDate,
1519
-			'token' => $token,
1520
-			'run' => &$run,
1521
-			'error' => &$error
1522
-		);
1523
-
1524
-		$preHookData['itemTarget'] = $isGroupShare ? $groupItemTarget : $itemTarget;
1525
-		$preHookData['shareWith'] = $isGroupShare ? $shareWith['group'] : $shareWith;
1526
-
1527
-		\OC_Hook::emit(\OCP\Share::class, 'pre_shared', $preHookData);
1528
-
1529
-		if ($run === false) {
1530
-			throw new \Exception($error);
1531
-		}
1532
-
1533
-		foreach ($users as $user) {
1534
-			$sourceId = ($itemType === 'file' || $itemType === 'folder') ? $fileSource : $itemSource;
1535
-			$sourceExists = self::getItemSharedWithBySource($itemType, $sourceId, self::FORMAT_NONE, null, true, $user);
1536
-
1537
-			$userShareType = $isGroupShare ? self::$shareTypeGroupUserUnique : $shareType;
1538
-
1539
-			if ($sourceExists && $sourceExists['item_source'] === $itemSource) {
1540
-				$fileTarget = $sourceExists['file_target'];
1541
-				$itemTarget = $sourceExists['item_target'];
1542
-
1543
-				// for group shares we don't need a additional entry if the target is the same
1544
-				if($isGroupShare && $groupItemTarget === $itemTarget) {
1545
-					continue;
1546
-				}
1547
-
1548
-			} elseif(!$sourceExists && !$isGroupShare)  {
1549
-
1550
-				$itemTarget = Helper::generateTarget($itemType, $itemSource, $userShareType, $user,
1551
-					$uidOwner, $suggestedItemTarget, $parent);
1552
-				if (isset($fileSource)) {
1553
-					if ($parentFolder) {
1554
-						if ($parentFolder === true) {
1555
-							$fileTarget = Helper::generateTarget('file', $filePath, $userShareType, $user,
1556
-								$uidOwner, $suggestedFileTarget, $parent);
1557
-							if ($fileTarget != $groupFileTarget) {
1558
-								$parentFolders[$user]['folder'] = $fileTarget;
1559
-							}
1560
-						} else if (isset($parentFolder[$user])) {
1561
-							$fileTarget = $parentFolder[$user]['folder'].$itemSource;
1562
-							$parent = $parentFolder[$user]['id'];
1563
-						}
1564
-					} else {
1565
-						$fileTarget = Helper::generateTarget('file', $filePath, $userShareType,
1566
-							$user, $uidOwner, $suggestedFileTarget, $parent);
1567
-					}
1568
-				} else {
1569
-					$fileTarget = null;
1570
-				}
1571
-
1572
-			} else {
1573
-
1574
-				// group share which doesn't exists until now, check if we need a unique target for this user
1575
-
1576
-				$itemTarget = Helper::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $user,
1577
-					$uidOwner, $suggestedItemTarget, $parent);
1578
-
1579
-				// do we also need a file target
1580
-				if (isset($fileSource)) {
1581
-					$fileTarget = Helper::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $user,
1582
-						$uidOwner, $suggestedFileTarget, $parent);
1583
-				} else {
1584
-					$fileTarget = null;
1585
-				}
1586
-
1587
-				if (($itemTarget === $groupItemTarget) &&
1588
-					(!isset($fileSource) || $fileTarget === $groupFileTarget)) {
1589
-					continue;
1590
-				}
1591
-			}
1592
-
1593
-			$queriesToExecute[] = array(
1594
-				'itemType'			=> $itemType,
1595
-				'itemSource'		=> $itemSource,
1596
-				'itemTarget'		=> $itemTarget,
1597
-				'shareType'			=> $userShareType,
1598
-				'shareWith'			=> $user,
1599
-				'uidOwner'			=> $uidOwner,
1600
-				'permissions'		=> $permissions,
1601
-				'shareTime'			=> time(),
1602
-				'fileSource'		=> $fileSource,
1603
-				'fileTarget'		=> $fileTarget,
1604
-				'token'				=> $token,
1605
-				'parent'			=> $parent,
1606
-				'expiration'		=> $expirationDate,
1607
-			);
1608
-
1609
-		}
1610
-
1611
-		$id = false;
1612
-		if ($isGroupShare) {
1613
-			$id = self::insertShare($queriesToExecute['groupShare']);
1614
-			// Save this id, any extra rows for this group share will need to reference it
1615
-			$parent = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share');
1616
-			unset($queriesToExecute['groupShare']);
1617
-		}
1618
-
1619
-		foreach ($queriesToExecute as $shareQuery) {
1620
-			$shareQuery['parent'] = $parent;
1621
-			$id = self::insertShare($shareQuery);
1622
-		}
1623
-
1624
-		$postHookData = array(
1625
-			'itemType' => $itemType,
1626
-			'itemSource' => $itemSource,
1627
-			'parent' => $parent,
1628
-			'shareType' => $shareType,
1629
-			'uidOwner' => $uidOwner,
1630
-			'permissions' => $permissions,
1631
-			'fileSource' => $fileSource,
1632
-			'id' => $parent,
1633
-			'token' => $token,
1634
-			'expirationDate' => $expirationDate,
1635
-		);
1636
-
1637
-		$postHookData['shareWith'] = $isGroupShare ? $shareWith['group'] : $shareWith;
1638
-		$postHookData['itemTarget'] = $isGroupShare ? $groupItemTarget : $itemTarget;
1639
-		$postHookData['fileTarget'] = $isGroupShare ? $groupFileTarget : $fileTarget;
1640
-
1641
-		\OC_Hook::emit(\OCP\Share::class, 'post_shared', $postHookData);
1642
-
1643
-
1644
-		return $id ? $id : false;
1645
-	}
1646
-
1647
-	/**
1648
-	 * @param string $itemType
1649
-	 * @param string $itemSource
1650
-	 * @param int $shareType
1651
-	 * @param string $shareWith
1652
-	 * @param string $uidOwner
1653
-	 * @param int $permissions
1654
-	 * @param string|null $itemSourceName
1655
-	 * @param null|\DateTime $expirationDate
1656
-	 */
1657
-	private static function checkReshare($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, $itemSourceName, $expirationDate) {
1658
-		$backend = self::getBackend($itemType);
1659
-
1660
-		$l = \OC::$server->getL10N('lib');
1661
-		$result = array();
1662
-
1663
-		$column = ($itemType === 'file' || $itemType === 'folder') ? 'file_source' : 'item_source';
1664
-
1665
-		$checkReshare = self::getItemSharedWithBySource($itemType, $itemSource, self::FORMAT_NONE, null, true);
1666
-		if ($checkReshare) {
1667
-			// Check if attempting to share back to owner
1668
-			if ($checkReshare['uid_owner'] == $shareWith && $shareType == self::SHARE_TYPE_USER) {
1669
-				$message = 'Sharing %1$s failed, because the user %2$s is the original sharer';
1670
-				$message_t = $l->t('Sharing failed, because the user %s is the original sharer', [$shareWith]);
1671
-
1672
-				\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
1673
-				throw new \Exception($message_t);
1674
-			}
1675
-		}
1676
-
1677
-		if ($checkReshare && $checkReshare['uid_owner'] !== \OC_User::getUser()) {
1678
-			// Check if share permissions is granted
1679
-			if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
1680
-				if (~(int)$checkReshare['permissions'] & $permissions) {
1681
-					$message = 'Sharing %1$s failed, because the permissions exceed permissions granted to %2$s';
1682
-					$message_t = $l->t('Sharing %1$s failed, because the permissions exceed permissions granted to %2$s', array($itemSourceName, $uidOwner));
1683
-
1684
-					\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $uidOwner), ILogger::DEBUG);
1685
-					throw new \Exception($message_t);
1686
-				} else {
1687
-					// TODO Don't check if inside folder
1688
-					$result['parent'] = $checkReshare['id'];
1689
-
1690
-					$result['expirationDate'] = $expirationDate;
1691
-					// $checkReshare['expiration'] could be null and then is always less than any value
1692
-					if(isset($checkReshare['expiration']) && $checkReshare['expiration'] < $expirationDate) {
1693
-						$result['expirationDate'] = $checkReshare['expiration'];
1694
-					}
1695
-
1696
-					// only suggest the same name as new target if it is a reshare of the
1697
-					// same file/folder and not the reshare of a child
1698
-					if ($checkReshare[$column] === $itemSource) {
1699
-						$result['filePath'] = $checkReshare['file_target'];
1700
-						$result['itemSource'] = $checkReshare['item_source'];
1701
-						$result['fileSource'] = $checkReshare['file_source'];
1702
-						$result['suggestedItemTarget'] = $checkReshare['item_target'];
1703
-						$result['suggestedFileTarget'] = $checkReshare['file_target'];
1704
-					} else {
1705
-						$result['filePath'] = ($backend instanceof \OCP\Share_Backend_File_Dependent) ? $backend->getFilePath($itemSource, $uidOwner) : null;
1706
-						$result['suggestedItemTarget'] = null;
1707
-						$result['suggestedFileTarget'] = null;
1708
-						$result['itemSource'] = $itemSource;
1709
-						$result['fileSource'] = ($backend instanceof \OCP\Share_Backend_File_Dependent) ? $itemSource : null;
1710
-					}
1711
-				}
1712
-			} else {
1713
-				$message = 'Sharing %s failed, because resharing is not allowed';
1714
-				$message_t = $l->t('Sharing %s failed, because resharing is not allowed', array($itemSourceName));
1715
-
1716
-				\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
1717
-				throw new \Exception($message_t);
1718
-			}
1719
-		} else {
1720
-			$result['parent'] = null;
1721
-			$result['suggestedItemTarget'] = null;
1722
-			$result['suggestedFileTarget'] = null;
1723
-			$result['itemSource'] = $itemSource;
1724
-			$result['expirationDate'] = $expirationDate;
1725
-			if (!$backend->isValidSource($itemSource, $uidOwner)) {
1726
-				$message = 'Sharing %1$s failed, because the sharing backend for '
1727
-					.'%2$s could not find its source';
1728
-				$message_t = $l->t('Sharing %1$s failed, because the sharing backend for %2$s could not find its source', array($itemSource, $itemType));
1729
-				\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSource, $itemType), ILogger::DEBUG);
1730
-				throw new \Exception($message_t);
1731
-			}
1732
-			if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
1733
-				$result['filePath'] = $backend->getFilePath($itemSource, $uidOwner);
1734
-				if ($itemType == 'file' || $itemType == 'folder') {
1735
-					$result['fileSource'] = $itemSource;
1736
-				} else {
1737
-					$meta = \OC\Files\Filesystem::getFileInfo($result['filePath']);
1738
-					$result['fileSource'] = $meta['fileid'];
1739
-				}
1740
-				if ($result['fileSource'] == -1) {
1741
-					$message = 'Sharing %s failed, because the file could not be found in the file cache';
1742
-					$message_t = $l->t('Sharing %s failed, because the file could not be found in the file cache', array($itemSource));
1743
-
1744
-					\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSource), ILogger::DEBUG);
1745
-					throw new \Exception($message_t);
1746
-				}
1747
-			} else {
1748
-				$result['filePath'] = null;
1749
-				$result['fileSource'] = null;
1750
-			}
1751
-		}
1752
-
1753
-		return $result;
1754
-	}
1755
-
1756
-	/**
1757
-	 *
1758
-	 * @param array $shareData
1759
-	 * @return mixed false in case of a failure or the id of the new share
1760
-	 */
1761
-	private static function insertShare(array $shareData) {
1762
-
1763
-		$query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` ('
1764
-			.' `item_type`, `item_source`, `item_target`, `share_type`,'
1765
-			.' `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,'
1766
-			.' `file_target`, `token`, `parent`, `expiration`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)');
1767
-		$query->bindValue(1, $shareData['itemType']);
1768
-		$query->bindValue(2, $shareData['itemSource']);
1769
-		$query->bindValue(3, $shareData['itemTarget']);
1770
-		$query->bindValue(4, $shareData['shareType']);
1771
-		$query->bindValue(5, $shareData['shareWith']);
1772
-		$query->bindValue(6, $shareData['uidOwner']);
1773
-		$query->bindValue(7, $shareData['permissions']);
1774
-		$query->bindValue(8, $shareData['shareTime']);
1775
-		$query->bindValue(9, $shareData['fileSource']);
1776
-		$query->bindValue(10, $shareData['fileTarget']);
1777
-		$query->bindValue(11, $shareData['token']);
1778
-		$query->bindValue(12, $shareData['parent']);
1779
-		$query->bindValue(13, $shareData['expiration'], 'datetime');
1780
-		$result = $query->execute();
1781
-
1782
-		$id = false;
1783
-		if ($result) {
1784
-			$id =  \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share');
1785
-		}
1786
-
1787
-		return $id;
1788
-
1789
-	}
1790
-
1791
-	/**
1792
-	 * In case a password protected link is not yet authenticated this function will return false
1793
-	 *
1794
-	 * @param array $linkItem
1795
-	 * @return boolean
1796
-	 */
1797
-	public static function checkPasswordProtectedShare(array $linkItem) {
1798
-		if (!isset($linkItem['share_with'])) {
1799
-			return true;
1800
-		}
1801
-		if (!isset($linkItem['share_type'])) {
1802
-			return true;
1803
-		}
1804
-		if (!isset($linkItem['id'])) {
1805
-			return true;
1806
-		}
1807
-
1808
-		if ($linkItem['share_type'] != \OCP\Share::SHARE_TYPE_LINK) {
1809
-			return true;
1810
-		}
1811
-
1812
-		if ( \OC::$server->getSession()->exists('public_link_authenticated')
1813
-			&& \OC::$server->getSession()->get('public_link_authenticated') === (string)$linkItem['id'] ) {
1814
-			return true;
1815
-		}
1816
-
1817
-		return false;
1818
-	}
1819
-
1820
-	/**
1821
-	 * construct select statement
1822
-	 * @param int $format
1823
-	 * @param boolean $fileDependent ist it a file/folder share or a generla share
1824
-	 * @param string $uidOwner
1825
-	 * @return string select statement
1826
-	 */
1827
-	private static function createSelectStatement($format, $fileDependent, $uidOwner = null) {
1828
-		$select = '*';
1829
-		if ($format == self::FORMAT_STATUSES) {
1830
-			if ($fileDependent) {
1831
-				$select = '`*PREFIX*share`.`id`, `*PREFIX*share`.`parent`, `share_type`, `path`, `storage`, '
1832
-					. '`share_with`, `uid_owner` , `file_source`, `stime`, `*PREFIX*share`.`permissions`, '
1833
-					. '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`, '
1834
-					. '`uid_initiator`';
1835
-			} else {
1836
-				$select = '`id`, `parent`, `share_type`, `share_with`, `uid_owner`, `item_source`, `stime`, `*PREFIX*share`.`permissions`';
1837
-			}
1838
-		} else {
1839
-			if (isset($uidOwner)) {
1840
-				if ($fileDependent) {
1841
-					$select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,'
1842
-						. ' `share_type`, `share_with`, `file_source`, `file_target`, `path`, `*PREFIX*share`.`permissions`, `stime`,'
1843
-						. ' `expiration`, `token`, `storage`, `mail_send`, `uid_owner`, '
1844
-						. '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`';
1845
-				} else {
1846
-					$select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `*PREFIX*share`.`permissions`,'
1847
-						. ' `stime`, `file_source`, `expiration`, `token`, `mail_send`, `uid_owner`';
1848
-				}
1849
-			} else {
1850
-				if ($fileDependent) {
1851
-					if ($format == \OCA\Files_Sharing\ShareBackend\File::FORMAT_GET_FOLDER_CONTENTS || $format == \OCA\Files_Sharing\ShareBackend\File::FORMAT_FILE_APP_ROOT) {
1852
-						$select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`, `uid_owner`, '
1853
-							. '`share_type`, `share_with`, `file_source`, `path`, `file_target`, `stime`, '
1854
-							. '`*PREFIX*share`.`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, '
1855
-							. '`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`, `mail_send`';
1856
-					} else {
1857
-						$select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`,'
1858
-							. '`*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`,'
1859
-							. '`file_source`, `path`, `file_target`, `*PREFIX*share`.`permissions`,'
1860
-						    . '`stime`, `expiration`, `token`, `storage`, `mail_send`,'
1861
-							. '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`';
1862
-					}
1863
-				}
1864
-			}
1865
-		}
1866
-		return $select;
1867
-	}
1868
-
1869
-
1870
-	/**
1871
-	 * transform db results
1872
-	 * @param array $row result
1873
-	 */
1874
-	private static function transformDBResults(&$row) {
1875
-		if (isset($row['id'])) {
1876
-			$row['id'] = (int) $row['id'];
1877
-		}
1878
-		if (isset($row['share_type'])) {
1879
-			$row['share_type'] = (int) $row['share_type'];
1880
-		}
1881
-		if (isset($row['parent'])) {
1882
-			$row['parent'] = (int) $row['parent'];
1883
-		}
1884
-		if (isset($row['file_parent'])) {
1885
-			$row['file_parent'] = (int) $row['file_parent'];
1886
-		}
1887
-		if (isset($row['file_source'])) {
1888
-			$row['file_source'] = (int) $row['file_source'];
1889
-		}
1890
-		if (isset($row['permissions'])) {
1891
-			$row['permissions'] = (int) $row['permissions'];
1892
-		}
1893
-		if (isset($row['storage'])) {
1894
-			$row['storage'] = (int) $row['storage'];
1895
-		}
1896
-		if (isset($row['stime'])) {
1897
-			$row['stime'] = (int) $row['stime'];
1898
-		}
1899
-		if (isset($row['expiration']) && $row['share_type'] !== self::SHARE_TYPE_LINK) {
1900
-			// discard expiration date for non-link shares, which might have been
1901
-			// set by ancient bugs
1902
-			$row['expiration'] = null;
1903
-		}
1904
-	}
1905
-
1906
-	/**
1907
-	 * format result
1908
-	 * @param array $items result
1909
-	 * @param string $column is it a file share or a general share ('file_target' or 'item_target')
1910
-	 * @param \OCP\Share_Backend $backend sharing backend
1911
-	 * @param int $format
1912
-	 * @param array $parameters additional format parameters
1913
-	 * @return array format result
1914
-	 */
1915
-	private static function formatResult($items, $column, $backend, $format = self::FORMAT_NONE , $parameters = null) {
1916
-		if ($format === self::FORMAT_NONE) {
1917
-			return $items;
1918
-		} else if ($format === self::FORMAT_STATUSES) {
1919
-			$statuses = array();
1920
-			foreach ($items as $item) {
1921
-				if ($item['share_type'] === self::SHARE_TYPE_LINK) {
1922
-					if ($item['uid_initiator'] !== \OC::$server->getUserSession()->getUser()->getUID()) {
1923
-						continue;
1924
-					}
1925
-					$statuses[$item[$column]]['link'] = true;
1926
-				} else if (!isset($statuses[$item[$column]])) {
1927
-					$statuses[$item[$column]]['link'] = false;
1928
-				}
1929
-				if (!empty($item['file_target'])) {
1930
-					$statuses[$item[$column]]['path'] = $item['path'];
1931
-				}
1932
-			}
1933
-			return $statuses;
1934
-		} else {
1935
-			return $backend->formatItems($items, $format, $parameters);
1936
-		}
1937
-	}
1938
-
1939
-	/**
1940
-	 * remove protocol from URL
1941
-	 *
1942
-	 * @param string $url
1943
-	 * @return string
1944
-	 */
1945
-	public static function removeProtocolFromUrl($url) {
1946
-		if (strpos($url, 'https://') === 0) {
1947
-			return substr($url, strlen('https://'));
1948
-		} else if (strpos($url, 'http://') === 0) {
1949
-			return substr($url, strlen('http://'));
1950
-		}
1951
-
1952
-		return $url;
1953
-	}
1954
-
1955
-	/**
1956
-	 * try http post first with https and then with http as a fallback
1957
-	 *
1958
-	 * @param string $remoteDomain
1959
-	 * @param string $urlSuffix
1960
-	 * @param array $fields post parameters
1961
-	 * @return array
1962
-	 */
1963
-	private static function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields) {
1964
-		$protocol = 'https://';
1965
-		$result = [
1966
-			'success' => false,
1967
-			'result' => '',
1968
-		];
1969
-		$try = 0;
1970
-		$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
1971
-		while ($result['success'] === false && $try < 2) {
1972
-			$federationEndpoints = $discoveryService->discover($protocol . $remoteDomain, 'FEDERATED_SHARING');
1973
-			$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
1974
-			$client = \OC::$server->getHTTPClientService()->newClient();
1975
-
1976
-			try {
1977
-				$response = $client->post(
1978
-					$protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT,
1979
-					[
1980
-						'body' => $fields,
1981
-						'connect_timeout' => 10,
1982
-					]
1983
-				);
1984
-
1985
-				$result = ['success' => true, 'result' => $response->getBody()];
1986
-			} catch (\Exception $e) {
1987
-				$result = ['success' => false, 'result' => $e->getMessage()];
1988
-			}
1989
-
1990
-			$try++;
1991
-			$protocol = 'http://';
1992
-		}
1993
-
1994
-		return $result;
1995
-	}
1996
-
1997
-	/**
1998
-	 * send server-to-server share to remote server
1999
-	 *
2000
-	 * @param string $token
2001
-	 * @param string $shareWith
2002
-	 * @param string $name
2003
-	 * @param int $remote_id
2004
-	 * @param string $owner
2005
-	 * @return bool
2006
-	 */
2007
-	private static function sendRemoteShare($token, $shareWith, $name, $remote_id, $owner) {
2008
-
2009
-		list($user, $remote) = Helper::splitUserRemote($shareWith);
2010
-
2011
-		if ($user && $remote) {
2012
-			$url = $remote;
2013
-
2014
-			$local = \OC::$server->getURLGenerator()->getAbsoluteURL('/');
2015
-
2016
-			$fields = array(
2017
-				'shareWith' => $user,
2018
-				'token' => $token,
2019
-				'name' => $name,
2020
-				'remoteId' => $remote_id,
2021
-				'owner' => $owner,
2022
-				'remote' => $local,
2023
-			);
2024
-
2025
-			$url = self::removeProtocolFromUrl($url);
2026
-			$result = self::tryHttpPostToShareEndpoint($url, '', $fields);
2027
-			$status = json_decode($result['result'], true);
2028
-
2029
-			if ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200)) {
2030
-				\OC_Hook::emit(\OCP\Share::class, 'federated_share_added', ['server' => $remote]);
2031
-				return true;
2032
-			}
2033
-
2034
-		}
2035
-
2036
-		return false;
2037
-	}
2038
-
2039
-	/**
2040
-	 * send server-to-server unshare to remote server
2041
-	 *
2042
-	 * @param string $remote url
2043
-	 * @param int $id share id
2044
-	 * @param string $token
2045
-	 * @return bool
2046
-	 */
2047
-	private static function sendRemoteUnshare($remote, $id, $token) {
2048
-		$url = rtrim($remote, '/');
2049
-		$fields = array('token' => $token, 'format' => 'json');
2050
-		$url = self::removeProtocolFromUrl($url);
2051
-		$result = self::tryHttpPostToShareEndpoint($url, '/'.$id.'/unshare', $fields);
2052
-		$status = json_decode($result['result'], true);
2053
-
2054
-		return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200));
2055
-	}
2056
-
2057
-	/**
2058
-	 * check if user can only share with group members
2059
-	 * @return bool
2060
-	 */
2061
-	public static function shareWithGroupMembersOnly() {
2062
-		$value = \OC::$server->getConfig()->getAppValue('core', 'shareapi_only_share_with_group_members', 'no');
2063
-		return $value === 'yes';
2064
-	}
2065
-
2066
-	/**
2067
-	 * @return bool
2068
-	 */
2069
-	public static function isDefaultExpireDateEnabled() {
2070
-		$defaultExpireDateEnabled = \OC::$server->getConfig()->getAppValue('core', 'shareapi_default_expire_date', 'no');
2071
-		return $defaultExpireDateEnabled === 'yes';
2072
-	}
2073
-
2074
-	/**
2075
-	 * @return int
2076
-	 */
2077
-	public static function getExpireInterval() {
2078
-		return (int)\OC::$server->getConfig()->getAppValue('core', 'shareapi_expire_after_n_days', '7');
2079
-	}
2080
-
2081
-	/**
2082
-	 * Checks whether the given path is reachable for the given owner
2083
-	 *
2084
-	 * @param string $path path relative to files
2085
-	 * @param string $ownerStorageId storage id of the owner
2086
-	 *
2087
-	 * @return boolean true if file is reachable, false otherwise
2088
-	 */
2089
-	private static function isFileReachable($path, $ownerStorageId) {
2090
-		// if outside the home storage, file is always considered reachable
2091
-		if (!(substr($ownerStorageId, 0, 6) === 'home::' ||
2092
-			substr($ownerStorageId, 0, 13) === 'object::user:'
2093
-		)) {
2094
-			return true;
2095
-		}
2096
-
2097
-		// if inside the home storage, the file has to be under "/files/"
2098
-		$path = ltrim($path, '/');
2099
-		if (substr($path, 0, 6) === 'files/') {
2100
-			return true;
2101
-		}
2102
-
2103
-		return false;
2104
-	}
2105
-
2106
-	/**
2107
-	 * @param IConfig $config
2108
-	 * @return bool
2109
-	 */
2110
-	public static function enforcePassword(IConfig $config) {
2111
-		$enforcePassword = $config->getAppValue('core', 'shareapi_enforce_links_password', 'no');
2112
-		return $enforcePassword === 'yes';
2113
-	}
2114
-
2115
-	/**
2116
-	 * @param string $password
2117
-	 * @throws \Exception
2118
-	 */
2119
-	private static function verifyPassword($password) {
2120
-
2121
-		$accepted = true;
2122
-		$message = '';
2123
-		\OCP\Util::emitHook('\OC\Share', 'verifyPassword', [
2124
-			'password' => $password,
2125
-			'accepted' => &$accepted,
2126
-			'message' => &$message
2127
-		]);
2128
-
2129
-		if (!$accepted) {
2130
-			throw new \Exception($message);
2131
-		}
2132
-	}
704
+        $result = $query->execute(array($status, $itemType, $itemSource, $shareType, $recipient));
705
+
706
+        if($result === false) {
707
+            \OCP\Util::writeLog('OCP\Share', 'Couldn\'t set send mail status', ILogger::ERROR);
708
+        }
709
+    }
710
+
711
+    /**
712
+     * validate expiration date if it meets all constraints
713
+     *
714
+     * @param string $expireDate well formatted date string, e.g. "DD-MM-YYYY"
715
+     * @param string $shareTime timestamp when the file was shared
716
+     * @param string $itemType
717
+     * @param string $itemSource
718
+     * @return \DateTime validated date
719
+     * @throws \Exception when the expire date is in the past or further in the future then the enforced date
720
+     */
721
+    private static function validateExpireDate($expireDate, $shareTime, $itemType, $itemSource) {
722
+        $l = \OC::$server->getL10N('lib');
723
+        $date = new \DateTime($expireDate);
724
+        $today = new \DateTime('now');
725
+
726
+        // if the user doesn't provide a share time we need to get it from the database
727
+        // fall-back mode to keep API stable, because the $shareTime parameter was added later
728
+        $defaultExpireDateEnforced = \OCP\Util::isDefaultExpireDateEnforced();
729
+        if ($defaultExpireDateEnforced && $shareTime === null) {
730
+            $items = self::getItemShared($itemType, $itemSource);
731
+            $firstItem = reset($items);
732
+            $shareTime = (int)$firstItem['stime'];
733
+        }
734
+
735
+        if ($defaultExpireDateEnforced) {
736
+            // initialize max date with share time
737
+            $maxDate = new \DateTime();
738
+            $maxDate->setTimestamp($shareTime);
739
+            $maxDays = \OC::$server->getConfig()->getAppValue('core', 'shareapi_expire_after_n_days', '7');
740
+            $maxDate->add(new \DateInterval('P' . $maxDays . 'D'));
741
+            if ($date > $maxDate) {
742
+                $warning = 'Cannot set expiration date. Shares cannot expire later than ' . $maxDays . ' after they have been shared';
743
+                $warning_t = $l->t('Cannot set expiration date. Shares cannot expire later than %s after they have been shared', array($maxDays));
744
+                \OCP\Util::writeLog('OCP\Share', $warning, ILogger::WARN);
745
+                throw new \Exception($warning_t);
746
+            }
747
+        }
748
+
749
+        if ($date < $today) {
750
+            $message = 'Cannot set expiration date. Expiration date is in the past';
751
+            $message_t = $l->t('Cannot set expiration date. Expiration date is in the past');
752
+            \OCP\Util::writeLog('OCP\Share', $message, ILogger::WARN);
753
+            throw new \Exception($message_t);
754
+        }
755
+
756
+        return $date;
757
+    }
758
+
759
+    /**
760
+     * Checks whether a share has expired, calls unshareItem() if yes.
761
+     * @param array $item Share data (usually database row)
762
+     * @return boolean True if item was expired, false otherwise.
763
+     */
764
+    protected static function expireItem(array $item) {
765
+
766
+        $result = false;
767
+
768
+        // only use default expiration date for link shares
769
+        if ((int) $item['share_type'] === self::SHARE_TYPE_LINK) {
770
+
771
+            // calculate expiration date
772
+            if (!empty($item['expiration'])) {
773
+                $userDefinedExpire = new \DateTime($item['expiration']);
774
+                $expires = $userDefinedExpire->getTimestamp();
775
+            } else {
776
+                $expires = null;
777
+            }
778
+
779
+
780
+            // get default expiration settings
781
+            $defaultSettings = Helper::getDefaultExpireSetting();
782
+            $expires = Helper::calculateExpireDate($defaultSettings, $item['stime'], $expires);
783
+
784
+
785
+            if (is_int($expires)) {
786
+                $now = time();
787
+                if ($now > $expires) {
788
+                    self::unshareItem($item);
789
+                    $result = true;
790
+                }
791
+            }
792
+        }
793
+        return $result;
794
+    }
795
+
796
+    /**
797
+     * Unshares a share given a share data array
798
+     * @param array $item Share data (usually database row)
799
+     * @param int $newParent parent ID
800
+     * @return null
801
+     */
802
+    protected static function unshareItem(array $item, $newParent = null) {
803
+
804
+        $shareType = (int)$item['share_type'];
805
+        $shareWith = null;
806
+        if ($shareType !== \OCP\Share::SHARE_TYPE_LINK) {
807
+            $shareWith = $item['share_with'];
808
+        }
809
+
810
+        // Pass all the vars we have for now, they may be useful
811
+        $hookParams = array(
812
+            'id'            => $item['id'],
813
+            'itemType'      => $item['item_type'],
814
+            'itemSource'    => $item['item_source'],
815
+            'shareType'     => $shareType,
816
+            'shareWith'     => $shareWith,
817
+            'itemParent'    => $item['parent'],
818
+            'uidOwner'      => $item['uid_owner'],
819
+        );
820
+        if($item['item_type'] === 'file' || $item['item_type'] === 'folder') {
821
+            $hookParams['fileSource'] = $item['file_source'];
822
+            $hookParams['fileTarget'] = $item['file_target'];
823
+        }
824
+
825
+        \OC_Hook::emit(\OCP\Share::class, 'pre_unshare', $hookParams);
826
+        $deletedShares = Helper::delete($item['id'], false, null, $newParent);
827
+        $deletedShares[] = $hookParams;
828
+        $hookParams['deletedShares'] = $deletedShares;
829
+        \OC_Hook::emit(\OCP\Share::class, 'post_unshare', $hookParams);
830
+        if ((int)$item['share_type'] === \OCP\Share::SHARE_TYPE_REMOTE && \OC::$server->getUserSession()->getUser()) {
831
+            list(, $remote) = Helper::splitUserRemote($item['share_with']);
832
+            self::sendRemoteUnshare($remote, $item['id'], $item['token']);
833
+        }
834
+    }
835
+
836
+    /**
837
+     * Get the backend class for the specified item type
838
+     * @param string $itemType
839
+     * @throws \Exception
840
+     * @return \OCP\Share_Backend
841
+     */
842
+    public static function getBackend($itemType) {
843
+        $l = \OC::$server->getL10N('lib');
844
+        if (isset(self::$backends[$itemType])) {
845
+            return self::$backends[$itemType];
846
+        } else if (isset(self::$backendTypes[$itemType]['class'])) {
847
+            $class = self::$backendTypes[$itemType]['class'];
848
+            if (class_exists($class)) {
849
+                self::$backends[$itemType] = new $class;
850
+                if (!(self::$backends[$itemType] instanceof \OCP\Share_Backend)) {
851
+                    $message = 'Sharing backend %s must implement the interface OCP\Share_Backend';
852
+                    $message_t = $l->t('Sharing backend %s must implement the interface OCP\Share_Backend', array($class));
853
+                    \OCP\Util::writeLog('OCP\Share', sprintf($message, $class), ILogger::ERROR);
854
+                    throw new \Exception($message_t);
855
+                }
856
+                return self::$backends[$itemType];
857
+            } else {
858
+                $message = 'Sharing backend %s not found';
859
+                $message_t = $l->t('Sharing backend %s not found', array($class));
860
+                \OCP\Util::writeLog('OCP\Share', sprintf($message, $class), ILogger::ERROR);
861
+                throw new \Exception($message_t);
862
+            }
863
+        }
864
+        $message = 'Sharing backend for %s not found';
865
+        $message_t = $l->t('Sharing backend for %s not found', array($itemType));
866
+        \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemType), ILogger::ERROR);
867
+        throw new \Exception($message_t);
868
+    }
869
+
870
+    /**
871
+     * Check if resharing is allowed
872
+     * @return boolean true if allowed or false
873
+     *
874
+     * Resharing is allowed by default if not configured
875
+     */
876
+    public static function isResharingAllowed() {
877
+        if (!isset(self::$isResharingAllowed)) {
878
+            if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_resharing', 'yes') == 'yes') {
879
+                self::$isResharingAllowed = true;
880
+            } else {
881
+                self::$isResharingAllowed = false;
882
+            }
883
+        }
884
+        return self::$isResharingAllowed;
885
+    }
886
+
887
+    /**
888
+     * Get a list of collection item types for the specified item type
889
+     * @param string $itemType
890
+     * @return array
891
+     */
892
+    private static function getCollectionItemTypes($itemType) {
893
+        $collectionTypes = array($itemType);
894
+        foreach (self::$backendTypes as $type => $backend) {
895
+            if (in_array($backend['collectionOf'], $collectionTypes)) {
896
+                $collectionTypes[] = $type;
897
+            }
898
+        }
899
+        // TODO Add option for collections to be collection of themselves, only 'folder' does it now...
900
+        if (isset(self::$backendTypes[$itemType]) && (!self::getBackend($itemType) instanceof \OCP\Share_Backend_Collection || $itemType != 'folder')) {
901
+            unset($collectionTypes[0]);
902
+        }
903
+        // Return array if collections were found or the item type is a
904
+        // collection itself - collections can be inside collections
905
+        if (count($collectionTypes) > 0) {
906
+            return $collectionTypes;
907
+        }
908
+        return false;
909
+    }
910
+
911
+    /**
912
+     * Get the owners of items shared with a user.
913
+     *
914
+     * @param string $user The user the items are shared with.
915
+     * @param string $type The type of the items shared with the user.
916
+     * @param boolean $includeCollections Include collection item types (optional)
917
+     * @param boolean $includeOwner include owner in the list of users the item is shared with (optional)
918
+     * @return array
919
+     */
920
+    public static function getSharedItemsOwners($user, $type, $includeCollections = false, $includeOwner = false) {
921
+        // First, we find out if $type is part of a collection (and if that collection is part of
922
+        // another one and so on).
923
+        $collectionTypes = array();
924
+        if (!$includeCollections || !$collectionTypes = self::getCollectionItemTypes($type)) {
925
+            $collectionTypes[] = $type;
926
+        }
927
+
928
+        // Of these collection types, along with our original $type, we make a
929
+        // list of the ones for which a sharing backend has been registered.
930
+        // FIXME: Ideally, we wouldn't need to nest getItemsSharedWith in this loop but just call it
931
+        // with its $includeCollections parameter set to true. Unfortunately, this fails currently.
932
+        $allMaybeSharedItems = array();
933
+        foreach ($collectionTypes as $collectionType) {
934
+            if (isset(self::$backends[$collectionType])) {
935
+                $allMaybeSharedItems[$collectionType] = self::getItemsSharedWithUser(
936
+                    $collectionType,
937
+                    $user,
938
+                    self::FORMAT_NONE
939
+                );
940
+            }
941
+        }
942
+
943
+        $owners = array();
944
+        if ($includeOwner) {
945
+            $owners[] = $user;
946
+        }
947
+
948
+        // We take a look at all shared items of the given $type (or of the collections it is part of)
949
+        // and find out their owners. Then, we gather the tags for the original $type from all owners,
950
+        // and return them as elements of a list that look like "Tag (owner)".
951
+        foreach ($allMaybeSharedItems as $collectionType => $maybeSharedItems) {
952
+            foreach ($maybeSharedItems as $sharedItem) {
953
+                if (isset($sharedItem['id'])) { //workaround for https://github.com/owncloud/core/issues/2814
954
+                    $owners[] = $sharedItem['uid_owner'];
955
+                }
956
+            }
957
+        }
958
+
959
+        return $owners;
960
+    }
961
+
962
+    /**
963
+     * Get shared items from the database
964
+     * @param string $itemType
965
+     * @param string $item Item source or target (optional)
966
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique
967
+     * @param string $shareWith User or group the item is being shared with
968
+     * @param string $uidOwner User that is the owner of shared items (optional)
969
+     * @param int $format Format to convert items to with formatItems() (optional)
970
+     * @param mixed $parameters to pass to formatItems() (optional)
971
+     * @param int $limit Number of items to return, -1 to return all matches (optional)
972
+     * @param boolean $includeCollections Include collection item types (optional)
973
+     * @param boolean $itemShareWithBySource (optional)
974
+     * @param boolean $checkExpireDate
975
+     * @return array
976
+     *
977
+     * See public functions getItem(s)... for parameter usage
978
+     *
979
+     */
980
+    public static function getItems($itemType, $item = null, $shareType = null, $shareWith = null,
981
+                                    $uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1,
982
+                                    $includeCollections = false, $itemShareWithBySource = false, $checkExpireDate  = true) {
983
+        if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_enabled', 'yes') != 'yes') {
984
+            return array();
985
+        }
986
+        $backend = self::getBackend($itemType);
987
+        $collectionTypes = false;
988
+        // Get filesystem root to add it to the file target and remove from the
989
+        // file source, match file_source with the file cache
990
+        if ($itemType == 'file' || $itemType == 'folder') {
991
+            if(!is_null($uidOwner)) {
992
+                $root = \OC\Files\Filesystem::getRoot();
993
+            } else {
994
+                $root = '';
995
+            }
996
+            $where = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` ';
997
+            if (!isset($item)) {
998
+                $where .= ' AND `file_target` IS NOT NULL ';
999
+            }
1000
+            $where .= 'INNER JOIN `*PREFIX*storages` ON `numeric_id` = `*PREFIX*filecache`.`storage` ';
1001
+            $fileDependent = true;
1002
+            $queryArgs = array();
1003
+        } else {
1004
+            $fileDependent = false;
1005
+            $root = '';
1006
+            $collectionTypes = self::getCollectionItemTypes($itemType);
1007
+            if ($includeCollections && !isset($item) && $collectionTypes) {
1008
+                // If includeCollections is true, find collections of this item type, e.g. a music album contains songs
1009
+                if (!in_array($itemType, $collectionTypes)) {
1010
+                    $itemTypes = array_merge(array($itemType), $collectionTypes);
1011
+                } else {
1012
+                    $itemTypes = $collectionTypes;
1013
+                }
1014
+                $placeholders = implode(',', array_fill(0, count($itemTypes), '?'));
1015
+                $where = ' WHERE `item_type` IN ('.$placeholders.'))';
1016
+                $queryArgs = $itemTypes;
1017
+            } else {
1018
+                $where = ' WHERE `item_type` = ?';
1019
+                $queryArgs = array($itemType);
1020
+            }
1021
+        }
1022
+        if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
1023
+            $where .= ' AND `share_type` != ?';
1024
+            $queryArgs[] = self::SHARE_TYPE_LINK;
1025
+        }
1026
+        if (isset($shareType)) {
1027
+            // Include all user and group items
1028
+            if ($shareType == self::$shareTypeUserAndGroups && isset($shareWith)) {
1029
+                $where .= ' AND ((`share_type` in (?, ?) AND `share_with` = ?) ';
1030
+                $queryArgs[] = self::SHARE_TYPE_USER;
1031
+                $queryArgs[] = self::$shareTypeGroupUserUnique;
1032
+                $queryArgs[] = $shareWith;
1033
+
1034
+                $user = \OC::$server->getUserManager()->get($shareWith);
1035
+                $groups = [];
1036
+                if ($user) {
1037
+                    $groups = \OC::$server->getGroupManager()->getUserGroupIds($user);
1038
+                }
1039
+                if (!empty($groups)) {
1040
+                    $placeholders = implode(',', array_fill(0, count($groups), '?'));
1041
+                    $where .= ' OR (`share_type` = ? AND `share_with` IN ('.$placeholders.')) ';
1042
+                    $queryArgs[] = self::SHARE_TYPE_GROUP;
1043
+                    $queryArgs = array_merge($queryArgs, $groups);
1044
+                }
1045
+                $where .= ')';
1046
+                // Don't include own group shares
1047
+                $where .= ' AND `uid_owner` != ?';
1048
+                $queryArgs[] = $shareWith;
1049
+            } else {
1050
+                $where .= ' AND `share_type` = ?';
1051
+                $queryArgs[] = $shareType;
1052
+                if (isset($shareWith)) {
1053
+                    $where .= ' AND `share_with` = ?';
1054
+                    $queryArgs[] = $shareWith;
1055
+                }
1056
+            }
1057
+        }
1058
+        if (isset($uidOwner)) {
1059
+            $where .= ' AND `uid_owner` = ?';
1060
+            $queryArgs[] = $uidOwner;
1061
+            if (!isset($shareType)) {
1062
+                // Prevent unique user targets for group shares from being selected
1063
+                $where .= ' AND `share_type` != ?';
1064
+                $queryArgs[] = self::$shareTypeGroupUserUnique;
1065
+            }
1066
+            if ($fileDependent) {
1067
+                $column = 'file_source';
1068
+            } else {
1069
+                $column = 'item_source';
1070
+            }
1071
+        } else {
1072
+            if ($fileDependent) {
1073
+                $column = 'file_target';
1074
+            } else {
1075
+                $column = 'item_target';
1076
+            }
1077
+        }
1078
+        if (isset($item)) {
1079
+            $collectionTypes = self::getCollectionItemTypes($itemType);
1080
+            if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
1081
+                $where .= ' AND (';
1082
+            } else {
1083
+                $where .= ' AND';
1084
+            }
1085
+            // If looking for own shared items, check item_source else check item_target
1086
+            if (isset($uidOwner) || $itemShareWithBySource) {
1087
+                // If item type is a file, file source needs to be checked in case the item was converted
1088
+                if ($fileDependent) {
1089
+                    $where .= ' `file_source` = ?';
1090
+                    $column = 'file_source';
1091
+                } else {
1092
+                    $where .= ' `item_source` = ?';
1093
+                    $column = 'item_source';
1094
+                }
1095
+            } else {
1096
+                if ($fileDependent) {
1097
+                    $where .= ' `file_target` = ?';
1098
+                    $item = \OC\Files\Filesystem::normalizePath($item);
1099
+                } else {
1100
+                    $where .= ' `item_target` = ?';
1101
+                }
1102
+            }
1103
+            $queryArgs[] = $item;
1104
+            if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
1105
+                $placeholders = implode(',', array_fill(0, count($collectionTypes), '?'));
1106
+                $where .= ' OR `item_type` IN ('.$placeholders.'))';
1107
+                $queryArgs = array_merge($queryArgs, $collectionTypes);
1108
+            }
1109
+        }
1110
+
1111
+        if ($shareType == self::$shareTypeUserAndGroups && $limit === 1) {
1112
+            // Make sure the unique user target is returned if it exists,
1113
+            // unique targets should follow the group share in the database
1114
+            // If the limit is not 1, the filtering can be done later
1115
+            $where .= ' ORDER BY `*PREFIX*share`.`id` DESC';
1116
+        } else {
1117
+            $where .= ' ORDER BY `*PREFIX*share`.`id` ASC';
1118
+        }
1119
+
1120
+        if ($limit != -1 && !$includeCollections) {
1121
+            // The limit must be at least 3, because filtering needs to be done
1122
+            if ($limit < 3) {
1123
+                $queryLimit = 3;
1124
+            } else {
1125
+                $queryLimit = $limit;
1126
+            }
1127
+        } else {
1128
+            $queryLimit = null;
1129
+        }
1130
+        $select = self::createSelectStatement($format, $fileDependent, $uidOwner);
1131
+        $root = strlen($root);
1132
+        $query = \OC_DB::prepare('SELECT '.$select.' FROM `*PREFIX*share` '.$where, $queryLimit);
1133
+        $result = $query->execute($queryArgs);
1134
+        if ($result === false) {
1135
+            \OCP\Util::writeLog('OCP\Share',
1136
+                \OC_DB::getErrorMessage() . ', select=' . $select . ' where=',
1137
+                ILogger::ERROR);
1138
+        }
1139
+        $items = array();
1140
+        $targets = array();
1141
+        $switchedItems = array();
1142
+        $mounts = array();
1143
+        while ($row = $result->fetchRow()) {
1144
+            self::transformDBResults($row);
1145
+            // Filter out duplicate group shares for users with unique targets
1146
+            if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
1147
+                continue;
1148
+            }
1149
+            if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) {
1150
+                $row['share_type'] = self::SHARE_TYPE_GROUP;
1151
+                $row['unique_name'] = true; // remember that we use a unique name for this user
1152
+                $row['share_with'] = $items[$row['parent']]['share_with'];
1153
+                // if the group share was unshared from the user we keep the permission, otherwise
1154
+                // we take the permission from the parent because this is always the up-to-date
1155
+                // permission for the group share
1156
+                if ($row['permissions'] > 0) {
1157
+                    $row['permissions'] = $items[$row['parent']]['permissions'];
1158
+                }
1159
+                // Remove the parent group share
1160
+                unset($items[$row['parent']]);
1161
+                if ($row['permissions'] == 0) {
1162
+                    continue;
1163
+                }
1164
+            } else if (!isset($uidOwner)) {
1165
+                // Check if the same target already exists
1166
+                if (isset($targets[$row['id']])) {
1167
+                    // Check if the same owner shared with the user twice
1168
+                    // through a group and user share - this is allowed
1169
+                    $id = $targets[$row['id']];
1170
+                    if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) {
1171
+                        // Switch to group share type to ensure resharing conditions aren't bypassed
1172
+                        if ($items[$id]['share_type'] != self::SHARE_TYPE_GROUP) {
1173
+                            $items[$id]['share_type'] = self::SHARE_TYPE_GROUP;
1174
+                            $items[$id]['share_with'] = $row['share_with'];
1175
+                        }
1176
+                        // Switch ids if sharing permission is granted on only
1177
+                        // one share to ensure correct parent is used if resharing
1178
+                        if (~(int)$items[$id]['permissions'] & \OCP\Constants::PERMISSION_SHARE
1179
+                            && (int)$row['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
1180
+                            $items[$row['id']] = $items[$id];
1181
+                            $switchedItems[$id] = $row['id'];
1182
+                            unset($items[$id]);
1183
+                            $id = $row['id'];
1184
+                        }
1185
+                        $items[$id]['permissions'] |= (int)$row['permissions'];
1186
+
1187
+                    }
1188
+                    continue;
1189
+                } elseif (!empty($row['parent'])) {
1190
+                    $targets[$row['parent']] = $row['id'];
1191
+                }
1192
+            }
1193
+            // Remove root from file source paths if retrieving own shared items
1194
+            if (isset($uidOwner) && isset($row['path'])) {
1195
+                if (isset($row['parent'])) {
1196
+                    $query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?');
1197
+                    $parentResult = $query->execute(array($row['parent']));
1198
+                    if ($result === false) {
1199
+                        \OCP\Util::writeLog('OCP\Share', 'Can\'t select parent: ' .
1200
+                            \OC_DB::getErrorMessage() . ', select=' . $select . ' where=' . $where,
1201
+                            ILogger::ERROR);
1202
+                    } else {
1203
+                        $parentRow = $parentResult->fetchRow();
1204
+                        $tmpPath = $parentRow['file_target'];
1205
+                        // find the right position where the row path continues from the target path
1206
+                        $pos = strrpos($row['path'], $parentRow['file_target']);
1207
+                        $subPath = substr($row['path'], $pos);
1208
+                        $splitPath = explode('/', $subPath);
1209
+                        foreach (array_slice($splitPath, 2) as $pathPart) {
1210
+                            $tmpPath = $tmpPath . '/' . $pathPart;
1211
+                        }
1212
+                        $row['path'] = $tmpPath;
1213
+                    }
1214
+                } else {
1215
+                    if (!isset($mounts[$row['storage']])) {
1216
+                        $mountPoints = \OC\Files\Filesystem::getMountByNumericId($row['storage']);
1217
+                        if (is_array($mountPoints) && !empty($mountPoints)) {
1218
+                            $mounts[$row['storage']] = current($mountPoints);
1219
+                        }
1220
+                    }
1221
+                    if (!empty($mounts[$row['storage']])) {
1222
+                        $path = $mounts[$row['storage']]->getMountPoint().$row['path'];
1223
+                        $relPath = substr($path, $root); // path relative to data/user
1224
+                        $row['path'] = rtrim($relPath, '/');
1225
+                    }
1226
+                }
1227
+            }
1228
+
1229
+            if($checkExpireDate) {
1230
+                if (self::expireItem($row)) {
1231
+                    continue;
1232
+                }
1233
+            }
1234
+            // Check if resharing is allowed, if not remove share permission
1235
+            if (isset($row['permissions']) && (!self::isResharingAllowed() | \OCP\Util::isSharingDisabledForUser())) {
1236
+                $row['permissions'] &= ~\OCP\Constants::PERMISSION_SHARE;
1237
+            }
1238
+            // Add display names to result
1239
+            $row['share_with_displayname'] = $row['share_with'];
1240
+            if ( isset($row['share_with']) && $row['share_with'] != '' &&
1241
+                $row['share_type'] === self::SHARE_TYPE_USER) {
1242
+                $shareWithUser = \OC::$server->getUserManager()->get($row['share_with']);
1243
+                $row['share_with_displayname'] = $shareWithUser === null ? $row['share_with'] : $shareWithUser->getDisplayName();
1244
+            } else if(isset($row['share_with']) && $row['share_with'] != '' &&
1245
+                $row['share_type'] === self::SHARE_TYPE_REMOTE) {
1246
+                $addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD']);
1247
+                foreach ($addressBookEntries as $entry) {
1248
+                    foreach ($entry['CLOUD'] as $cloudID) {
1249
+                        if ($cloudID === $row['share_with']) {
1250
+                            $row['share_with_displayname'] = $entry['FN'];
1251
+                        }
1252
+                    }
1253
+                }
1254
+            }
1255
+            if ( isset($row['uid_owner']) && $row['uid_owner'] != '') {
1256
+                $ownerUser = \OC::$server->getUserManager()->get($row['uid_owner']);
1257
+                $row['displayname_owner'] = $ownerUser === null ? $row['uid_owner'] : $ownerUser->getDisplayName();
1258
+            }
1259
+
1260
+            if ($row['permissions'] > 0) {
1261
+                $items[$row['id']] = $row;
1262
+            }
1263
+
1264
+        }
1265
+
1266
+        // group items if we are looking for items shared with the current user
1267
+        if (isset($shareWith) && $shareWith === \OCP\User::getUser()) {
1268
+            $items = self::groupItems($items, $itemType);
1269
+        }
1270
+
1271
+        if (!empty($items)) {
1272
+            $collectionItems = array();
1273
+            foreach ($items as &$row) {
1274
+                // Return only the item instead of a 2-dimensional array
1275
+                if ($limit == 1 && $row[$column] == $item && ($row['item_type'] == $itemType || $itemType == 'file')) {
1276
+                    if ($format == self::FORMAT_NONE) {
1277
+                        return $row;
1278
+                    } else {
1279
+                        break;
1280
+                    }
1281
+                }
1282
+                // Check if this is a collection of the requested item type
1283
+                if ($includeCollections && $collectionTypes && $row['item_type'] !== 'folder' && in_array($row['item_type'], $collectionTypes)) {
1284
+                    if (($collectionBackend = self::getBackend($row['item_type']))
1285
+                        && $collectionBackend instanceof \OCP\Share_Backend_Collection) {
1286
+                        // Collections can be inside collections, check if the item is a collection
1287
+                        if (isset($item) && $row['item_type'] == $itemType && $row[$column] == $item) {
1288
+                            $collectionItems[] = $row;
1289
+                        } else {
1290
+                            $collection = array();
1291
+                            $collection['item_type'] = $row['item_type'];
1292
+                            if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
1293
+                                $collection['path'] = basename($row['path']);
1294
+                            }
1295
+                            $row['collection'] = $collection;
1296
+                            // Fetch all of the children sources
1297
+                            $children = $collectionBackend->getChildren($row[$column]);
1298
+                            foreach ($children as $child) {
1299
+                                $childItem = $row;
1300
+                                $childItem['item_type'] = $itemType;
1301
+                                if ($row['item_type'] != 'file' && $row['item_type'] != 'folder') {
1302
+                                    $childItem['item_source'] = $child['source'];
1303
+                                    $childItem['item_target'] = $child['target'];
1304
+                                }
1305
+                                if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
1306
+                                    if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
1307
+                                        $childItem['file_source'] = $child['source'];
1308
+                                    } else { // TODO is this really needed if we already know that we use the file backend?
1309
+                                        $meta = \OC\Files\Filesystem::getFileInfo($child['file_path']);
1310
+                                        $childItem['file_source'] = $meta['fileid'];
1311
+                                    }
1312
+                                    $childItem['file_target'] =
1313
+                                        \OC\Files\Filesystem::normalizePath($child['file_path']);
1314
+                                }
1315
+                                if (isset($item)) {
1316
+                                    if ($childItem[$column] == $item) {
1317
+                                        // Return only the item instead of a 2-dimensional array
1318
+                                        if ($limit == 1) {
1319
+                                            if ($format == self::FORMAT_NONE) {
1320
+                                                return $childItem;
1321
+                                            } else {
1322
+                                                // Unset the items array and break out of both loops
1323
+                                                $items = array();
1324
+                                                $items[] = $childItem;
1325
+                                                break 2;
1326
+                                            }
1327
+                                        } else {
1328
+                                            $collectionItems[] = $childItem;
1329
+                                        }
1330
+                                    }
1331
+                                } else {
1332
+                                    $collectionItems[] = $childItem;
1333
+                                }
1334
+                            }
1335
+                        }
1336
+                    }
1337
+                    // Remove collection item
1338
+                    $toRemove = $row['id'];
1339
+                    if (array_key_exists($toRemove, $switchedItems)) {
1340
+                        $toRemove = $switchedItems[$toRemove];
1341
+                    }
1342
+                    unset($items[$toRemove]);
1343
+                } elseif ($includeCollections && $collectionTypes && in_array($row['item_type'], $collectionTypes)) {
1344
+                    // FIXME: Thats a dirty hack to improve file sharing performance,
1345
+                    // see github issue #10588 for more details
1346
+                    // Need to find a solution which works for all back-ends
1347
+                    $collectionBackend = self::getBackend($row['item_type']);
1348
+                    $sharedParents = $collectionBackend->getParents($row['item_source']);
1349
+                    foreach ($sharedParents as $parent) {
1350
+                        $collectionItems[] = $parent;
1351
+                    }
1352
+                }
1353
+            }
1354
+            if (!empty($collectionItems)) {
1355
+                $collectionItems = array_unique($collectionItems, SORT_REGULAR);
1356
+                $items = array_merge($items, $collectionItems);
1357
+            }
1358
+
1359
+            // filter out invalid items, these can appear when subshare entries exist
1360
+            // for a group in which the requested user isn't a member any more
1361
+            $items = array_filter($items, function($item) {
1362
+                return $item['share_type'] !== self::$shareTypeGroupUserUnique;
1363
+            });
1364
+
1365
+            return self::formatResult($items, $column, $backend, $format, $parameters);
1366
+        } elseif ($includeCollections && $collectionTypes && in_array('folder', $collectionTypes)) {
1367
+            // FIXME: Thats a dirty hack to improve file sharing performance,
1368
+            // see github issue #10588 for more details
1369
+            // Need to find a solution which works for all back-ends
1370
+            $collectionItems = array();
1371
+            $collectionBackend = self::getBackend('folder');
1372
+            $sharedParents = $collectionBackend->getParents($item, $shareWith, $uidOwner);
1373
+            foreach ($sharedParents as $parent) {
1374
+                $collectionItems[] = $parent;
1375
+            }
1376
+            if ($limit === 1) {
1377
+                return reset($collectionItems);
1378
+            }
1379
+            return self::formatResult($collectionItems, $column, $backend, $format, $parameters);
1380
+        }
1381
+
1382
+        return array();
1383
+    }
1384
+
1385
+    /**
1386
+     * group items with link to the same source
1387
+     *
1388
+     * @param array $items
1389
+     * @param string $itemType
1390
+     * @return array of grouped items
1391
+     */
1392
+    protected static function groupItems($items, $itemType) {
1393
+
1394
+        $fileSharing = $itemType === 'file' || $itemType === 'folder';
1395
+
1396
+        $result = array();
1397
+
1398
+        foreach ($items as $item) {
1399
+            $grouped = false;
1400
+            foreach ($result as $key => $r) {
1401
+                // for file/folder shares we need to compare file_source, otherwise we compare item_source
1402
+                // only group shares if they already point to the same target, otherwise the file where shared
1403
+                // before grouping of shares was added. In this case we don't group them toi avoid confusions
1404
+                if (( $fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) ||
1405
+                    (!$fileSharing && $item['item_source'] === $r['item_source'] && $item['item_target'] === $r['item_target'])) {
1406
+                    // add the first item to the list of grouped shares
1407
+                    if (!isset($result[$key]['grouped'])) {
1408
+                        $result[$key]['grouped'][] = $result[$key];
1409
+                    }
1410
+                    $result[$key]['permissions'] = (int) $item['permissions'] | (int) $r['permissions'];
1411
+                    $result[$key]['grouped'][] = $item;
1412
+                    $grouped = true;
1413
+                    break;
1414
+                }
1415
+            }
1416
+
1417
+            if (!$grouped) {
1418
+                $result[] = $item;
1419
+            }
1420
+
1421
+        }
1422
+
1423
+        return $result;
1424
+    }
1425
+
1426
+    /**
1427
+     * Put shared item into the database
1428
+     * @param string $itemType Item type
1429
+     * @param string $itemSource Item source
1430
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
1431
+     * @param string $shareWith User or group the item is being shared with
1432
+     * @param string $uidOwner User that is the owner of shared item
1433
+     * @param int $permissions CRUDS permissions
1434
+     * @param boolean|array $parentFolder Parent folder target (optional)
1435
+     * @param string $token (optional)
1436
+     * @param string $itemSourceName name of the source item (optional)
1437
+     * @param \DateTime $expirationDate (optional)
1438
+     * @throws \Exception
1439
+     * @return mixed id of the new share or false
1440
+     */
1441
+    private static function put($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
1442
+                                $permissions, $parentFolder = null, $token = null, $itemSourceName = null, \DateTime $expirationDate = null) {
1443
+
1444
+        $queriesToExecute = array();
1445
+        $suggestedItemTarget = null;
1446
+        $groupFileTarget = $fileTarget = $suggestedFileTarget = $filePath = '';
1447
+        $groupItemTarget = $itemTarget = $fileSource = $parent = 0;
1448
+
1449
+        $result = self::checkReshare($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, $itemSourceName, $expirationDate);
1450
+        if(!empty($result)) {
1451
+            $parent = $result['parent'];
1452
+            $itemSource = $result['itemSource'];
1453
+            $fileSource = $result['fileSource'];
1454
+            $suggestedItemTarget = $result['suggestedItemTarget'];
1455
+            $suggestedFileTarget = $result['suggestedFileTarget'];
1456
+            $filePath = $result['filePath'];
1457
+        }
1458
+
1459
+        $isGroupShare = false;
1460
+        if ($shareType == self::SHARE_TYPE_GROUP) {
1461
+            $isGroupShare = true;
1462
+            if (isset($shareWith['users'])) {
1463
+                $users = $shareWith['users'];
1464
+            } else {
1465
+                $group = \OC::$server->getGroupManager()->get($shareWith['group']);
1466
+                if ($group) {
1467
+                    $users = $group->searchUsers('', -1, 0);
1468
+                    $userIds = [];
1469
+                    foreach ($users as $user) {
1470
+                        $userIds[] = $user->getUID();
1471
+                    }
1472
+                    $users = $userIds;
1473
+                } else {
1474
+                    $users = [];
1475
+                }
1476
+            }
1477
+            // remove current user from list
1478
+            if (in_array(\OCP\User::getUser(), $users)) {
1479
+                unset($users[array_search(\OCP\User::getUser(), $users)]);
1480
+            }
1481
+            $groupItemTarget = Helper::generateTarget($itemType, $itemSource,
1482
+                $shareType, $shareWith['group'], $uidOwner, $suggestedItemTarget);
1483
+            $groupFileTarget = Helper::generateTarget($itemType, $itemSource,
1484
+                $shareType, $shareWith['group'], $uidOwner, $filePath);
1485
+
1486
+            // add group share to table and remember the id as parent
1487
+            $queriesToExecute['groupShare'] = array(
1488
+                'itemType'			=> $itemType,
1489
+                'itemSource'		=> $itemSource,
1490
+                'itemTarget'		=> $groupItemTarget,
1491
+                'shareType'			=> $shareType,
1492
+                'shareWith'			=> $shareWith['group'],
1493
+                'uidOwner'			=> $uidOwner,
1494
+                'permissions'		=> $permissions,
1495
+                'shareTime'			=> time(),
1496
+                'fileSource'		=> $fileSource,
1497
+                'fileTarget'		=> $groupFileTarget,
1498
+                'token'				=> $token,
1499
+                'parent'			=> $parent,
1500
+                'expiration'		=> $expirationDate,
1501
+            );
1502
+
1503
+        } else {
1504
+            $users = array($shareWith);
1505
+            $itemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
1506
+                $suggestedItemTarget);
1507
+        }
1508
+
1509
+        $run = true;
1510
+        $error = '';
1511
+        $preHookData = array(
1512
+            'itemType' => $itemType,
1513
+            'itemSource' => $itemSource,
1514
+            'shareType' => $shareType,
1515
+            'uidOwner' => $uidOwner,
1516
+            'permissions' => $permissions,
1517
+            'fileSource' => $fileSource,
1518
+            'expiration' => $expirationDate,
1519
+            'token' => $token,
1520
+            'run' => &$run,
1521
+            'error' => &$error
1522
+        );
1523
+
1524
+        $preHookData['itemTarget'] = $isGroupShare ? $groupItemTarget : $itemTarget;
1525
+        $preHookData['shareWith'] = $isGroupShare ? $shareWith['group'] : $shareWith;
1526
+
1527
+        \OC_Hook::emit(\OCP\Share::class, 'pre_shared', $preHookData);
1528
+
1529
+        if ($run === false) {
1530
+            throw new \Exception($error);
1531
+        }
1532
+
1533
+        foreach ($users as $user) {
1534
+            $sourceId = ($itemType === 'file' || $itemType === 'folder') ? $fileSource : $itemSource;
1535
+            $sourceExists = self::getItemSharedWithBySource($itemType, $sourceId, self::FORMAT_NONE, null, true, $user);
1536
+
1537
+            $userShareType = $isGroupShare ? self::$shareTypeGroupUserUnique : $shareType;
1538
+
1539
+            if ($sourceExists && $sourceExists['item_source'] === $itemSource) {
1540
+                $fileTarget = $sourceExists['file_target'];
1541
+                $itemTarget = $sourceExists['item_target'];
1542
+
1543
+                // for group shares we don't need a additional entry if the target is the same
1544
+                if($isGroupShare && $groupItemTarget === $itemTarget) {
1545
+                    continue;
1546
+                }
1547
+
1548
+            } elseif(!$sourceExists && !$isGroupShare)  {
1549
+
1550
+                $itemTarget = Helper::generateTarget($itemType, $itemSource, $userShareType, $user,
1551
+                    $uidOwner, $suggestedItemTarget, $parent);
1552
+                if (isset($fileSource)) {
1553
+                    if ($parentFolder) {
1554
+                        if ($parentFolder === true) {
1555
+                            $fileTarget = Helper::generateTarget('file', $filePath, $userShareType, $user,
1556
+                                $uidOwner, $suggestedFileTarget, $parent);
1557
+                            if ($fileTarget != $groupFileTarget) {
1558
+                                $parentFolders[$user]['folder'] = $fileTarget;
1559
+                            }
1560
+                        } else if (isset($parentFolder[$user])) {
1561
+                            $fileTarget = $parentFolder[$user]['folder'].$itemSource;
1562
+                            $parent = $parentFolder[$user]['id'];
1563
+                        }
1564
+                    } else {
1565
+                        $fileTarget = Helper::generateTarget('file', $filePath, $userShareType,
1566
+                            $user, $uidOwner, $suggestedFileTarget, $parent);
1567
+                    }
1568
+                } else {
1569
+                    $fileTarget = null;
1570
+                }
1571
+
1572
+            } else {
1573
+
1574
+                // group share which doesn't exists until now, check if we need a unique target for this user
1575
+
1576
+                $itemTarget = Helper::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $user,
1577
+                    $uidOwner, $suggestedItemTarget, $parent);
1578
+
1579
+                // do we also need a file target
1580
+                if (isset($fileSource)) {
1581
+                    $fileTarget = Helper::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $user,
1582
+                        $uidOwner, $suggestedFileTarget, $parent);
1583
+                } else {
1584
+                    $fileTarget = null;
1585
+                }
1586
+
1587
+                if (($itemTarget === $groupItemTarget) &&
1588
+                    (!isset($fileSource) || $fileTarget === $groupFileTarget)) {
1589
+                    continue;
1590
+                }
1591
+            }
1592
+
1593
+            $queriesToExecute[] = array(
1594
+                'itemType'			=> $itemType,
1595
+                'itemSource'		=> $itemSource,
1596
+                'itemTarget'		=> $itemTarget,
1597
+                'shareType'			=> $userShareType,
1598
+                'shareWith'			=> $user,
1599
+                'uidOwner'			=> $uidOwner,
1600
+                'permissions'		=> $permissions,
1601
+                'shareTime'			=> time(),
1602
+                'fileSource'		=> $fileSource,
1603
+                'fileTarget'		=> $fileTarget,
1604
+                'token'				=> $token,
1605
+                'parent'			=> $parent,
1606
+                'expiration'		=> $expirationDate,
1607
+            );
1608
+
1609
+        }
1610
+
1611
+        $id = false;
1612
+        if ($isGroupShare) {
1613
+            $id = self::insertShare($queriesToExecute['groupShare']);
1614
+            // Save this id, any extra rows for this group share will need to reference it
1615
+            $parent = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share');
1616
+            unset($queriesToExecute['groupShare']);
1617
+        }
1618
+
1619
+        foreach ($queriesToExecute as $shareQuery) {
1620
+            $shareQuery['parent'] = $parent;
1621
+            $id = self::insertShare($shareQuery);
1622
+        }
1623
+
1624
+        $postHookData = array(
1625
+            'itemType' => $itemType,
1626
+            'itemSource' => $itemSource,
1627
+            'parent' => $parent,
1628
+            'shareType' => $shareType,
1629
+            'uidOwner' => $uidOwner,
1630
+            'permissions' => $permissions,
1631
+            'fileSource' => $fileSource,
1632
+            'id' => $parent,
1633
+            'token' => $token,
1634
+            'expirationDate' => $expirationDate,
1635
+        );
1636
+
1637
+        $postHookData['shareWith'] = $isGroupShare ? $shareWith['group'] : $shareWith;
1638
+        $postHookData['itemTarget'] = $isGroupShare ? $groupItemTarget : $itemTarget;
1639
+        $postHookData['fileTarget'] = $isGroupShare ? $groupFileTarget : $fileTarget;
1640
+
1641
+        \OC_Hook::emit(\OCP\Share::class, 'post_shared', $postHookData);
1642
+
1643
+
1644
+        return $id ? $id : false;
1645
+    }
1646
+
1647
+    /**
1648
+     * @param string $itemType
1649
+     * @param string $itemSource
1650
+     * @param int $shareType
1651
+     * @param string $shareWith
1652
+     * @param string $uidOwner
1653
+     * @param int $permissions
1654
+     * @param string|null $itemSourceName
1655
+     * @param null|\DateTime $expirationDate
1656
+     */
1657
+    private static function checkReshare($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, $itemSourceName, $expirationDate) {
1658
+        $backend = self::getBackend($itemType);
1659
+
1660
+        $l = \OC::$server->getL10N('lib');
1661
+        $result = array();
1662
+
1663
+        $column = ($itemType === 'file' || $itemType === 'folder') ? 'file_source' : 'item_source';
1664
+
1665
+        $checkReshare = self::getItemSharedWithBySource($itemType, $itemSource, self::FORMAT_NONE, null, true);
1666
+        if ($checkReshare) {
1667
+            // Check if attempting to share back to owner
1668
+            if ($checkReshare['uid_owner'] == $shareWith && $shareType == self::SHARE_TYPE_USER) {
1669
+                $message = 'Sharing %1$s failed, because the user %2$s is the original sharer';
1670
+                $message_t = $l->t('Sharing failed, because the user %s is the original sharer', [$shareWith]);
1671
+
1672
+                \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
1673
+                throw new \Exception($message_t);
1674
+            }
1675
+        }
1676
+
1677
+        if ($checkReshare && $checkReshare['uid_owner'] !== \OC_User::getUser()) {
1678
+            // Check if share permissions is granted
1679
+            if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
1680
+                if (~(int)$checkReshare['permissions'] & $permissions) {
1681
+                    $message = 'Sharing %1$s failed, because the permissions exceed permissions granted to %2$s';
1682
+                    $message_t = $l->t('Sharing %1$s failed, because the permissions exceed permissions granted to %2$s', array($itemSourceName, $uidOwner));
1683
+
1684
+                    \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $uidOwner), ILogger::DEBUG);
1685
+                    throw new \Exception($message_t);
1686
+                } else {
1687
+                    // TODO Don't check if inside folder
1688
+                    $result['parent'] = $checkReshare['id'];
1689
+
1690
+                    $result['expirationDate'] = $expirationDate;
1691
+                    // $checkReshare['expiration'] could be null and then is always less than any value
1692
+                    if(isset($checkReshare['expiration']) && $checkReshare['expiration'] < $expirationDate) {
1693
+                        $result['expirationDate'] = $checkReshare['expiration'];
1694
+                    }
1695
+
1696
+                    // only suggest the same name as new target if it is a reshare of the
1697
+                    // same file/folder and not the reshare of a child
1698
+                    if ($checkReshare[$column] === $itemSource) {
1699
+                        $result['filePath'] = $checkReshare['file_target'];
1700
+                        $result['itemSource'] = $checkReshare['item_source'];
1701
+                        $result['fileSource'] = $checkReshare['file_source'];
1702
+                        $result['suggestedItemTarget'] = $checkReshare['item_target'];
1703
+                        $result['suggestedFileTarget'] = $checkReshare['file_target'];
1704
+                    } else {
1705
+                        $result['filePath'] = ($backend instanceof \OCP\Share_Backend_File_Dependent) ? $backend->getFilePath($itemSource, $uidOwner) : null;
1706
+                        $result['suggestedItemTarget'] = null;
1707
+                        $result['suggestedFileTarget'] = null;
1708
+                        $result['itemSource'] = $itemSource;
1709
+                        $result['fileSource'] = ($backend instanceof \OCP\Share_Backend_File_Dependent) ? $itemSource : null;
1710
+                    }
1711
+                }
1712
+            } else {
1713
+                $message = 'Sharing %s failed, because resharing is not allowed';
1714
+                $message_t = $l->t('Sharing %s failed, because resharing is not allowed', array($itemSourceName));
1715
+
1716
+                \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
1717
+                throw new \Exception($message_t);
1718
+            }
1719
+        } else {
1720
+            $result['parent'] = null;
1721
+            $result['suggestedItemTarget'] = null;
1722
+            $result['suggestedFileTarget'] = null;
1723
+            $result['itemSource'] = $itemSource;
1724
+            $result['expirationDate'] = $expirationDate;
1725
+            if (!$backend->isValidSource($itemSource, $uidOwner)) {
1726
+                $message = 'Sharing %1$s failed, because the sharing backend for '
1727
+                    .'%2$s could not find its source';
1728
+                $message_t = $l->t('Sharing %1$s failed, because the sharing backend for %2$s could not find its source', array($itemSource, $itemType));
1729
+                \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSource, $itemType), ILogger::DEBUG);
1730
+                throw new \Exception($message_t);
1731
+            }
1732
+            if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
1733
+                $result['filePath'] = $backend->getFilePath($itemSource, $uidOwner);
1734
+                if ($itemType == 'file' || $itemType == 'folder') {
1735
+                    $result['fileSource'] = $itemSource;
1736
+                } else {
1737
+                    $meta = \OC\Files\Filesystem::getFileInfo($result['filePath']);
1738
+                    $result['fileSource'] = $meta['fileid'];
1739
+                }
1740
+                if ($result['fileSource'] == -1) {
1741
+                    $message = 'Sharing %s failed, because the file could not be found in the file cache';
1742
+                    $message_t = $l->t('Sharing %s failed, because the file could not be found in the file cache', array($itemSource));
1743
+
1744
+                    \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSource), ILogger::DEBUG);
1745
+                    throw new \Exception($message_t);
1746
+                }
1747
+            } else {
1748
+                $result['filePath'] = null;
1749
+                $result['fileSource'] = null;
1750
+            }
1751
+        }
1752
+
1753
+        return $result;
1754
+    }
1755
+
1756
+    /**
1757
+     *
1758
+     * @param array $shareData
1759
+     * @return mixed false in case of a failure or the id of the new share
1760
+     */
1761
+    private static function insertShare(array $shareData) {
1762
+
1763
+        $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` ('
1764
+            .' `item_type`, `item_source`, `item_target`, `share_type`,'
1765
+            .' `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,'
1766
+            .' `file_target`, `token`, `parent`, `expiration`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)');
1767
+        $query->bindValue(1, $shareData['itemType']);
1768
+        $query->bindValue(2, $shareData['itemSource']);
1769
+        $query->bindValue(3, $shareData['itemTarget']);
1770
+        $query->bindValue(4, $shareData['shareType']);
1771
+        $query->bindValue(5, $shareData['shareWith']);
1772
+        $query->bindValue(6, $shareData['uidOwner']);
1773
+        $query->bindValue(7, $shareData['permissions']);
1774
+        $query->bindValue(8, $shareData['shareTime']);
1775
+        $query->bindValue(9, $shareData['fileSource']);
1776
+        $query->bindValue(10, $shareData['fileTarget']);
1777
+        $query->bindValue(11, $shareData['token']);
1778
+        $query->bindValue(12, $shareData['parent']);
1779
+        $query->bindValue(13, $shareData['expiration'], 'datetime');
1780
+        $result = $query->execute();
1781
+
1782
+        $id = false;
1783
+        if ($result) {
1784
+            $id =  \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share');
1785
+        }
1786
+
1787
+        return $id;
1788
+
1789
+    }
1790
+
1791
+    /**
1792
+     * In case a password protected link is not yet authenticated this function will return false
1793
+     *
1794
+     * @param array $linkItem
1795
+     * @return boolean
1796
+     */
1797
+    public static function checkPasswordProtectedShare(array $linkItem) {
1798
+        if (!isset($linkItem['share_with'])) {
1799
+            return true;
1800
+        }
1801
+        if (!isset($linkItem['share_type'])) {
1802
+            return true;
1803
+        }
1804
+        if (!isset($linkItem['id'])) {
1805
+            return true;
1806
+        }
1807
+
1808
+        if ($linkItem['share_type'] != \OCP\Share::SHARE_TYPE_LINK) {
1809
+            return true;
1810
+        }
1811
+
1812
+        if ( \OC::$server->getSession()->exists('public_link_authenticated')
1813
+            && \OC::$server->getSession()->get('public_link_authenticated') === (string)$linkItem['id'] ) {
1814
+            return true;
1815
+        }
1816
+
1817
+        return false;
1818
+    }
1819
+
1820
+    /**
1821
+     * construct select statement
1822
+     * @param int $format
1823
+     * @param boolean $fileDependent ist it a file/folder share or a generla share
1824
+     * @param string $uidOwner
1825
+     * @return string select statement
1826
+     */
1827
+    private static function createSelectStatement($format, $fileDependent, $uidOwner = null) {
1828
+        $select = '*';
1829
+        if ($format == self::FORMAT_STATUSES) {
1830
+            if ($fileDependent) {
1831
+                $select = '`*PREFIX*share`.`id`, `*PREFIX*share`.`parent`, `share_type`, `path`, `storage`, '
1832
+                    . '`share_with`, `uid_owner` , `file_source`, `stime`, `*PREFIX*share`.`permissions`, '
1833
+                    . '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`, '
1834
+                    . '`uid_initiator`';
1835
+            } else {
1836
+                $select = '`id`, `parent`, `share_type`, `share_with`, `uid_owner`, `item_source`, `stime`, `*PREFIX*share`.`permissions`';
1837
+            }
1838
+        } else {
1839
+            if (isset($uidOwner)) {
1840
+                if ($fileDependent) {
1841
+                    $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,'
1842
+                        . ' `share_type`, `share_with`, `file_source`, `file_target`, `path`, `*PREFIX*share`.`permissions`, `stime`,'
1843
+                        . ' `expiration`, `token`, `storage`, `mail_send`, `uid_owner`, '
1844
+                        . '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`';
1845
+                } else {
1846
+                    $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `*PREFIX*share`.`permissions`,'
1847
+                        . ' `stime`, `file_source`, `expiration`, `token`, `mail_send`, `uid_owner`';
1848
+                }
1849
+            } else {
1850
+                if ($fileDependent) {
1851
+                    if ($format == \OCA\Files_Sharing\ShareBackend\File::FORMAT_GET_FOLDER_CONTENTS || $format == \OCA\Files_Sharing\ShareBackend\File::FORMAT_FILE_APP_ROOT) {
1852
+                        $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`, `uid_owner`, '
1853
+                            . '`share_type`, `share_with`, `file_source`, `path`, `file_target`, `stime`, '
1854
+                            . '`*PREFIX*share`.`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, '
1855
+                            . '`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`, `mail_send`';
1856
+                    } else {
1857
+                        $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`,'
1858
+                            . '`*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`,'
1859
+                            . '`file_source`, `path`, `file_target`, `*PREFIX*share`.`permissions`,'
1860
+                            . '`stime`, `expiration`, `token`, `storage`, `mail_send`,'
1861
+                            . '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`';
1862
+                    }
1863
+                }
1864
+            }
1865
+        }
1866
+        return $select;
1867
+    }
1868
+
1869
+
1870
+    /**
1871
+     * transform db results
1872
+     * @param array $row result
1873
+     */
1874
+    private static function transformDBResults(&$row) {
1875
+        if (isset($row['id'])) {
1876
+            $row['id'] = (int) $row['id'];
1877
+        }
1878
+        if (isset($row['share_type'])) {
1879
+            $row['share_type'] = (int) $row['share_type'];
1880
+        }
1881
+        if (isset($row['parent'])) {
1882
+            $row['parent'] = (int) $row['parent'];
1883
+        }
1884
+        if (isset($row['file_parent'])) {
1885
+            $row['file_parent'] = (int) $row['file_parent'];
1886
+        }
1887
+        if (isset($row['file_source'])) {
1888
+            $row['file_source'] = (int) $row['file_source'];
1889
+        }
1890
+        if (isset($row['permissions'])) {
1891
+            $row['permissions'] = (int) $row['permissions'];
1892
+        }
1893
+        if (isset($row['storage'])) {
1894
+            $row['storage'] = (int) $row['storage'];
1895
+        }
1896
+        if (isset($row['stime'])) {
1897
+            $row['stime'] = (int) $row['stime'];
1898
+        }
1899
+        if (isset($row['expiration']) && $row['share_type'] !== self::SHARE_TYPE_LINK) {
1900
+            // discard expiration date for non-link shares, which might have been
1901
+            // set by ancient bugs
1902
+            $row['expiration'] = null;
1903
+        }
1904
+    }
1905
+
1906
+    /**
1907
+     * format result
1908
+     * @param array $items result
1909
+     * @param string $column is it a file share or a general share ('file_target' or 'item_target')
1910
+     * @param \OCP\Share_Backend $backend sharing backend
1911
+     * @param int $format
1912
+     * @param array $parameters additional format parameters
1913
+     * @return array format result
1914
+     */
1915
+    private static function formatResult($items, $column, $backend, $format = self::FORMAT_NONE , $parameters = null) {
1916
+        if ($format === self::FORMAT_NONE) {
1917
+            return $items;
1918
+        } else if ($format === self::FORMAT_STATUSES) {
1919
+            $statuses = array();
1920
+            foreach ($items as $item) {
1921
+                if ($item['share_type'] === self::SHARE_TYPE_LINK) {
1922
+                    if ($item['uid_initiator'] !== \OC::$server->getUserSession()->getUser()->getUID()) {
1923
+                        continue;
1924
+                    }
1925
+                    $statuses[$item[$column]]['link'] = true;
1926
+                } else if (!isset($statuses[$item[$column]])) {
1927
+                    $statuses[$item[$column]]['link'] = false;
1928
+                }
1929
+                if (!empty($item['file_target'])) {
1930
+                    $statuses[$item[$column]]['path'] = $item['path'];
1931
+                }
1932
+            }
1933
+            return $statuses;
1934
+        } else {
1935
+            return $backend->formatItems($items, $format, $parameters);
1936
+        }
1937
+    }
1938
+
1939
+    /**
1940
+     * remove protocol from URL
1941
+     *
1942
+     * @param string $url
1943
+     * @return string
1944
+     */
1945
+    public static function removeProtocolFromUrl($url) {
1946
+        if (strpos($url, 'https://') === 0) {
1947
+            return substr($url, strlen('https://'));
1948
+        } else if (strpos($url, 'http://') === 0) {
1949
+            return substr($url, strlen('http://'));
1950
+        }
1951
+
1952
+        return $url;
1953
+    }
1954
+
1955
+    /**
1956
+     * try http post first with https and then with http as a fallback
1957
+     *
1958
+     * @param string $remoteDomain
1959
+     * @param string $urlSuffix
1960
+     * @param array $fields post parameters
1961
+     * @return array
1962
+     */
1963
+    private static function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields) {
1964
+        $protocol = 'https://';
1965
+        $result = [
1966
+            'success' => false,
1967
+            'result' => '',
1968
+        ];
1969
+        $try = 0;
1970
+        $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
1971
+        while ($result['success'] === false && $try < 2) {
1972
+            $federationEndpoints = $discoveryService->discover($protocol . $remoteDomain, 'FEDERATED_SHARING');
1973
+            $endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
1974
+            $client = \OC::$server->getHTTPClientService()->newClient();
1975
+
1976
+            try {
1977
+                $response = $client->post(
1978
+                    $protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT,
1979
+                    [
1980
+                        'body' => $fields,
1981
+                        'connect_timeout' => 10,
1982
+                    ]
1983
+                );
1984
+
1985
+                $result = ['success' => true, 'result' => $response->getBody()];
1986
+            } catch (\Exception $e) {
1987
+                $result = ['success' => false, 'result' => $e->getMessage()];
1988
+            }
1989
+
1990
+            $try++;
1991
+            $protocol = 'http://';
1992
+        }
1993
+
1994
+        return $result;
1995
+    }
1996
+
1997
+    /**
1998
+     * send server-to-server share to remote server
1999
+     *
2000
+     * @param string $token
2001
+     * @param string $shareWith
2002
+     * @param string $name
2003
+     * @param int $remote_id
2004
+     * @param string $owner
2005
+     * @return bool
2006
+     */
2007
+    private static function sendRemoteShare($token, $shareWith, $name, $remote_id, $owner) {
2008
+
2009
+        list($user, $remote) = Helper::splitUserRemote($shareWith);
2010
+
2011
+        if ($user && $remote) {
2012
+            $url = $remote;
2013
+
2014
+            $local = \OC::$server->getURLGenerator()->getAbsoluteURL('/');
2015
+
2016
+            $fields = array(
2017
+                'shareWith' => $user,
2018
+                'token' => $token,
2019
+                'name' => $name,
2020
+                'remoteId' => $remote_id,
2021
+                'owner' => $owner,
2022
+                'remote' => $local,
2023
+            );
2024
+
2025
+            $url = self::removeProtocolFromUrl($url);
2026
+            $result = self::tryHttpPostToShareEndpoint($url, '', $fields);
2027
+            $status = json_decode($result['result'], true);
2028
+
2029
+            if ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200)) {
2030
+                \OC_Hook::emit(\OCP\Share::class, 'federated_share_added', ['server' => $remote]);
2031
+                return true;
2032
+            }
2033
+
2034
+        }
2035
+
2036
+        return false;
2037
+    }
2038
+
2039
+    /**
2040
+     * send server-to-server unshare to remote server
2041
+     *
2042
+     * @param string $remote url
2043
+     * @param int $id share id
2044
+     * @param string $token
2045
+     * @return bool
2046
+     */
2047
+    private static function sendRemoteUnshare($remote, $id, $token) {
2048
+        $url = rtrim($remote, '/');
2049
+        $fields = array('token' => $token, 'format' => 'json');
2050
+        $url = self::removeProtocolFromUrl($url);
2051
+        $result = self::tryHttpPostToShareEndpoint($url, '/'.$id.'/unshare', $fields);
2052
+        $status = json_decode($result['result'], true);
2053
+
2054
+        return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200));
2055
+    }
2056
+
2057
+    /**
2058
+     * check if user can only share with group members
2059
+     * @return bool
2060
+     */
2061
+    public static function shareWithGroupMembersOnly() {
2062
+        $value = \OC::$server->getConfig()->getAppValue('core', 'shareapi_only_share_with_group_members', 'no');
2063
+        return $value === 'yes';
2064
+    }
2065
+
2066
+    /**
2067
+     * @return bool
2068
+     */
2069
+    public static function isDefaultExpireDateEnabled() {
2070
+        $defaultExpireDateEnabled = \OC::$server->getConfig()->getAppValue('core', 'shareapi_default_expire_date', 'no');
2071
+        return $defaultExpireDateEnabled === 'yes';
2072
+    }
2073
+
2074
+    /**
2075
+     * @return int
2076
+     */
2077
+    public static function getExpireInterval() {
2078
+        return (int)\OC::$server->getConfig()->getAppValue('core', 'shareapi_expire_after_n_days', '7');
2079
+    }
2080
+
2081
+    /**
2082
+     * Checks whether the given path is reachable for the given owner
2083
+     *
2084
+     * @param string $path path relative to files
2085
+     * @param string $ownerStorageId storage id of the owner
2086
+     *
2087
+     * @return boolean true if file is reachable, false otherwise
2088
+     */
2089
+    private static function isFileReachable($path, $ownerStorageId) {
2090
+        // if outside the home storage, file is always considered reachable
2091
+        if (!(substr($ownerStorageId, 0, 6) === 'home::' ||
2092
+            substr($ownerStorageId, 0, 13) === 'object::user:'
2093
+        )) {
2094
+            return true;
2095
+        }
2096
+
2097
+        // if inside the home storage, the file has to be under "/files/"
2098
+        $path = ltrim($path, '/');
2099
+        if (substr($path, 0, 6) === 'files/') {
2100
+            return true;
2101
+        }
2102
+
2103
+        return false;
2104
+    }
2105
+
2106
+    /**
2107
+     * @param IConfig $config
2108
+     * @return bool
2109
+     */
2110
+    public static function enforcePassword(IConfig $config) {
2111
+        $enforcePassword = $config->getAppValue('core', 'shareapi_enforce_links_password', 'no');
2112
+        return $enforcePassword === 'yes';
2113
+    }
2114
+
2115
+    /**
2116
+     * @param string $password
2117
+     * @throws \Exception
2118
+     */
2119
+    private static function verifyPassword($password) {
2120
+
2121
+        $accepted = true;
2122
+        $message = '';
2123
+        \OCP\Util::emitHook('\OC\Share', 'verifyPassword', [
2124
+            'password' => $password,
2125
+            'accepted' => &$accepted,
2126
+            'message' => &$message
2127
+        ]);
2128
+
2129
+        if (!$accepted) {
2130
+            throw new \Exception($message);
2131
+        }
2132
+    }
2133 2133
 }
Please login to merge, or discard this patch.
Spacing   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
 					'collectionOf' => $collectionOf,
85 85
 					'supportedFileExtensions' => $supportedFileExtensions
86 86
 				);
87
-				if(count(self::$backendTypes) === 1) {
87
+				if (count(self::$backendTypes) === 1) {
88 88
 					Util::addScript('core', 'merged-share-backend');
89 89
 				}
90 90
 				return true;
@@ -154,7 +154,7 @@  discard block
 block discarded – undo
154 154
 
155 155
 		$select = self::createSelectStatement(self::FORMAT_NONE, $fileDependent);
156 156
 
157
-		$where .= ' `' . $column . '` = ? AND `item_type` = ? ';
157
+		$where .= ' `'.$column.'` = ? AND `item_type` = ? ';
158 158
 		$arguments = array($itemSource, $itemType);
159 159
 		// for link shares $user === null
160 160
 		if ($user !== null) {
@@ -172,7 +172,7 @@  discard block
 block discarded – undo
172 172
 			$arguments[] = $owner;
173 173
 		}
174 174
 
175
-		$query = \OC_DB::prepare('SELECT ' . $select . ' FROM `*PREFIX*share` '. $fileDependentWhere . $where);
175
+		$query = \OC_DB::prepare('SELECT '.$select.' FROM `*PREFIX*share` '.$fileDependentWhere.$where);
176 176
 
177 177
 		$result = \OC_DB::executeAudited($query, $arguments);
178 178
 
@@ -180,7 +180,7 @@  discard block
 block discarded – undo
180 180
 			if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
181 181
 				continue;
182 182
 			}
183
-			if ($fileDependent && (int)$row['file_parent'] === -1) {
183
+			if ($fileDependent && (int) $row['file_parent'] === -1) {
184 184
 				// if it is a mount point we need to get the path from the mount manager
185 185
 				$mountManager = \OC\Files\Filesystem::getMountManager();
186 186
 				$mountPoint = $mountManager->findByStorageId($row['storage_id']);
@@ -191,7 +191,7 @@  discard block
 block discarded – undo
191 191
 					$row['path'] = $path;
192 192
 				} else {
193 193
 					\OC::$server->getLogger()->warning(
194
-						'Could not resolve mount point for ' . $row['storage_id'],
194
+						'Could not resolve mount point for '.$row['storage_id'],
195 195
 						['app' => 'OCP\Share']
196 196
 					);
197 197
 				}
@@ -200,7 +200,7 @@  discard block
 block discarded – undo
200 200
 		}
201 201
 
202 202
 		//if didn't found a result than let's look for a group share.
203
-		if(empty($shares) && $user !== null) {
203
+		if (empty($shares) && $user !== null) {
204 204
 			$userObject = \OC::$server->getUserManager()->get($user);
205 205
 			$groups = [];
206 206
 			if ($userObject) {
@@ -208,7 +208,7 @@  discard block
 block discarded – undo
208 208
 			}
209 209
 
210 210
 			if (!empty($groups)) {
211
-				$where = $fileDependentWhere . ' WHERE `' . $column . '` = ? AND `item_type` = ? AND `share_with` in (?)';
211
+				$where = $fileDependentWhere.' WHERE `'.$column.'` = ? AND `item_type` = ? AND `share_with` in (?)';
212 212
 				$arguments = array($itemSource, $itemType, $groups);
213 213
 				$types = array(null, null, IQueryBuilder::PARAM_STR_ARRAY);
214 214
 
@@ -222,7 +222,7 @@  discard block
 block discarded – undo
222 222
 				// class isn't static anymore...
223 223
 				$conn = \OC::$server->getDatabaseConnection();
224 224
 				$result = $conn->executeQuery(
225
-					'SELECT ' . $select . ' FROM `*PREFIX*share` ' . $where,
225
+					'SELECT '.$select.' FROM `*PREFIX*share` '.$where,
226 226
 					$arguments,
227 227
 					$types
228 228
 				);
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
 		$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `token` = ?', 1);
265 265
 		$result = $query->execute(array($token));
266 266
 		if ($result === false) {
267
-			\OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage() . ', token=' . $token, ILogger::ERROR);
267
+			\OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage().', token='.$token, ILogger::ERROR);
268 268
 		}
269 269
 		$row = $result->fetchRow();
270 270
 		if ($row === false) {
@@ -371,12 +371,12 @@  discard block
 block discarded – undo
371 371
 
372 372
 		//verify that we don't share a folder which already contains a share mount point
373 373
 		if ($itemType === 'folder') {
374
-			$path = '/' . $uidOwner . '/files' . \OC\Files\Filesystem::getPath($itemSource) . '/';
374
+			$path = '/'.$uidOwner.'/files'.\OC\Files\Filesystem::getPath($itemSource).'/';
375 375
 			$mountManager = \OC\Files\Filesystem::getMountManager();
376 376
 			$mounts = $mountManager->findIn($path);
377 377
 			foreach ($mounts as $mount) {
378 378
 				if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
379
-					$message = 'Sharing "' . $itemSourceName . '" failed, because it contains files shared with you!';
379
+					$message = 'Sharing "'.$itemSourceName.'" failed, because it contains files shared with you!';
380 380
 					\OCP\Util::writeLog('OCP\Share', $message, ILogger::DEBUG);
381 381
 					throw new \Exception($message);
382 382
 				}
@@ -386,7 +386,7 @@  discard block
 block discarded – undo
386 386
 
387 387
 		// single file shares should never have delete permissions
388 388
 		if ($itemType === 'file') {
389
-			$permissions = (int)$permissions & ~\OCP\Constants::PERMISSION_DELETE;
389
+			$permissions = (int) $permissions & ~\OCP\Constants::PERMISSION_DELETE;
390 390
 		}
391 391
 
392 392
 		//Validate expirationDate
@@ -540,7 +540,7 @@  discard block
 block discarded – undo
540 540
 					} else {
541 541
 						// reuse the already set password, but only if we change permissions
542 542
 						// otherwise the user disabled the password protection
543
-						if ($checkExists && (int)$permissions !== (int)$oldPermissions) {
543
+						if ($checkExists && (int) $permissions !== (int) $oldPermissions) {
544 544
 							$shareWith = $checkExists['share_with'];
545 545
 						}
546 546
 					}
@@ -612,10 +612,10 @@  discard block
 block discarded – undo
612 612
 				throw new \Exception($message_t);
613 613
 			}
614 614
 
615
-			$token = \OC::$server->getSecureRandom()->generate(self::TOKEN_LENGTH, \OCP\Security\ISecureRandom::CHAR_LOWER . \OCP\Security\ISecureRandom::CHAR_UPPER .
615
+			$token = \OC::$server->getSecureRandom()->generate(self::TOKEN_LENGTH, \OCP\Security\ISecureRandom::CHAR_LOWER.\OCP\Security\ISecureRandom::CHAR_UPPER.
616 616
 				\OCP\Security\ISecureRandom::CHAR_DIGITS);
617 617
 
618
-			$shareWith = $user . '@' . $remote;
618
+			$shareWith = $user.'@'.$remote;
619 619
 			$shareId = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, $token, $itemSourceName);
620 620
 
621 621
 			$send = false;
@@ -666,12 +666,12 @@  discard block
 block discarded – undo
666 666
 		$currentUser = $owner ? $owner : \OC_User::getUser();
667 667
 		foreach ($items as $item) {
668 668
 			// delete the item with the expected share_type and owner
669
-			if ((int)$item['share_type'] === (int)$shareType && $item['uid_owner'] === $currentUser) {
669
+			if ((int) $item['share_type'] === (int) $shareType && $item['uid_owner'] === $currentUser) {
670 670
 				$toDelete = $item;
671 671
 				// if there is more then one result we don't have to delete the children
672 672
 				// but update their parent. For group shares the new parent should always be
673 673
 				// the original group share and not the db entry with the unique name
674
-			} else if ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) {
674
+			} else if ((int) $item['share_type'] === self::$shareTypeGroupUserUnique) {
675 675
 				$newParent = $item['parent'];
676 676
 			} else {
677 677
 				$newParent = $item['id'];
@@ -703,7 +703,7 @@  discard block
 block discarded – undo
703 703
 
704 704
 		$result = $query->execute(array($status, $itemType, $itemSource, $shareType, $recipient));
705 705
 
706
-		if($result === false) {
706
+		if ($result === false) {
707 707
 			\OCP\Util::writeLog('OCP\Share', 'Couldn\'t set send mail status', ILogger::ERROR);
708 708
 		}
709 709
 	}
@@ -729,7 +729,7 @@  discard block
 block discarded – undo
729 729
 		if ($defaultExpireDateEnforced && $shareTime === null) {
730 730
 			$items = self::getItemShared($itemType, $itemSource);
731 731
 			$firstItem = reset($items);
732
-			$shareTime = (int)$firstItem['stime'];
732
+			$shareTime = (int) $firstItem['stime'];
733 733
 		}
734 734
 
735 735
 		if ($defaultExpireDateEnforced) {
@@ -737,9 +737,9 @@  discard block
 block discarded – undo
737 737
 			$maxDate = new \DateTime();
738 738
 			$maxDate->setTimestamp($shareTime);
739 739
 			$maxDays = \OC::$server->getConfig()->getAppValue('core', 'shareapi_expire_after_n_days', '7');
740
-			$maxDate->add(new \DateInterval('P' . $maxDays . 'D'));
740
+			$maxDate->add(new \DateInterval('P'.$maxDays.'D'));
741 741
 			if ($date > $maxDate) {
742
-				$warning = 'Cannot set expiration date. Shares cannot expire later than ' . $maxDays . ' after they have been shared';
742
+				$warning = 'Cannot set expiration date. Shares cannot expire later than '.$maxDays.' after they have been shared';
743 743
 				$warning_t = $l->t('Cannot set expiration date. Shares cannot expire later than %s after they have been shared', array($maxDays));
744 744
 				\OCP\Util::writeLog('OCP\Share', $warning, ILogger::WARN);
745 745
 				throw new \Exception($warning_t);
@@ -801,7 +801,7 @@  discard block
 block discarded – undo
801 801
 	 */
802 802
 	protected static function unshareItem(array $item, $newParent = null) {
803 803
 
804
-		$shareType = (int)$item['share_type'];
804
+		$shareType = (int) $item['share_type'];
805 805
 		$shareWith = null;
806 806
 		if ($shareType !== \OCP\Share::SHARE_TYPE_LINK) {
807 807
 			$shareWith = $item['share_with'];
@@ -817,7 +817,7 @@  discard block
 block discarded – undo
817 817
 			'itemParent'    => $item['parent'],
818 818
 			'uidOwner'      => $item['uid_owner'],
819 819
 		);
820
-		if($item['item_type'] === 'file' || $item['item_type'] === 'folder') {
820
+		if ($item['item_type'] === 'file' || $item['item_type'] === 'folder') {
821 821
 			$hookParams['fileSource'] = $item['file_source'];
822 822
 			$hookParams['fileTarget'] = $item['file_target'];
823 823
 		}
@@ -827,7 +827,7 @@  discard block
 block discarded – undo
827 827
 		$deletedShares[] = $hookParams;
828 828
 		$hookParams['deletedShares'] = $deletedShares;
829 829
 		\OC_Hook::emit(\OCP\Share::class, 'post_unshare', $hookParams);
830
-		if ((int)$item['share_type'] === \OCP\Share::SHARE_TYPE_REMOTE && \OC::$server->getUserSession()->getUser()) {
830
+		if ((int) $item['share_type'] === \OCP\Share::SHARE_TYPE_REMOTE && \OC::$server->getUserSession()->getUser()) {
831 831
 			list(, $remote) = Helper::splitUserRemote($item['share_with']);
832 832
 			self::sendRemoteUnshare($remote, $item['id'], $item['token']);
833 833
 		}
@@ -988,7 +988,7 @@  discard block
 block discarded – undo
988 988
 		// Get filesystem root to add it to the file target and remove from the
989 989
 		// file source, match file_source with the file cache
990 990
 		if ($itemType == 'file' || $itemType == 'folder') {
991
-			if(!is_null($uidOwner)) {
991
+			if (!is_null($uidOwner)) {
992 992
 				$root = \OC\Files\Filesystem::getRoot();
993 993
 			} else {
994 994
 				$root = '';
@@ -1133,7 +1133,7 @@  discard block
 block discarded – undo
1133 1133
 		$result = $query->execute($queryArgs);
1134 1134
 		if ($result === false) {
1135 1135
 			\OCP\Util::writeLog('OCP\Share',
1136
-				\OC_DB::getErrorMessage() . ', select=' . $select . ' where=',
1136
+				\OC_DB::getErrorMessage().', select='.$select.' where=',
1137 1137
 				ILogger::ERROR);
1138 1138
 		}
1139 1139
 		$items = array();
@@ -1175,14 +1175,14 @@  discard block
 block discarded – undo
1175 1175
 						}
1176 1176
 						// Switch ids if sharing permission is granted on only
1177 1177
 						// one share to ensure correct parent is used if resharing
1178
-						if (~(int)$items[$id]['permissions'] & \OCP\Constants::PERMISSION_SHARE
1179
-							&& (int)$row['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
1178
+						if (~(int) $items[$id]['permissions'] & \OCP\Constants::PERMISSION_SHARE
1179
+							&& (int) $row['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
1180 1180
 							$items[$row['id']] = $items[$id];
1181 1181
 							$switchedItems[$id] = $row['id'];
1182 1182
 							unset($items[$id]);
1183 1183
 							$id = $row['id'];
1184 1184
 						}
1185
-						$items[$id]['permissions'] |= (int)$row['permissions'];
1185
+						$items[$id]['permissions'] |= (int) $row['permissions'];
1186 1186
 
1187 1187
 					}
1188 1188
 					continue;
@@ -1196,8 +1196,8 @@  discard block
 block discarded – undo
1196 1196
 					$query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?');
1197 1197
 					$parentResult = $query->execute(array($row['parent']));
1198 1198
 					if ($result === false) {
1199
-						\OCP\Util::writeLog('OCP\Share', 'Can\'t select parent: ' .
1200
-							\OC_DB::getErrorMessage() . ', select=' . $select . ' where=' . $where,
1199
+						\OCP\Util::writeLog('OCP\Share', 'Can\'t select parent: '.
1200
+							\OC_DB::getErrorMessage().', select='.$select.' where='.$where,
1201 1201
 							ILogger::ERROR);
1202 1202
 					} else {
1203 1203
 						$parentRow = $parentResult->fetchRow();
@@ -1207,7 +1207,7 @@  discard block
 block discarded – undo
1207 1207
 						$subPath = substr($row['path'], $pos);
1208 1208
 						$splitPath = explode('/', $subPath);
1209 1209
 						foreach (array_slice($splitPath, 2) as $pathPart) {
1210
-							$tmpPath = $tmpPath . '/' . $pathPart;
1210
+							$tmpPath = $tmpPath.'/'.$pathPart;
1211 1211
 						}
1212 1212
 						$row['path'] = $tmpPath;
1213 1213
 					}
@@ -1226,7 +1226,7 @@  discard block
 block discarded – undo
1226 1226
 				}
1227 1227
 			}
1228 1228
 
1229
-			if($checkExpireDate) {
1229
+			if ($checkExpireDate) {
1230 1230
 				if (self::expireItem($row)) {
1231 1231
 					continue;
1232 1232
 				}
@@ -1237,11 +1237,11 @@  discard block
 block discarded – undo
1237 1237
 			}
1238 1238
 			// Add display names to result
1239 1239
 			$row['share_with_displayname'] = $row['share_with'];
1240
-			if ( isset($row['share_with']) && $row['share_with'] != '' &&
1240
+			if (isset($row['share_with']) && $row['share_with'] != '' &&
1241 1241
 				$row['share_type'] === self::SHARE_TYPE_USER) {
1242 1242
 				$shareWithUser = \OC::$server->getUserManager()->get($row['share_with']);
1243 1243
 				$row['share_with_displayname'] = $shareWithUser === null ? $row['share_with'] : $shareWithUser->getDisplayName();
1244
-			} else if(isset($row['share_with']) && $row['share_with'] != '' &&
1244
+			} else if (isset($row['share_with']) && $row['share_with'] != '' &&
1245 1245
 				$row['share_type'] === self::SHARE_TYPE_REMOTE) {
1246 1246
 				$addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD']);
1247 1247
 				foreach ($addressBookEntries as $entry) {
@@ -1252,7 +1252,7 @@  discard block
 block discarded – undo
1252 1252
 					}
1253 1253
 				}
1254 1254
 			}
1255
-			if ( isset($row['uid_owner']) && $row['uid_owner'] != '') {
1255
+			if (isset($row['uid_owner']) && $row['uid_owner'] != '') {
1256 1256
 				$ownerUser = \OC::$server->getUserManager()->get($row['uid_owner']);
1257 1257
 				$row['displayname_owner'] = $ownerUser === null ? $row['uid_owner'] : $ownerUser->getDisplayName();
1258 1258
 			}
@@ -1401,7 +1401,7 @@  discard block
 block discarded – undo
1401 1401
 				// for file/folder shares we need to compare file_source, otherwise we compare item_source
1402 1402
 				// only group shares if they already point to the same target, otherwise the file where shared
1403 1403
 				// before grouping of shares was added. In this case we don't group them toi avoid confusions
1404
-				if (( $fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) ||
1404
+				if (($fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) ||
1405 1405
 					(!$fileSharing && $item['item_source'] === $r['item_source'] && $item['item_target'] === $r['item_target'])) {
1406 1406
 					// add the first item to the list of grouped shares
1407 1407
 					if (!isset($result[$key]['grouped'])) {
@@ -1447,7 +1447,7 @@  discard block
 block discarded – undo
1447 1447
 		$groupItemTarget = $itemTarget = $fileSource = $parent = 0;
1448 1448
 
1449 1449
 		$result = self::checkReshare($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, $itemSourceName, $expirationDate);
1450
-		if(!empty($result)) {
1450
+		if (!empty($result)) {
1451 1451
 			$parent = $result['parent'];
1452 1452
 			$itemSource = $result['itemSource'];
1453 1453
 			$fileSource = $result['fileSource'];
@@ -1541,11 +1541,11 @@  discard block
 block discarded – undo
1541 1541
 				$itemTarget = $sourceExists['item_target'];
1542 1542
 
1543 1543
 				// for group shares we don't need a additional entry if the target is the same
1544
-				if($isGroupShare && $groupItemTarget === $itemTarget) {
1544
+				if ($isGroupShare && $groupItemTarget === $itemTarget) {
1545 1545
 					continue;
1546 1546
 				}
1547 1547
 
1548
-			} elseif(!$sourceExists && !$isGroupShare)  {
1548
+			} elseif (!$sourceExists && !$isGroupShare) {
1549 1549
 
1550 1550
 				$itemTarget = Helper::generateTarget($itemType, $itemSource, $userShareType, $user,
1551 1551
 					$uidOwner, $suggestedItemTarget, $parent);
@@ -1676,8 +1676,8 @@  discard block
 block discarded – undo
1676 1676
 
1677 1677
 		if ($checkReshare && $checkReshare['uid_owner'] !== \OC_User::getUser()) {
1678 1678
 			// Check if share permissions is granted
1679
-			if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
1680
-				if (~(int)$checkReshare['permissions'] & $permissions) {
1679
+			if (self::isResharingAllowed() && (int) $checkReshare['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
1680
+				if (~(int) $checkReshare['permissions'] & $permissions) {
1681 1681
 					$message = 'Sharing %1$s failed, because the permissions exceed permissions granted to %2$s';
1682 1682
 					$message_t = $l->t('Sharing %1$s failed, because the permissions exceed permissions granted to %2$s', array($itemSourceName, $uidOwner));
1683 1683
 
@@ -1689,7 +1689,7 @@  discard block
 block discarded – undo
1689 1689
 
1690 1690
 					$result['expirationDate'] = $expirationDate;
1691 1691
 					// $checkReshare['expiration'] could be null and then is always less than any value
1692
-					if(isset($checkReshare['expiration']) && $checkReshare['expiration'] < $expirationDate) {
1692
+					if (isset($checkReshare['expiration']) && $checkReshare['expiration'] < $expirationDate) {
1693 1693
 						$result['expirationDate'] = $checkReshare['expiration'];
1694 1694
 					}
1695 1695
 
@@ -1781,7 +1781,7 @@  discard block
 block discarded – undo
1781 1781
 
1782 1782
 		$id = false;
1783 1783
 		if ($result) {
1784
-			$id =  \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share');
1784
+			$id = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share');
1785 1785
 		}
1786 1786
 
1787 1787
 		return $id;
@@ -1809,8 +1809,8 @@  discard block
 block discarded – undo
1809 1809
 			return true;
1810 1810
 		}
1811 1811
 
1812
-		if ( \OC::$server->getSession()->exists('public_link_authenticated')
1813
-			&& \OC::$server->getSession()->get('public_link_authenticated') === (string)$linkItem['id'] ) {
1812
+		if (\OC::$server->getSession()->exists('public_link_authenticated')
1813
+			&& \OC::$server->getSession()->get('public_link_authenticated') === (string) $linkItem['id']) {
1814 1814
 			return true;
1815 1815
 		}
1816 1816
 
@@ -1912,7 +1912,7 @@  discard block
 block discarded – undo
1912 1912
 	 * @param array $parameters additional format parameters
1913 1913
 	 * @return array format result
1914 1914
 	 */
1915
-	private static function formatResult($items, $column, $backend, $format = self::FORMAT_NONE , $parameters = null) {
1915
+	private static function formatResult($items, $column, $backend, $format = self::FORMAT_NONE, $parameters = null) {
1916 1916
 		if ($format === self::FORMAT_NONE) {
1917 1917
 			return $items;
1918 1918
 		} else if ($format === self::FORMAT_STATUSES) {
@@ -1969,13 +1969,13 @@  discard block
 block discarded – undo
1969 1969
 		$try = 0;
1970 1970
 		$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
1971 1971
 		while ($result['success'] === false && $try < 2) {
1972
-			$federationEndpoints = $discoveryService->discover($protocol . $remoteDomain, 'FEDERATED_SHARING');
1972
+			$federationEndpoints = $discoveryService->discover($protocol.$remoteDomain, 'FEDERATED_SHARING');
1973 1973
 			$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
1974 1974
 			$client = \OC::$server->getHTTPClientService()->newClient();
1975 1975
 
1976 1976
 			try {
1977 1977
 				$response = $client->post(
1978
-					$protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT,
1978
+					$protocol.$remoteDomain.$endpoint.$urlSuffix.'?format='.self::RESPONSE_FORMAT,
1979 1979
 					[
1980 1980
 						'body' => $fields,
1981 1981
 						'connect_timeout' => 10,
@@ -2075,7 +2075,7 @@  discard block
 block discarded – undo
2075 2075
 	 * @return int
2076 2076
 	 */
2077 2077
 	public static function getExpireInterval() {
2078
-		return (int)\OC::$server->getConfig()->getAppValue('core', 'shareapi_expire_after_n_days', '7');
2078
+		return (int) \OC::$server->getConfig()->getAppValue('core', 'shareapi_expire_after_n_days', '7');
2079 2079
 	}
2080 2080
 
2081 2081
 	/**
Please login to merge, or discard this patch.
core/ajax/update.php 2 patches
Indentation   +182 added lines, -182 removed lines patch added patch discarded remove patch
@@ -33,7 +33,7 @@  discard block
 block discarded – undo
33 33
 use Symfony\Component\EventDispatcher\GenericEvent;
34 34
 
35 35
 if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
36
-	@set_time_limit(0);
36
+    @set_time_limit(0);
37 37
 }
38 38
 
39 39
 require_once '../../lib/base.php';
@@ -47,192 +47,192 @@  discard block
 block discarded – undo
47 47
 $eventSource->send('success', (string)$l->t('Preparing update'));
48 48
 
49 49
 class FeedBackHandler {
50
-	/** @var integer */
51
-	private $progressStateMax = 100;
52
-	/** @var integer */
53
-	private $progressStateStep = 0;
54
-	/** @var string */
55
-	private $currentStep;
56
-	/** @var \OCP\IEventSource */
57
-	private $eventSource;
58
-	/** @var \OCP\IL10N */
59
-	private $l10n;
60
-
61
-	public function __construct(\OCP\IEventSource $eventSource, \OCP\IL10N $l10n) {
62
-		$this->eventSource = $eventSource;
63
-		$this->l10n = $l10n;
64
-	}
65
-
66
-	public function handleRepairFeedback($event) {
67
-		if (!$event instanceof GenericEvent) {
68
-			return;
69
-		}
70
-
71
-		switch ($event->getSubject()) {
72
-			case '\OC\Repair::startProgress':
73
-				$this->progressStateMax = $event->getArgument(0);
74
-				$this->progressStateStep = 0;
75
-				$this->currentStep = $event->getArgument(1);
76
-				break;
77
-			case '\OC\Repair::advance':
78
-				$this->progressStateStep += $event->getArgument(0);
79
-				$desc = $event->getArgument(1);
80
-				if (empty($desc)) {
81
-					$desc = $this->currentStep;
82
-				}
83
-				$this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $desc]));
84
-				break;
85
-			case '\OC\Repair::finishProgress':
86
-				$this->progressStateMax = $this->progressStateStep;
87
-				$this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $this->currentStep]));
88
-				break;
89
-			case '\OC\Repair::step':
90
-				break;
91
-			case '\OC\Repair::info':
92
-				break;
93
-			case '\OC\Repair::warning':
94
-				$this->eventSource->send('notice', (string)$this->l10n->t('Repair warning: ') . $event->getArgument(0));
95
-				break;
96
-			case '\OC\Repair::error':
97
-				$this->eventSource->send('notice', (string)$this->l10n->t('Repair error: ') . $event->getArgument(0));
98
-				break;
99
-		}
100
-	}
50
+    /** @var integer */
51
+    private $progressStateMax = 100;
52
+    /** @var integer */
53
+    private $progressStateStep = 0;
54
+    /** @var string */
55
+    private $currentStep;
56
+    /** @var \OCP\IEventSource */
57
+    private $eventSource;
58
+    /** @var \OCP\IL10N */
59
+    private $l10n;
60
+
61
+    public function __construct(\OCP\IEventSource $eventSource, \OCP\IL10N $l10n) {
62
+        $this->eventSource = $eventSource;
63
+        $this->l10n = $l10n;
64
+    }
65
+
66
+    public function handleRepairFeedback($event) {
67
+        if (!$event instanceof GenericEvent) {
68
+            return;
69
+        }
70
+
71
+        switch ($event->getSubject()) {
72
+            case '\OC\Repair::startProgress':
73
+                $this->progressStateMax = $event->getArgument(0);
74
+                $this->progressStateStep = 0;
75
+                $this->currentStep = $event->getArgument(1);
76
+                break;
77
+            case '\OC\Repair::advance':
78
+                $this->progressStateStep += $event->getArgument(0);
79
+                $desc = $event->getArgument(1);
80
+                if (empty($desc)) {
81
+                    $desc = $this->currentStep;
82
+                }
83
+                $this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $desc]));
84
+                break;
85
+            case '\OC\Repair::finishProgress':
86
+                $this->progressStateMax = $this->progressStateStep;
87
+                $this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $this->currentStep]));
88
+                break;
89
+            case '\OC\Repair::step':
90
+                break;
91
+            case '\OC\Repair::info':
92
+                break;
93
+            case '\OC\Repair::warning':
94
+                $this->eventSource->send('notice', (string)$this->l10n->t('Repair warning: ') . $event->getArgument(0));
95
+                break;
96
+            case '\OC\Repair::error':
97
+                $this->eventSource->send('notice', (string)$this->l10n->t('Repair error: ') . $event->getArgument(0));
98
+                break;
99
+        }
100
+    }
101 101
 }
102 102
 
103 103
 if (\OCP\Util::needUpgrade()) {
104 104
 
105
-	$config = \OC::$server->getSystemConfig();
106
-	if ($config->getValue('upgrade.disable-web', false)) {
107
-		$eventSource->send('failure', (string)$l->t('Please use the command line updater because automatic updating is disabled in the config.php.'));
108
-		$eventSource->close();
109
-		exit();
110
-	}
111
-
112
-	// if a user is currently logged in, their session must be ignored to
113
-	// avoid side effects
114
-	\OC_User::setIncognitoMode(true);
115
-
116
-	$logger = \OC::$server->getLogger();
117
-	$config = \OC::$server->getConfig();
118
-	$updater = new \OC\Updater(
119
-			$config,
120
-			\OC::$server->getIntegrityCodeChecker(),
121
-			$logger,
122
-			\OC::$server->query(\OC\Installer::class),
123
-			\OC::$server->getJobList()
124
-	);
125
-	$incompatibleApps = [];
126
-
127
-	$dispatcher = \OC::$server->getEventDispatcher();
128
-	$dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($eventSource, $l) {
129
-		if ($event instanceof GenericEvent) {
130
-			$eventSource->send('success', (string)$l->t('[%d / %d]: %s', [$event[0], $event[1], $event->getSubject()]));
131
-		}
132
-	});
133
-	$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($eventSource, $l) {
134
-		if ($event instanceof GenericEvent) {
135
-			$eventSource->send('success', (string)$l->t('[%d / %d]: Checking table %s', [$event[0], $event[1], $event->getSubject()]));
136
-		}
137
-	});
138
-	$feedBack = new FeedBackHandler($eventSource, $l);
139
-	$dispatcher->addListener('\OC\Repair::startProgress', [$feedBack, 'handleRepairFeedback']);
140
-	$dispatcher->addListener('\OC\Repair::advance', [$feedBack, 'handleRepairFeedback']);
141
-	$dispatcher->addListener('\OC\Repair::finishProgress', [$feedBack, 'handleRepairFeedback']);
142
-	$dispatcher->addListener('\OC\Repair::step', [$feedBack, 'handleRepairFeedback']);
143
-	$dispatcher->addListener('\OC\Repair::info', [$feedBack, 'handleRepairFeedback']);
144
-	$dispatcher->addListener('\OC\Repair::warning', [$feedBack, 'handleRepairFeedback']);
145
-	$dispatcher->addListener('\OC\Repair::error', [$feedBack, 'handleRepairFeedback']);
146
-
147
-	$updater->listen('\OC\Updater', 'maintenanceEnabled', function () use ($eventSource, $l) {
148
-		$eventSource->send('success', (string)$l->t('Turned on maintenance mode'));
149
-	});
150
-	$updater->listen('\OC\Updater', 'maintenanceDisabled', function () use ($eventSource, $l) {
151
-		$eventSource->send('success', (string)$l->t('Turned off maintenance mode'));
152
-	});
153
-	$updater->listen('\OC\Updater', 'maintenanceActive', function () use ($eventSource, $l) {
154
-		$eventSource->send('success', (string)$l->t('Maintenance mode is kept active'));
155
-	});
156
-	$updater->listen('\OC\Updater', 'waitForCronToFinish', function () use ($eventSource, $l) {
157
-		$eventSource->send('success', (string)$l->t('Waiting for cron to finish (checks again in 5 seconds) …'));
158
-	});
159
-	$updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($eventSource, $l) {
160
-		$eventSource->send('success', (string)$l->t('Updating database schema'));
161
-	});
162
-	$updater->listen('\OC\Updater', 'dbUpgrade', function () use ($eventSource, $l) {
163
-		$eventSource->send('success', (string)$l->t('Updated database'));
164
-	});
165
-	$updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($eventSource, $l) {
166
-		$eventSource->send('success', (string)$l->t('Checking whether the database schema can be updated (this can take a long time depending on the database size)'));
167
-	});
168
-	$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use ($eventSource, $l) {
169
-		$eventSource->send('success', (string)$l->t('Checked database schema update'));
170
-	});
171
-	$updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($eventSource, $l) {
172
-		$eventSource->send('success', (string)$l->t('Checking updates of apps'));
173
-	});
174
-	$updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use ($eventSource, $l) {
175
-		$eventSource->send('success', (string)$l->t('Checking for update of app "%s" in appstore', [$app]));
176
-	});
177
-	$updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use ($eventSource, $l) {
178
-		$eventSource->send('success', (string)$l->t('Update app "%s" from appstore', [$app]));
179
-	});
180
-	$updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use ($eventSource, $l) {
181
-		$eventSource->send('success', (string)$l->t('Checked for update of app "%s" in appstore', [$app]));
182
-	});
183
-	$updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($eventSource, $l) {
184
-		$eventSource->send('success', (string)$l->t('Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)', [$app]));
185
-	});
186
-	$updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($eventSource, $l) {
187
-		$eventSource->send('success', (string)$l->t('Checked database schema update for apps'));
188
-	});
189
-	$updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($eventSource, $l) {
190
-		$eventSource->send('success', (string)$l->t('Updated "%1$s" to %2$s', array($app, $version)));
191
-	});
192
-	$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use (&$incompatibleApps) {
193
-		$incompatibleApps[]= $app;
194
-	});
195
-	$updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource, $config) {
196
-		$eventSource->send('failure', $message);
197
-		$eventSource->close();
198
-		$config->setSystemValue('maintenance', false);
199
-	});
200
-	$updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
201
-		$eventSource->send('success', (string)$l->t('Set log level to debug'));
202
-	});
203
-	$updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
204
-		$eventSource->send('success', (string)$l->t('Reset log level'));
205
-	});
206
-	$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($eventSource, $l) {
207
-		$eventSource->send('success', (string)$l->t('Starting code integrity check'));
208
-	});
209
-	$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($eventSource, $l) {
210
-		$eventSource->send('success', (string)$l->t('Finished code integrity check'));
211
-	});
212
-
213
-	try {
214
-		$updater->upgrade();
215
-	} catch (\Exception $e) {
216
-		\OC::$server->getLogger()->logException($e, [
217
-			'level' => ILogger::ERROR,
218
-			'app' => 'update',
219
-		]);
220
-		$eventSource->send('failure', get_class($e) . ': ' . $e->getMessage());
221
-		$eventSource->close();
222
-		exit();
223
-	}
224
-
225
-	$disabledApps = [];
226
-	foreach ($incompatibleApps as $app) {
227
-		$disabledApps[$app] = (string) $l->t('%s (incompatible)', [$app]);
228
-	}
229
-
230
-	if (!empty($disabledApps)) {
231
-		$eventSource->send('notice',
232
-			(string)$l->t('Following apps have been disabled: %s', [implode(', ', $disabledApps)]));
233
-	}
105
+    $config = \OC::$server->getSystemConfig();
106
+    if ($config->getValue('upgrade.disable-web', false)) {
107
+        $eventSource->send('failure', (string)$l->t('Please use the command line updater because automatic updating is disabled in the config.php.'));
108
+        $eventSource->close();
109
+        exit();
110
+    }
111
+
112
+    // if a user is currently logged in, their session must be ignored to
113
+    // avoid side effects
114
+    \OC_User::setIncognitoMode(true);
115
+
116
+    $logger = \OC::$server->getLogger();
117
+    $config = \OC::$server->getConfig();
118
+    $updater = new \OC\Updater(
119
+            $config,
120
+            \OC::$server->getIntegrityCodeChecker(),
121
+            $logger,
122
+            \OC::$server->query(\OC\Installer::class),
123
+            \OC::$server->getJobList()
124
+    );
125
+    $incompatibleApps = [];
126
+
127
+    $dispatcher = \OC::$server->getEventDispatcher();
128
+    $dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($eventSource, $l) {
129
+        if ($event instanceof GenericEvent) {
130
+            $eventSource->send('success', (string)$l->t('[%d / %d]: %s', [$event[0], $event[1], $event->getSubject()]));
131
+        }
132
+    });
133
+    $dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($eventSource, $l) {
134
+        if ($event instanceof GenericEvent) {
135
+            $eventSource->send('success', (string)$l->t('[%d / %d]: Checking table %s', [$event[0], $event[1], $event->getSubject()]));
136
+        }
137
+    });
138
+    $feedBack = new FeedBackHandler($eventSource, $l);
139
+    $dispatcher->addListener('\OC\Repair::startProgress', [$feedBack, 'handleRepairFeedback']);
140
+    $dispatcher->addListener('\OC\Repair::advance', [$feedBack, 'handleRepairFeedback']);
141
+    $dispatcher->addListener('\OC\Repair::finishProgress', [$feedBack, 'handleRepairFeedback']);
142
+    $dispatcher->addListener('\OC\Repair::step', [$feedBack, 'handleRepairFeedback']);
143
+    $dispatcher->addListener('\OC\Repair::info', [$feedBack, 'handleRepairFeedback']);
144
+    $dispatcher->addListener('\OC\Repair::warning', [$feedBack, 'handleRepairFeedback']);
145
+    $dispatcher->addListener('\OC\Repair::error', [$feedBack, 'handleRepairFeedback']);
146
+
147
+    $updater->listen('\OC\Updater', 'maintenanceEnabled', function () use ($eventSource, $l) {
148
+        $eventSource->send('success', (string)$l->t('Turned on maintenance mode'));
149
+    });
150
+    $updater->listen('\OC\Updater', 'maintenanceDisabled', function () use ($eventSource, $l) {
151
+        $eventSource->send('success', (string)$l->t('Turned off maintenance mode'));
152
+    });
153
+    $updater->listen('\OC\Updater', 'maintenanceActive', function () use ($eventSource, $l) {
154
+        $eventSource->send('success', (string)$l->t('Maintenance mode is kept active'));
155
+    });
156
+    $updater->listen('\OC\Updater', 'waitForCronToFinish', function () use ($eventSource, $l) {
157
+        $eventSource->send('success', (string)$l->t('Waiting for cron to finish (checks again in 5 seconds) …'));
158
+    });
159
+    $updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($eventSource, $l) {
160
+        $eventSource->send('success', (string)$l->t('Updating database schema'));
161
+    });
162
+    $updater->listen('\OC\Updater', 'dbUpgrade', function () use ($eventSource, $l) {
163
+        $eventSource->send('success', (string)$l->t('Updated database'));
164
+    });
165
+    $updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($eventSource, $l) {
166
+        $eventSource->send('success', (string)$l->t('Checking whether the database schema can be updated (this can take a long time depending on the database size)'));
167
+    });
168
+    $updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use ($eventSource, $l) {
169
+        $eventSource->send('success', (string)$l->t('Checked database schema update'));
170
+    });
171
+    $updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($eventSource, $l) {
172
+        $eventSource->send('success', (string)$l->t('Checking updates of apps'));
173
+    });
174
+    $updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use ($eventSource, $l) {
175
+        $eventSource->send('success', (string)$l->t('Checking for update of app "%s" in appstore', [$app]));
176
+    });
177
+    $updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use ($eventSource, $l) {
178
+        $eventSource->send('success', (string)$l->t('Update app "%s" from appstore', [$app]));
179
+    });
180
+    $updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use ($eventSource, $l) {
181
+        $eventSource->send('success', (string)$l->t('Checked for update of app "%s" in appstore', [$app]));
182
+    });
183
+    $updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($eventSource, $l) {
184
+        $eventSource->send('success', (string)$l->t('Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)', [$app]));
185
+    });
186
+    $updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($eventSource, $l) {
187
+        $eventSource->send('success', (string)$l->t('Checked database schema update for apps'));
188
+    });
189
+    $updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($eventSource, $l) {
190
+        $eventSource->send('success', (string)$l->t('Updated "%1$s" to %2$s', array($app, $version)));
191
+    });
192
+    $updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use (&$incompatibleApps) {
193
+        $incompatibleApps[]= $app;
194
+    });
195
+    $updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource, $config) {
196
+        $eventSource->send('failure', $message);
197
+        $eventSource->close();
198
+        $config->setSystemValue('maintenance', false);
199
+    });
200
+    $updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
201
+        $eventSource->send('success', (string)$l->t('Set log level to debug'));
202
+    });
203
+    $updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
204
+        $eventSource->send('success', (string)$l->t('Reset log level'));
205
+    });
206
+    $updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($eventSource, $l) {
207
+        $eventSource->send('success', (string)$l->t('Starting code integrity check'));
208
+    });
209
+    $updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($eventSource, $l) {
210
+        $eventSource->send('success', (string)$l->t('Finished code integrity check'));
211
+    });
212
+
213
+    try {
214
+        $updater->upgrade();
215
+    } catch (\Exception $e) {
216
+        \OC::$server->getLogger()->logException($e, [
217
+            'level' => ILogger::ERROR,
218
+            'app' => 'update',
219
+        ]);
220
+        $eventSource->send('failure', get_class($e) . ': ' . $e->getMessage());
221
+        $eventSource->close();
222
+        exit();
223
+    }
224
+
225
+    $disabledApps = [];
226
+    foreach ($incompatibleApps as $app) {
227
+        $disabledApps[$app] = (string) $l->t('%s (incompatible)', [$app]);
228
+    }
229
+
230
+    if (!empty($disabledApps)) {
231
+        $eventSource->send('notice',
232
+            (string)$l->t('Following apps have been disabled: %s', [implode(', ', $disabledApps)]));
233
+    }
234 234
 } else {
235
-	$eventSource->send('notice', (string)$l->t('Already up to date'));
235
+    $eventSource->send('notice', (string)$l->t('Already up to date'));
236 236
 }
237 237
 
238 238
 $eventSource->send('done', '');
Please login to merge, or discard this patch.
Spacing   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -44,7 +44,7 @@  discard block
 block discarded – undo
44 44
 // need to send an initial message to force-init the event source,
45 45
 // which will then trigger its own CSRF check and produces its own CSRF error
46 46
 // message
47
-$eventSource->send('success', (string)$l->t('Preparing update'));
47
+$eventSource->send('success', (string) $l->t('Preparing update'));
48 48
 
49 49
 class FeedBackHandler {
50 50
 	/** @var integer */
@@ -80,21 +80,21 @@  discard block
 block discarded – undo
80 80
 				if (empty($desc)) {
81 81
 					$desc = $this->currentStep;
82 82
 				}
83
-				$this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $desc]));
83
+				$this->eventSource->send('success', (string) $this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $desc]));
84 84
 				break;
85 85
 			case '\OC\Repair::finishProgress':
86 86
 				$this->progressStateMax = $this->progressStateStep;
87
-				$this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $this->currentStep]));
87
+				$this->eventSource->send('success', (string) $this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $this->currentStep]));
88 88
 				break;
89 89
 			case '\OC\Repair::step':
90 90
 				break;
91 91
 			case '\OC\Repair::info':
92 92
 				break;
93 93
 			case '\OC\Repair::warning':
94
-				$this->eventSource->send('notice', (string)$this->l10n->t('Repair warning: ') . $event->getArgument(0));
94
+				$this->eventSource->send('notice', (string) $this->l10n->t('Repair warning: ').$event->getArgument(0));
95 95
 				break;
96 96
 			case '\OC\Repair::error':
97
-				$this->eventSource->send('notice', (string)$this->l10n->t('Repair error: ') . $event->getArgument(0));
97
+				$this->eventSource->send('notice', (string) $this->l10n->t('Repair error: ').$event->getArgument(0));
98 98
 				break;
99 99
 		}
100 100
 	}
@@ -104,7 +104,7 @@  discard block
 block discarded – undo
104 104
 
105 105
 	$config = \OC::$server->getSystemConfig();
106 106
 	if ($config->getValue('upgrade.disable-web', false)) {
107
-		$eventSource->send('failure', (string)$l->t('Please use the command line updater because automatic updating is disabled in the config.php.'));
107
+		$eventSource->send('failure', (string) $l->t('Please use the command line updater because automatic updating is disabled in the config.php.'));
108 108
 		$eventSource->close();
109 109
 		exit();
110 110
 	}
@@ -127,12 +127,12 @@  discard block
 block discarded – undo
127 127
 	$dispatcher = \OC::$server->getEventDispatcher();
128 128
 	$dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($eventSource, $l) {
129 129
 		if ($event instanceof GenericEvent) {
130
-			$eventSource->send('success', (string)$l->t('[%d / %d]: %s', [$event[0], $event[1], $event->getSubject()]));
130
+			$eventSource->send('success', (string) $l->t('[%d / %d]: %s', [$event[0], $event[1], $event->getSubject()]));
131 131
 		}
132 132
 	});
133 133
 	$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($eventSource, $l) {
134 134
 		if ($event instanceof GenericEvent) {
135
-			$eventSource->send('success', (string)$l->t('[%d / %d]: Checking table %s', [$event[0], $event[1], $event->getSubject()]));
135
+			$eventSource->send('success', (string) $l->t('[%d / %d]: Checking table %s', [$event[0], $event[1], $event->getSubject()]));
136 136
 		}
137 137
 	});
138 138
 	$feedBack = new FeedBackHandler($eventSource, $l);
@@ -144,70 +144,70 @@  discard block
 block discarded – undo
144 144
 	$dispatcher->addListener('\OC\Repair::warning', [$feedBack, 'handleRepairFeedback']);
145 145
 	$dispatcher->addListener('\OC\Repair::error', [$feedBack, 'handleRepairFeedback']);
146 146
 
147
-	$updater->listen('\OC\Updater', 'maintenanceEnabled', function () use ($eventSource, $l) {
148
-		$eventSource->send('success', (string)$l->t('Turned on maintenance mode'));
147
+	$updater->listen('\OC\Updater', 'maintenanceEnabled', function() use ($eventSource, $l) {
148
+		$eventSource->send('success', (string) $l->t('Turned on maintenance mode'));
149 149
 	});
150
-	$updater->listen('\OC\Updater', 'maintenanceDisabled', function () use ($eventSource, $l) {
151
-		$eventSource->send('success', (string)$l->t('Turned off maintenance mode'));
150
+	$updater->listen('\OC\Updater', 'maintenanceDisabled', function() use ($eventSource, $l) {
151
+		$eventSource->send('success', (string) $l->t('Turned off maintenance mode'));
152 152
 	});
153
-	$updater->listen('\OC\Updater', 'maintenanceActive', function () use ($eventSource, $l) {
154
-		$eventSource->send('success', (string)$l->t('Maintenance mode is kept active'));
153
+	$updater->listen('\OC\Updater', 'maintenanceActive', function() use ($eventSource, $l) {
154
+		$eventSource->send('success', (string) $l->t('Maintenance mode is kept active'));
155 155
 	});
156
-	$updater->listen('\OC\Updater', 'waitForCronToFinish', function () use ($eventSource, $l) {
157
-		$eventSource->send('success', (string)$l->t('Waiting for cron to finish (checks again in 5 seconds) …'));
156
+	$updater->listen('\OC\Updater', 'waitForCronToFinish', function() use ($eventSource, $l) {
157
+		$eventSource->send('success', (string) $l->t('Waiting for cron to finish (checks again in 5 seconds) …'));
158 158
 	});
159
-	$updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($eventSource, $l) {
160
-		$eventSource->send('success', (string)$l->t('Updating database schema'));
159
+	$updater->listen('\OC\Updater', 'dbUpgradeBefore', function() use($eventSource, $l) {
160
+		$eventSource->send('success', (string) $l->t('Updating database schema'));
161 161
 	});
162
-	$updater->listen('\OC\Updater', 'dbUpgrade', function () use ($eventSource, $l) {
163
-		$eventSource->send('success', (string)$l->t('Updated database'));
162
+	$updater->listen('\OC\Updater', 'dbUpgrade', function() use ($eventSource, $l) {
163
+		$eventSource->send('success', (string) $l->t('Updated database'));
164 164
 	});
165
-	$updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($eventSource, $l) {
166
-		$eventSource->send('success', (string)$l->t('Checking whether the database schema can be updated (this can take a long time depending on the database size)'));
165
+	$updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function() use($eventSource, $l) {
166
+		$eventSource->send('success', (string) $l->t('Checking whether the database schema can be updated (this can take a long time depending on the database size)'));
167 167
 	});
168
-	$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use ($eventSource, $l) {
169
-		$eventSource->send('success', (string)$l->t('Checked database schema update'));
168
+	$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function() use ($eventSource, $l) {
169
+		$eventSource->send('success', (string) $l->t('Checked database schema update'));
170 170
 	});
171
-	$updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($eventSource, $l) {
172
-		$eventSource->send('success', (string)$l->t('Checking updates of apps'));
171
+	$updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function() use ($eventSource, $l) {
172
+		$eventSource->send('success', (string) $l->t('Checking updates of apps'));
173 173
 	});
174
-	$updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use ($eventSource, $l) {
175
-		$eventSource->send('success', (string)$l->t('Checking for update of app "%s" in appstore', [$app]));
174
+	$updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function($app) use ($eventSource, $l) {
175
+		$eventSource->send('success', (string) $l->t('Checking for update of app "%s" in appstore', [$app]));
176 176
 	});
177
-	$updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use ($eventSource, $l) {
178
-		$eventSource->send('success', (string)$l->t('Update app "%s" from appstore', [$app]));
177
+	$updater->listen('\OC\Updater', 'upgradeAppStoreApp', function($app) use ($eventSource, $l) {
178
+		$eventSource->send('success', (string) $l->t('Update app "%s" from appstore', [$app]));
179 179
 	});
180
-	$updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use ($eventSource, $l) {
181
-		$eventSource->send('success', (string)$l->t('Checked for update of app "%s" in appstore', [$app]));
180
+	$updater->listen('\OC\Updater', 'checkAppStoreApp', function($app) use ($eventSource, $l) {
181
+		$eventSource->send('success', (string) $l->t('Checked for update of app "%s" in appstore', [$app]));
182 182
 	});
183
-	$updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($eventSource, $l) {
184
-		$eventSource->send('success', (string)$l->t('Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)', [$app]));
183
+	$updater->listen('\OC\Updater', 'appSimulateUpdate', function($app) use ($eventSource, $l) {
184
+		$eventSource->send('success', (string) $l->t('Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)', [$app]));
185 185
 	});
186
-	$updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($eventSource, $l) {
187
-		$eventSource->send('success', (string)$l->t('Checked database schema update for apps'));
186
+	$updater->listen('\OC\Updater', 'appUpgradeCheck', function() use ($eventSource, $l) {
187
+		$eventSource->send('success', (string) $l->t('Checked database schema update for apps'));
188 188
 	});
189
-	$updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($eventSource, $l) {
190
-		$eventSource->send('success', (string)$l->t('Updated "%1$s" to %2$s', array($app, $version)));
189
+	$updater->listen('\OC\Updater', 'appUpgrade', function($app, $version) use ($eventSource, $l) {
190
+		$eventSource->send('success', (string) $l->t('Updated "%1$s" to %2$s', array($app, $version)));
191 191
 	});
192
-	$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use (&$incompatibleApps) {
193
-		$incompatibleApps[]= $app;
192
+	$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function($app) use (&$incompatibleApps) {
193
+		$incompatibleApps[] = $app;
194 194
 	});
195
-	$updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource, $config) {
195
+	$updater->listen('\OC\Updater', 'failure', function($message) use ($eventSource, $config) {
196 196
 		$eventSource->send('failure', $message);
197 197
 		$eventSource->close();
198 198
 		$config->setSystemValue('maintenance', false);
199 199
 	});
200
-	$updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
201
-		$eventSource->send('success', (string)$l->t('Set log level to debug'));
200
+	$updater->listen('\OC\Updater', 'setDebugLogLevel', function($logLevel, $logLevelName) use($eventSource, $l) {
201
+		$eventSource->send('success', (string) $l->t('Set log level to debug'));
202 202
 	});
203
-	$updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
204
-		$eventSource->send('success', (string)$l->t('Reset log level'));
203
+	$updater->listen('\OC\Updater', 'resetLogLevel', function($logLevel, $logLevelName) use($eventSource, $l) {
204
+		$eventSource->send('success', (string) $l->t('Reset log level'));
205 205
 	});
206
-	$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($eventSource, $l) {
207
-		$eventSource->send('success', (string)$l->t('Starting code integrity check'));
206
+	$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function() use($eventSource, $l) {
207
+		$eventSource->send('success', (string) $l->t('Starting code integrity check'));
208 208
 	});
209
-	$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($eventSource, $l) {
210
-		$eventSource->send('success', (string)$l->t('Finished code integrity check'));
209
+	$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function() use($eventSource, $l) {
210
+		$eventSource->send('success', (string) $l->t('Finished code integrity check'));
211 211
 	});
212 212
 
213 213
 	try {
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
 			'level' => ILogger::ERROR,
218 218
 			'app' => 'update',
219 219
 		]);
220
-		$eventSource->send('failure', get_class($e) . ': ' . $e->getMessage());
220
+		$eventSource->send('failure', get_class($e).': '.$e->getMessage());
221 221
 		$eventSource->close();
222 222
 		exit();
223 223
 	}
@@ -229,10 +229,10 @@  discard block
 block discarded – undo
229 229
 
230 230
 	if (!empty($disabledApps)) {
231 231
 		$eventSource->send('notice',
232
-			(string)$l->t('Following apps have been disabled: %s', [implode(', ', $disabledApps)]));
232
+			(string) $l->t('Following apps have been disabled: %s', [implode(', ', $disabledApps)]));
233 233
 	}
234 234
 } else {
235
-	$eventSource->send('notice', (string)$l->t('Already up to date'));
235
+	$eventSource->send('notice', (string) $l->t('Already up to date'));
236 236
 }
237 237
 
238 238
 $eventSource->send('done', '');
Please login to merge, or discard this patch.
core/templates/loginflow/authpicker.php 2 patches
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -31,9 +31,9 @@
 block discarded – undo
31 31
 	<h2><?php p($l->t('Connect to your account')) ?></h2>
32 32
 	<p class="info">
33 33
 		<?php print_unescaped($l->t('Please log in before granting %1$s access to your %2$s account.', [
34
-								'<strong>' . \OCP\Util::sanitizeHTML($_['client']) . '</strong>',
35
-								\OCP\Util::sanitizeHTML($_['instanceName'])
36
-							])) ?>
34
+                                '<strong>' . \OCP\Util::sanitizeHTML($_['client']) . '</strong>',
35
+                                \OCP\Util::sanitizeHTML($_['instanceName'])
36
+                            ])) ?>
37 37
 	</p>
38 38
 
39 39
 	<br/>
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -31,7 +31,7 @@  discard block
 block discarded – undo
31 31
 	<h2><?php p($l->t('Connect to your account')) ?></h2>
32 32
 	<p class="info">
33 33
 		<?php print_unescaped($l->t('Please log in before granting %1$s access to your %2$s account.', [
34
-								'<strong>' . \OCP\Util::sanitizeHTML($_['client']) . '</strong>',
34
+								'<strong>'.\OCP\Util::sanitizeHTML($_['client']).'</strong>',
35 35
 								\OCP\Util::sanitizeHTML($_['instanceName'])
36 36
 							])) ?>
37 37
 	</p>
@@ -58,6 +58,6 @@  discard block
 block discarded – undo
58 58
 	</fieldset>
59 59
 </div>
60 60
 
61
-<?php if(empty($_['oauthState'])): ?>
61
+<?php if (empty($_['oauthState'])): ?>
62 62
 <a id="app-token-login" class="warning" href="#"><?php p($l->t('Alternative log in using app token')) ?></a>
63 63
 <?php endif; ?>
Please login to merge, or discard this patch.
core/templates/loginflow/grant.php 2 patches
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -31,9 +31,9 @@
 block discarded – undo
31 31
 	<h2><?php p($l->t('Account access')) ?></h2>
32 32
 	<p class="info">
33 33
 		<?php print_unescaped($l->t('You are about to grant %1$s access to your %2$s account.', [
34
-								'<strong>' . \OCP\Util::sanitizeHTML($_['client']) . '</strong>',
35
-								\OCP\Util::sanitizeHTML($_['instanceName'])
36
-							])) ?>
34
+                                '<strong>' . \OCP\Util::sanitizeHTML($_['client']) . '</strong>',
35
+                                \OCP\Util::sanitizeHTML($_['instanceName'])
36
+                            ])) ?>
37 37
 	</p>
38 38
 
39 39
 	<br/>
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -31,7 +31,7 @@
 block discarded – undo
31 31
 	<h2><?php p($l->t('Account access')) ?></h2>
32 32
 	<p class="info">
33 33
 		<?php print_unescaped($l->t('You are about to grant %1$s access to your %2$s account.', [
34
-								'<strong>' . \OCP\Util::sanitizeHTML($_['client']) . '</strong>',
34
+								'<strong>'.\OCP\Util::sanitizeHTML($_['client']).'</strong>',
35 35
 								\OCP\Util::sanitizeHTML($_['instanceName'])
36 36
 							])) ?>
37 37
 	</p>
Please login to merge, or discard this patch.
core/templates/update.admin.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -4,7 +4,7 @@
 block discarded – undo
4 4
 		<h2 class="title"><?php p($l->t('App update required')); ?></h2>
5 5
 		<?php } else { ?>
6 6
 		<h2 class="title"><?php p($l->t('%1$s will be updated to version %2$s',
7
-			array($_['productName'], $_['version']))); ?></h2>
7
+            array($_['productName'], $_['version']))); ?></h2>
8 8
 		<?php } ?>
9 9
 		<?php if (!empty($_['appsToUpgrade'])) { ?>
10 10
 		<div class="infogroup">
Please login to merge, or discard this patch.
core/templates/untrustedDomain.php 1 patch
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -8,6 +8,6 @@
 block discarded – undo
8 8
 	</p>
9 9
 	<br />
10 10
 	<p>
11
-		<?php print_unescaped($l->t('Further information how to configure this can be found in the %1$sdocumentation%2$s.', ['<a href="' . $_['docUrl'] . '" target="blank">', '</a>'])); ?>
11
+		<?php print_unescaped($l->t('Further information how to configure this can be found in the %1$sdocumentation%2$s.', ['<a href="'.$_['docUrl'].'" target="blank">', '</a>'])); ?>
12 12
 	</p>
13 13
 </div>
Please login to merge, or discard this patch.
settings/templates/settings/admin/overview.php 1 patch
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -28,39 +28,39 @@
 block discarded – undo
28 28
 ?>
29 29
 
30 30
 <div id="security-warning" class="section">
31
-	<h2><?php p($l->t('Security & setup warnings'));?></h2>
32
-	<p class="settings-hint"><?php p($l->t('It\'s important for the security and performance of your instance that everything is configured correctly. To help you with that we are doing some automatic checks. Please see the linked documentation for more information.'));?></p>
31
+	<h2><?php p($l->t('Security & setup warnings')); ?></h2>
32
+	<p class="settings-hint"><?php p($l->t('It\'s important for the security and performance of your instance that everything is configured correctly. To help you with that we are doing some automatic checks. Please see the linked documentation for more information.')); ?></p>
33 33
 
34 34
 	<div id="security-warning-state-ok" class="hidden">
35
-		<span class="icon icon-checkmark-white"></span><span class="message"><?php p($l->t('All checks passed.'));?></span>
35
+		<span class="icon icon-checkmark-white"></span><span class="message"><?php p($l->t('All checks passed.')); ?></span>
36 36
 	</div>
37 37
 	<div id="security-warning-state-failure" class="hidden">
38
-		<span class="icon icon-close-white"></span><span class="message"><?php p($l->t('There are some errors regarding your setup.'));?></span>
38
+		<span class="icon icon-close-white"></span><span class="message"><?php p($l->t('There are some errors regarding your setup.')); ?></span>
39 39
 	</div>
40 40
 	<div id="security-warning-state-warning" class="hidden">
41
-		<span class="icon icon-error-white"></span><span class="message"><?php p($l->t('There are some warnings regarding your setup.'));?></span>
41
+		<span class="icon icon-error-white"></span><span class="message"><?php p($l->t('There are some warnings regarding your setup.')); ?></span>
42 42
 	</div>
43 43
 	<div id="security-warning-state-loading">
44
-		<span class="icon loading"></span><span class="message"><?php p($l->t('Checking for system and security issues.'));?></span>
44
+		<span class="icon loading"></span><span class="message"><?php p($l->t('Checking for system and security issues.')); ?></span>
45 45
 	</div>
46 46
 
47
-	<div id="postsetupchecks" data-check-wellknown="<?php if($_['checkForWorkingWellKnownSetup']) { p('true'); } else { p('false'); } ?>">
47
+	<div id="postsetupchecks" data-check-wellknown="<?php if ($_['checkForWorkingWellKnownSetup']) { p('true'); } else { p('false'); } ?>">
48 48
 		<ul class="errors hidden"></ul>
49 49
 		<ul class="warnings hidden"></ul>
50 50
 		<ul class="info hidden"></ul>
51 51
 	</div>
52 52
 	<p id="postsetupchecks-hint" class="hidden">
53
-		<?php print_unescaped($l->t('Please double check the <a target="_blank" rel="noreferrer noopener" href="%1$s">installation guides ↗</a>, and check for any errors or warnings in the <a href="%2$s">log</a>.', [link_to_docs('admin-install'), \OC::$server->getURLGenerator()->linkToRoute('settings.AdminSettings.index', ['section' => 'logging'])] )); ?>
53
+		<?php print_unescaped($l->t('Please double check the <a target="_blank" rel="noreferrer noopener" href="%1$s">installation guides ↗</a>, and check for any errors or warnings in the <a href="%2$s">log</a>.', [link_to_docs('admin-install'), \OC::$server->getURLGenerator()->linkToRoute('settings.AdminSettings.index', ['section' => 'logging'])])); ?>
54 54
 	</p>
55 55
 
56 56
 	<p class="extra-top-margin">
57
-		<?php print_unescaped($l->t('Check the security of your Nextcloud over <a target="_blank" rel="noreferrer noopener" href="%s">our security scan ↗</a>.', ['https://scan.nextcloud.com']));?>
57
+		<?php print_unescaped($l->t('Check the security of your Nextcloud over <a target="_blank" rel="noreferrer noopener" href="%s">our security scan ↗</a>.', ['https://scan.nextcloud.com'])); ?>
58 58
 	</p>
59 59
 
60 60
 </div>
61 61
 
62 62
 <div id="version" class="section">
63 63
 	<!-- should be the last part, so Updater can follow if enabled (it has no heading therefore). -->
64
-	<h2><?php p($l->t('Version'));?></h2>
64
+	<h2><?php p($l->t('Version')); ?></h2>
65 65
 	<p><strong><a href="<?php print_unescaped($theme->getBaseUrl()); ?>" rel="noreferrer noopener" target="_blank"><?php p($theme->getTitle()); ?></a> <?php p(OC_Util::getHumanVersion()) ?></strong></p>
66 66
 </div>
Please login to merge, or discard this patch.
settings/templates/settings/personal/personal.info.php 3 patches
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -26,10 +26,10 @@  discard block
 block discarded – undo
26 26
 /** @var array $_ */
27 27
 
28 28
 script('settings', [
29
-	'usersettings',
30
-	'federationsettingsview',
31
-	'federationscopemenu',
32
-	'settings/personalInfo',
29
+    'usersettings',
30
+    'federationsettingsview',
31
+    'federationscopemenu',
32
+    'settings/personalInfo',
33 33
 ]);
34 34
 vendor_script('jcrop/js/jquery.Jcrop');
35 35
 vendor_style('jcrop/css/jquery.Jcrop');
@@ -87,10 +87,10 @@  discard block
 block discarded – undo
87 87
 					<p class="quotatext">
88 88
 						<?php if ($_['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED): ?>
89 89
 							<?php print_unescaped($l->t('You are using <strong>%s</strong>',
90
-								[$_['usage']]));?>
90
+                                [$_['usage']]));?>
91 91
 						<?php else: ?>
92 92
 							<?php print_unescaped($l->t('You are using <strong>%1$s</strong> of <strong>%2$s</strong> (<strong>%3$s %%</strong>)',
93
-								[$_['usage'], $_['total_space'],  $_['usage_relative']]));?>
93
+                                [$_['usage'], $_['total_space'],  $_['usage_relative']]));?>
94 94
 						<?php endif ?>
95 95
 					</p>
96 96
 				</div>
@@ -137,17 +137,17 @@  discard block
 block discarded – undo
137 137
 				<div class="verify <?php if ($_['email'] === ''  || $_['emailScope'] !== 'public') p('hidden'); ?>">
138 138
 					<img id="verify-email" title="<?php p($_['emailMessage']); ?>" data-status="<?php p($_['emailVerification']) ?>" src="
139 139
 				<?php
140
-					switch($_['emailVerification']) {
141
-						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
142
-							p(image_path('core', 'actions/verifying.svg'));
143
-							break;
144
-						case \OC\Accounts\AccountManager::VERIFIED:
145
-							p(image_path('core', 'actions/verified.svg'));
146
-							break;
147
-						default:
148
-							p(image_path('core', 'actions/verify.svg'));
149
-					}
150
-					?>">
140
+                    switch($_['emailVerification']) {
141
+                        case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
142
+                            p(image_path('core', 'actions/verifying.svg'));
143
+                            break;
144
+                        case \OC\Accounts\AccountManager::VERIFIED:
145
+                            p(image_path('core', 'actions/verified.svg'));
146
+                            break;
147
+                        default:
148
+                            p(image_path('core', 'actions/verify.svg'));
149
+                    }
150
+                    ?>">
151 151
 				</div>
152 152
 				<input type="email" name="email" id="email" value="<?php p($_['email']); ?>"
153 153
 					<?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
@@ -225,17 +225,17 @@  discard block
 block discarded – undo
225 225
 				<div class="verify <?php if ($_['website'] === ''  || $_['websiteScope'] !== 'public') p('hidden'); ?>">
226 226
 					<img id="verify-website" title="<?php p($_['websiteMessage']); ?>" data-status="<?php p($_['websiteVerification']) ?>" src="
227 227
 					<?php
228
-					switch($_['websiteVerification']) {
229
-						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
230
-							p(image_path('core', 'actions/verifying.svg'));
231
-							break;
232
-						case \OC\Accounts\AccountManager::VERIFIED:
233
-							p(image_path('core', 'actions/verified.svg'));
234
-							break;
235
-						default:
236
-							p(image_path('core', 'actions/verify.svg'));
237
-					}
238
-					?>"
228
+                    switch($_['websiteVerification']) {
229
+                        case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
230
+                            p(image_path('core', 'actions/verifying.svg'));
231
+                            break;
232
+                        case \OC\Accounts\AccountManager::VERIFIED:
233
+                            p(image_path('core', 'actions/verified.svg'));
234
+                            break;
235
+                        default:
236
+                            p(image_path('core', 'actions/verify.svg'));
237
+                    }
238
+                    ?>"
239 239
 					<?php if($_['websiteVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['websiteVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
240 240
 					>
241 241
 					<div class="verification-dialog popovermenu bubble menu">
@@ -274,17 +274,17 @@  discard block
 block discarded – undo
274 274
 				<div class="verify <?php if ($_['twitter'] === ''  || $_['twitterScope'] !== 'public') p('hidden'); ?>">
275 275
 					<img id="verify-twitter" title="<?php p($_['twitterMessage']); ?>" data-status="<?php p($_['twitterVerification']) ?>" src="
276 276
 					<?php
277
-					switch($_['twitterVerification']) {
278
-						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
279
-							p(image_path('core', 'actions/verifying.svg'));
280
-							break;
281
-						case \OC\Accounts\AccountManager::VERIFIED:
282
-							p(image_path('core', 'actions/verified.svg'));
283
-							break;
284
-						default:
285
-							p(image_path('core', 'actions/verify.svg'));
286
-					}
287
-					?>"
277
+                    switch($_['twitterVerification']) {
278
+                        case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
279
+                            p(image_path('core', 'actions/verifying.svg'));
280
+                            break;
281
+                        case \OC\Accounts\AccountManager::VERIFIED:
282
+                            p(image_path('core', 'actions/verified.svg'));
283
+                            break;
284
+                        default:
285
+                            p(image_path('core', 'actions/verify.svg'));
286
+                    }
287
+                    ?>"
288 288
 					<?php if($_['twitterVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['twitterVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
289 289
 					>
290 290
 					<div class="verification-dialog popovermenu bubble menu">
Please login to merge, or discard this patch.
Spacing   +60 added lines, -60 removed lines patch added patch discarded remove patch
@@ -69,7 +69,7 @@  discard block
 block discarded – undo
69 69
 					</div>
70 70
 				</div>
71 71
 				<span class="icon-checkmark hidden"></span>
72
-				<?php if($_['lookupServerUploadEnabled']) { ?>
72
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
73 73
 				<input type="hidden" id="avatarscope" value="<?php p($_['avatarScope']) ?>">
74 74
 				<?php } ?>
75 75
 			</form>
@@ -87,14 +87,14 @@  discard block
 block discarded – undo
87 87
 					<p class="quotatext">
88 88
 						<?php if ($_['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED): ?>
89 89
 							<?php print_unescaped($l->t('You are using <strong>%s</strong>',
90
-								[$_['usage']]));?>
90
+								[$_['usage']])); ?>
91 91
 						<?php else: ?>
92 92
 							<?php print_unescaped($l->t('You are using <strong>%1$s</strong> of <strong>%2$s</strong> (<strong>%3$s %%</strong>)',
93
-								[$_['usage'], $_['total_space'],  $_['usage_relative']]));?>
93
+								[$_['usage'], $_['total_space'], $_['usage_relative']])); ?>
94 94
 						<?php endif ?>
95 95
 					</p>
96 96
 				</div>
97
-				<progress value="<?php p($_['usage_relative']); ?>" max="100"<?php if($_['usage_relative'] > 80): ?> class="warn" <?php endif; ?>></progress>
97
+				<progress value="<?php p($_['usage_relative']); ?>" max="100"<?php if ($_['usage_relative'] > 80): ?> class="warn" <?php endif; ?>></progress>
98 98
 			</div>
99 99
 		</div>
100 100
 	</div>
@@ -111,15 +111,15 @@  discard block
 block discarded – undo
111 111
 					</div>
112 112
 				</h3>
113 113
 				<input type="text" id="displayname" name="displayname"
114
-					<?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
114
+					<?php if (!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
115 115
 					   value="<?php p($_['displayName']) ?>"
116 116
 					   autocomplete="on" autocapitalize="none" autocorrect="off" />
117
-				<?php if(!$_['displayNameChangeSupported']) { ?>
118
-					<span><?php if(isset($_['displayName']) && !empty($_['displayName'])) { p($_['displayName']); } else { p($l->t('No display name set')); } ?></span>
117
+				<?php if (!$_['displayNameChangeSupported']) { ?>
118
+					<span><?php if (isset($_['displayName']) && !empty($_['displayName'])) { p($_['displayName']); } else { p($l->t('No display name set')); } ?></span>
119 119
 				<?php } ?>
120 120
 				<span class="icon-checkmark hidden"></span>
121 121
 				<span class="icon-error hidden" ></span>
122
-				<?php if($_['lookupServerUploadEnabled']) { ?>
122
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
123 123
 					<input type="hidden" id="displaynamescope" value="<?php p($_['displayNameScope']) ?>">
124 124
 				<?php } ?>
125 125
 			</form>
@@ -134,10 +134,10 @@  discard block
 block discarded – undo
134 134
 						</span>
135 135
 					</div>
136 136
 				</h3>
137
-				<div class="verify <?php if ($_['email'] === ''  || $_['emailScope'] !== 'public') p('hidden'); ?>">
137
+				<div class="verify <?php if ($_['email'] === '' || $_['emailScope'] !== 'public') p('hidden'); ?>">
138 138
 					<img id="verify-email" title="<?php p($_['emailMessage']); ?>" data-status="<?php p($_['emailVerification']) ?>" src="
139 139
 				<?php
140
-					switch($_['emailVerification']) {
140
+					switch ($_['emailVerification']) {
141 141
 						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
142 142
 							p(image_path('core', 'actions/verifying.svg'));
143 143
 							break;
@@ -150,18 +150,18 @@  discard block
 block discarded – undo
150 150
 					?>">
151 151
 				</div>
152 152
 				<input type="email" name="email" id="email" value="<?php p($_['email']); ?>"
153
-					<?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
153
+					<?php if (!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?>
154 154
 					   placeholder="<?php p($l->t('Your email address')); ?>"
155 155
 					   autocomplete="on" autocapitalize="none" autocorrect="off" />
156 156
 			   	<span class="icon-checkmark hidden"></span>
157 157
 				<span class="icon-error hidden" ></span>
158
-				<?php if(!$_['displayNameChangeSupported']) { ?>
159
-					<span><?php if(isset($_['email']) && !empty($_['email'])) { p($_['email']); } else { p($l->t('No email address set')); }?></span>
158
+				<?php if (!$_['displayNameChangeSupported']) { ?>
159
+					<span><?php if (isset($_['email']) && !empty($_['email'])) { p($_['email']); } else { p($l->t('No email address set')); }?></span>
160 160
 				<?php } ?>
161
-				<?php if($_['displayNameChangeSupported']) { ?>
161
+				<?php if ($_['displayNameChangeSupported']) { ?>
162 162
 					<em><?php p($l->t('For password reset and notifications')); ?></em>
163 163
 				<?php } ?>
164
-				<?php if($_['lookupServerUploadEnabled']) { ?>
164
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
165 165
 					<input type="hidden" id="emailscope" value="<?php p($_['emailScope']) ?>">
166 166
 				<?php } ?>
167 167
 			</form>
@@ -177,12 +177,12 @@  discard block
 block discarded – undo
177 177
 						</span>
178 178
 					</div>
179 179
 				</h3>
180
-				<input type="tel" id="phone" name="phone" <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
180
+				<input type="tel" id="phone" name="phone" <?php if (!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
181 181
 					   value="<?php p($_['phone']) ?>"
182 182
 					   placeholder="<?php p($l->t('Your phone number')); ?>"
183 183
 				       autocomplete="on" autocapitalize="none" autocorrect="off" />
184 184
 				<span class="icon-checkmark hidden"></span>
185
-				<?php if($_['lookupServerUploadEnabled']) { ?>
185
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
186 186
 				<input type="hidden" id="phonescope" value="<?php p($_['phoneScope']) ?>">
187 187
 				<?php } ?>
188 188
 			</form>
@@ -199,12 +199,12 @@  discard block
 block discarded – undo
199 199
 						</span>
200 200
 					</div>
201 201
 				</h3>
202
-				<input type="text" id="address" name="address" <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"');  ?>
202
+				<input type="text" id="address" name="address" <?php if (!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
203 203
 					   placeholder="<?php p($l->t('Your postal address')); ?>"
204 204
 					   value="<?php p($_['address']) ?>"
205 205
 					   autocomplete="on" autocapitalize="none" autocorrect="off" />
206 206
 				<span class="icon-checkmark hidden"></span>
207
-				<?php if($_['lookupServerUploadEnabled']) { ?>
207
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
208 208
 				<input type="hidden" id="addressscope" value="<?php p($_['addressScope']) ?>">
209 209
 				<?php } ?>
210 210
 			</form>
@@ -221,11 +221,11 @@  discard block
 block discarded – undo
221 221
 						</span>
222 222
 					</div>
223 223
 				</h3>
224
-				<?php if($_['lookupServerUploadEnabled']) { ?>
225
-				<div class="verify <?php if ($_['website'] === ''  || $_['websiteScope'] !== 'public') p('hidden'); ?>">
224
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
225
+				<div class="verify <?php if ($_['website'] === '' || $_['websiteScope'] !== 'public') p('hidden'); ?>">
226 226
 					<img id="verify-website" title="<?php p($_['websiteMessage']); ?>" data-status="<?php p($_['websiteVerification']) ?>" src="
227 227
 					<?php
228
-					switch($_['websiteVerification']) {
228
+					switch ($_['websiteVerification']) {
229 229
 						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
230 230
 							p(image_path('core', 'actions/verifying.svg'));
231 231
 							break;
@@ -236,13 +236,13 @@  discard block
 block discarded – undo
236 236
 							p(image_path('core', 'actions/verify.svg'));
237 237
 					}
238 238
 					?>"
239
-					<?php if($_['websiteVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['websiteVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
239
+					<?php if ($_['websiteVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['websiteVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
240 240
 					>
241 241
 					<div class="verification-dialog popovermenu bubble menu">
242 242
 						<div class="verification-dialog-content">
243 243
 							<p class="explainVerification"></p>
244 244
 							<p class="verificationCode"></p>
245
-							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.'));?></p>
245
+							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.')); ?></p>
246 246
 						</div>
247 247
 					</div>
248 248
 				</div>
@@ -250,10 +250,10 @@  discard block
 block discarded – undo
250 250
 				<input type="url" name="website" id="website" value="<?php p($_['website']); ?>"
251 251
 				       placeholder="<?php p($l->t('Link https://…')); ?>"
252 252
 				       autocomplete="on" autocapitalize="none" autocorrect="off"
253
-					   <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"');  ?>
253
+					   <?php if (!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
254 254
 				/>
255 255
 				<span class="icon-checkmark hidden"></span>
256
-				<?php if($_['lookupServerUploadEnabled']) { ?>
256
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
257 257
 				<input type="hidden" id="websitescope" value="<?php p($_['websiteScope']) ?>">
258 258
 				<?php } ?>
259 259
 			</form>
@@ -270,11 +270,11 @@  discard block
 block discarded – undo
270 270
 						</span>
271 271
 					</div>
272 272
 				</h3>
273
-				<?php if($_['lookupServerUploadEnabled']) { ?>
274
-				<div class="verify <?php if ($_['twitter'] === ''  || $_['twitterScope'] !== 'public') p('hidden'); ?>">
273
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
274
+				<div class="verify <?php if ($_['twitter'] === '' || $_['twitterScope'] !== 'public') p('hidden'); ?>">
275 275
 					<img id="verify-twitter" title="<?php p($_['twitterMessage']); ?>" data-status="<?php p($_['twitterVerification']) ?>" src="
276 276
 					<?php
277
-					switch($_['twitterVerification']) {
277
+					switch ($_['twitterVerification']) {
278 278
 						case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS:
279 279
 							p(image_path('core', 'actions/verifying.svg'));
280 280
 							break;
@@ -285,13 +285,13 @@  discard block
 block discarded – undo
285 285
 							p(image_path('core', 'actions/verify.svg'));
286 286
 					}
287 287
 					?>"
288
-					<?php if($_['twitterVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['twitterVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
288
+					<?php if ($_['twitterVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['twitterVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
289 289
 					>
290 290
 					<div class="verification-dialog popovermenu bubble menu">
291 291
 						<div class="verification-dialog-content">
292 292
 							<p class="explainVerification"></p>
293 293
 							<p class="verificationCode"></p>
294
-							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.'));?></p>
294
+							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.')); ?></p>
295 295
 						</div>
296 296
 					</div>
297 297
 				</div>
@@ -299,10 +299,10 @@  discard block
 block discarded – undo
299 299
 				<input type="text" name="twitter" id="twitter" value="<?php p($_['twitter']); ?>"
300 300
 					   placeholder="<?php p($l->t('Twitter handle @…')); ?>"
301 301
 					   autocomplete="on" autocapitalize="none" autocorrect="off"
302
-					   <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"');  ?>
302
+					   <?php if (!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
303 303
 				/>
304 304
 				<span class="icon-checkmark hidden"></span>
305
-				<?php if($_['lookupServerUploadEnabled']) { ?>
305
+				<?php if ($_['lookupServerUploadEnabled']) { ?>
306 306
 				<input type="hidden" id="twitterscope" value="<?php p($_['twitterScope']) ?>">
307 307
 				<?php } ?>
308 308
 			</form>
@@ -315,27 +315,27 @@  discard block
 block discarded – undo
315 315
 			<?php if (isset($_['activelanguage'])) { ?>
316 316
 				<form id="language" class="section">
317 317
 					<h3>
318
-						<label for="languageinput"><?php p($l->t('Language'));?></label>
318
+						<label for="languageinput"><?php p($l->t('Language')); ?></label>
319 319
 					</h3>
320
-					<select id="languageinput" name="lang" data-placeholder="<?php p($l->t('Language'));?>">
321
-						<option value="<?php p($_['activelanguage']['code']);?>">
322
-							<?php p($_['activelanguage']['name']);?>
320
+					<select id="languageinput" name="lang" data-placeholder="<?php p($l->t('Language')); ?>">
321
+						<option value="<?php p($_['activelanguage']['code']); ?>">
322
+							<?php p($_['activelanguage']['name']); ?>
323 323
 						</option>
324
-						<?php foreach($_['commonlanguages'] as $language):?>
325
-							<option value="<?php p($language['code']);?>">
326
-								<?php p($language['name']);?>
324
+						<?php foreach ($_['commonlanguages'] as $language):?>
325
+							<option value="<?php p($language['code']); ?>">
326
+								<?php p($language['name']); ?>
327 327
 							</option>
328
-						<?php endforeach;?>
328
+						<?php endforeach; ?>
329 329
 						<optgroup label="––––––––––"></optgroup>
330
-						<?php foreach($_['languages'] as $language):?>
331
-							<option value="<?php p($language['code']);?>">
332
-								<?php p($language['name']);?>
330
+						<?php foreach ($_['languages'] as $language):?>
331
+							<option value="<?php p($language['code']); ?>">
332
+								<?php p($language['name']); ?>
333 333
 							</option>
334
-						<?php endforeach;?>
334
+						<?php endforeach; ?>
335 335
 					</select>
336 336
 					<a href="https://www.transifex.com/nextcloud/nextcloud/"
337 337
 					   target="_blank" rel="noreferrer noopener">
338
-						<em><?php p($l->t('Help translate'));?></em>
338
+						<em><?php p($l->t('Help translate')); ?></em>
339 339
 					</a>
340 340
 				</form>
341 341
 			<?php } ?>
@@ -344,27 +344,27 @@  discard block
 block discarded – undo
344 344
 			<?php if (isset($_['activelocale'])) { ?>
345 345
 				<form id="locale" class="section">
346 346
 					<h3>
347
-						<label for="localeinput"><?php p($l->t('Locale'));?></label>
347
+						<label for="localeinput"><?php p($l->t('Locale')); ?></label>
348 348
 					</h3>
349
-					<select id="localeinput" name="lang" data-placeholder="<?php p($l->t('Locale'));?>">
350
-						<option value="<?php p($_['activelocale']['code']);?>">
351
-							<?php p($_['activelocale']['name']);?>
349
+					<select id="localeinput" name="lang" data-placeholder="<?php p($l->t('Locale')); ?>">
350
+						<option value="<?php p($_['activelocale']['code']); ?>">
351
+							<?php p($_['activelocale']['name']); ?>
352 352
 						</option>
353 353
 						<optgroup label="––––––––––"></optgroup>
354
-						<?php foreach($_['localesForLanguage'] as $locale):?>
355
-							<option value="<?php p($locale['code']);?>">
356
-								<?php p($locale['name']);?>
354
+						<?php foreach ($_['localesForLanguage'] as $locale):?>
355
+							<option value="<?php p($locale['code']); ?>">
356
+								<?php p($locale['name']); ?>
357 357
 							</option>
358
-						<?php endforeach;?>
358
+						<?php endforeach; ?>
359 359
 						<optgroup label="––––––––––"></optgroup>
360
-						<option value="<?php p($_['activelocale']['code']);?>">
361
-							<?php p($_['activelocale']['name']);?>
360
+						<option value="<?php p($_['activelocale']['code']); ?>">
361
+							<?php p($_['activelocale']['name']); ?>
362 362
 						</option>
363
-						<?php foreach($_['locales'] as $locale):?>
364
-							<option value="<?php p($locale['code']);?>">
365
-								<?php p($locale['name']);?>
363
+						<?php foreach ($_['locales'] as $locale):?>
364
+							<option value="<?php p($locale['code']); ?>">
365
+								<?php p($locale['name']); ?>
366 366
 							</option>
367
-						<?php endforeach;?>
367
+						<?php endforeach; ?>
368 368
 					</select>
369 369
 					<div id="localeexample" class="personal-info icon-timezone">
370 370
 						<p>
Please login to merge, or discard this patch.
Braces   +48 added lines, -15 removed lines patch added patch discarded remove patch
@@ -57,8 +57,11 @@  discard block
 block discarded – undo
57 57
 						<div class="hidden button icon-delete svg" id="removeavatar" title="<?php p($l->t('Remove image')); ?>"></div>
58 58
 						<input type="file" name="files[]" id="uploadavatar" class="hiddenuploadfield">
59 59
 						<p><em><?php p($l->t('png or jpg, max. 20 MB')); ?></em></p>
60
-					<?php else: ?>
61
-						<?php p($l->t('Picture provided by original account')); ?>
60
+					<?php else {
61
+    : ?>
62
+						<?php p($l->t('Picture provided by original account'));
63
+}
64
+?>
62 65
 					<?php endif; ?>
63 66
 				</div>
64 67
 
@@ -88,9 +91,12 @@  discard block
 block discarded – undo
88 91
 						<?php if ($_['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED): ?>
89 92
 							<?php print_unescaped($l->t('You are using <strong>%s</strong>',
90 93
 								[$_['usage']]));?>
91
-						<?php else: ?>
94
+						<?php else {
95
+    : ?>
92 96
 							<?php print_unescaped($l->t('You are using <strong>%1$s</strong> of <strong>%2$s</strong> (<strong>%3$s %%</strong>)',
93
-								[$_['usage'], $_['total_space'],  $_['usage_relative']]));?>
97
+								[$_['usage'], $_['total_space'],  $_['usage_relative']]));
98
+}
99
+?>
94 100
 						<?php endif ?>
95 101
 					</p>
96 102
 				</div>
@@ -134,7 +140,10 @@  discard block
 block discarded – undo
134 140
 						</span>
135 141
 					</div>
136 142
 				</h3>
137
-				<div class="verify <?php if ($_['email'] === ''  || $_['emailScope'] !== 'public') p('hidden'); ?>">
143
+				<div class="verify <?php if ($_['email'] === ''  || $_['emailScope'] !== 'public') {
144
+    p('hidden');
145
+}
146
+?>">
138 147
 					<img id="verify-email" title="<?php p($_['emailMessage']); ?>" data-status="<?php p($_['emailVerification']) ?>" src="
139 148
 				<?php
140 149
 					switch($_['emailVerification']) {
@@ -177,7 +186,10 @@  discard block
 block discarded – undo
177 186
 						</span>
178 187
 					</div>
179 188
 				</h3>
180
-				<input type="tel" id="phone" name="phone" <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"'); ?>
189
+				<input type="tel" id="phone" name="phone" <?php if(!$_['lookupServerUploadEnabled']) {
190
+    print_unescaped('disabled="1"');
191
+}
192
+?>
181 193
 					   value="<?php p($_['phone']) ?>"
182 194
 					   placeholder="<?php p($l->t('Your phone number')); ?>"
183 195
 				       autocomplete="on" autocapitalize="none" autocorrect="off" />
@@ -199,7 +211,10 @@  discard block
 block discarded – undo
199 211
 						</span>
200 212
 					</div>
201 213
 				</h3>
202
-				<input type="text" id="address" name="address" <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"');  ?>
214
+				<input type="text" id="address" name="address" <?php if(!$_['lookupServerUploadEnabled']) {
215
+    print_unescaped('disabled="1"');
216
+}
217
+?>
203 218
 					   placeholder="<?php p($l->t('Your postal address')); ?>"
204 219
 					   value="<?php p($_['address']) ?>"
205 220
 					   autocomplete="on" autocapitalize="none" autocorrect="off" />
@@ -222,7 +237,10 @@  discard block
 block discarded – undo
222 237
 					</div>
223 238
 				</h3>
224 239
 				<?php if($_['lookupServerUploadEnabled']) { ?>
225
-				<div class="verify <?php if ($_['website'] === ''  || $_['websiteScope'] !== 'public') p('hidden'); ?>">
240
+				<div class="verify <?php if ($_['website'] === ''  || $_['websiteScope'] !== 'public') {
241
+    p('hidden');
242
+}
243
+?>">
226 244
 					<img id="verify-website" title="<?php p($_['websiteMessage']); ?>" data-status="<?php p($_['websiteVerification']) ?>" src="
227 245
 					<?php
228 246
 					switch($_['websiteVerification']) {
@@ -236,13 +254,16 @@  discard block
 block discarded – undo
236 254
 							p(image_path('core', 'actions/verify.svg'));
237 255
 					}
238 256
 					?>"
239
-					<?php if($_['websiteVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['websiteVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
257
+					<?php if($_['websiteVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['websiteVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) {
258
+    print_unescaped(' class="verify-action"') ?>
240 259
 					>
241 260
 					<div class="verification-dialog popovermenu bubble menu">
242 261
 						<div class="verification-dialog-content">
243 262
 							<p class="explainVerification"></p>
244 263
 							<p class="verificationCode"></p>
245
-							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.'));?></p>
264
+							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.'));
265
+}
266
+?></p>
246 267
 						</div>
247 268
 					</div>
248 269
 				</div>
@@ -250,7 +271,10 @@  discard block
 block discarded – undo
250 271
 				<input type="url" name="website" id="website" value="<?php p($_['website']); ?>"
251 272
 				       placeholder="<?php p($l->t('Link https://…')); ?>"
252 273
 				       autocomplete="on" autocapitalize="none" autocorrect="off"
253
-					   <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"');  ?>
274
+					   <?php if(!$_['lookupServerUploadEnabled']) {
275
+    print_unescaped('disabled="1"');
276
+}
277
+?>
254 278
 				/>
255 279
 				<span class="icon-checkmark hidden"></span>
256 280
 				<?php if($_['lookupServerUploadEnabled']) { ?>
@@ -271,7 +295,10 @@  discard block
 block discarded – undo
271 295
 					</div>
272 296
 				</h3>
273 297
 				<?php if($_['lookupServerUploadEnabled']) { ?>
274
-				<div class="verify <?php if ($_['twitter'] === ''  || $_['twitterScope'] !== 'public') p('hidden'); ?>">
298
+				<div class="verify <?php if ($_['twitter'] === ''  || $_['twitterScope'] !== 'public') {
299
+    p('hidden');
300
+}
301
+?>">
275 302
 					<img id="verify-twitter" title="<?php p($_['twitterMessage']); ?>" data-status="<?php p($_['twitterVerification']) ?>" src="
276 303
 					<?php
277 304
 					switch($_['twitterVerification']) {
@@ -285,13 +312,16 @@  discard block
 block discarded – undo
285 312
 							p(image_path('core', 'actions/verify.svg'));
286 313
 					}
287 314
 					?>"
288
-					<?php if($_['twitterVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['twitterVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) print_unescaped(' class="verify-action"') ?>
315
+					<?php if($_['twitterVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['twitterVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) {
316
+    print_unescaped(' class="verify-action"') ?>
289 317
 					>
290 318
 					<div class="verification-dialog popovermenu bubble menu">
291 319
 						<div class="verification-dialog-content">
292 320
 							<p class="explainVerification"></p>
293 321
 							<p class="verificationCode"></p>
294
-							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.'));?></p>
322
+							<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.'));
323
+}
324
+?></p>
295 325
 						</div>
296 326
 					</div>
297 327
 				</div>
@@ -299,7 +329,10 @@  discard block
 block discarded – undo
299 329
 				<input type="text" name="twitter" id="twitter" value="<?php p($_['twitter']); ?>"
300 330
 					   placeholder="<?php p($l->t('Twitter handle @…')); ?>"
301 331
 					   autocomplete="on" autocapitalize="none" autocorrect="off"
302
-					   <?php if(!$_['lookupServerUploadEnabled']) print_unescaped('disabled="1"');  ?>
332
+					   <?php if(!$_['lookupServerUploadEnabled']) {
333
+    print_unescaped('disabled="1"');
334
+}
335
+?>
303 336
 				/>
304 337
 				<span class="icon-checkmark hidden"></span>
305 338
 				<?php if($_['lookupServerUploadEnabled']) { ?>
Please login to merge, or discard this patch.