Completed
Branch master (69e0e2)
by Johannes
12:08
created

ShareByMailProvider::getAccessList()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 17
nc 2
nop 2
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Bjoern Schiessle <[email protected]>
4
 *
5
 * @license GNU AGPL version 3 or any later version
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Affero General Public License as
9
 * published by the Free Software Foundation, either version 3 of the
10
 * License, or (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 */
21
22
namespace OCA\ShareByMail;
23
24
use OC\HintException;
25
use OC\Share20\Exception\InvalidShare;
26
use OCA\ShareByMail\Settings\SettingsManager;
27
use OCP\Activity\IManager;
28
use OCP\DB\QueryBuilder\IQueryBuilder;
29
use OCP\Files\Folder;
30
use OCP\Files\IRootFolder;
31
use OCP\Files\Node;
32
use OCP\IDBConnection;
33
use OCP\IL10N;
34
use OCP\ILogger;
35
use OCP\IURLGenerator;
36
use OCP\IUser;
37
use OCP\IUserManager;
38
use OCP\Mail\IMailer;
39
use OCP\Security\ISecureRandom;
40
use OC\Share20\Share;
41
use OCP\Share\Exceptions\ShareNotFound;
42
use OCP\Share\IShare;
43
use OCP\Share\IShareProvider;
44
use OCP\Template;
45
46
/**
47
 * Class ShareByMail
48
 *
49
 * @package OCA\ShareByMail
50
 */
51
class ShareByMailProvider implements IShareProvider {
52
53
	/** @var  IDBConnection */
54
	private $dbConnection;
55
56
	/** @var ILogger */
57
	private $logger;
58
59
	/** @var ISecureRandom */
60
	private $secureRandom;
61
62
	/** @var IUserManager */
63
	private $userManager;
64
65
	/** @var IRootFolder */
66
	private $rootFolder;
67
68
	/** @var IL10N */
69
	private $l;
70
71
	/** @var IMailer */
72
	private $mailer;
73
74
	/** @var IURLGenerator */
75
	private $urlGenerator;
76
77
	/** @var IManager  */
78
	private $activityManager;
79
80
	/** @var SettingsManager */
81
	private $settingsManager;
82
83
	/**
84
	 * Return the identifier of this provider.
85
	 *
86
	 * @return string Containing only [a-zA-Z0-9]
87
	 */
88
	public function identifier() {
89
		return 'ocMailShare';
90
	}
91
92
	/**
93
	 * DefaultShareProvider constructor.
94
	 *
95
	 * @param IDBConnection $connection
96
	 * @param ISecureRandom $secureRandom
97
	 * @param IUserManager $userManager
98
	 * @param IRootFolder $rootFolder
99
	 * @param IL10N $l
100
	 * @param ILogger $logger
101
	 * @param IMailer $mailer
102
	 * @param IURLGenerator $urlGenerator
103
	 * @param IManager $activityManager
104
	 * @param SettingsManager $settingsManager
105
	 */
106 View Code Duplication
	public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
107
		IDBConnection $connection,
108
		ISecureRandom $secureRandom,
109
		IUserManager $userManager,
110
		IRootFolder $rootFolder,
111
		IL10N $l,
112
		ILogger $logger,
113
		IMailer $mailer,
114
		IURLGenerator $urlGenerator,
115
		IManager $activityManager,
116
		SettingsManager $settingsManager
117
	) {
118
		$this->dbConnection = $connection;
119
		$this->secureRandom = $secureRandom;
120
		$this->userManager = $userManager;
121
		$this->rootFolder = $rootFolder;
122
		$this->l = $l;
123
		$this->logger = $logger;
124
		$this->mailer = $mailer;
125
		$this->urlGenerator = $urlGenerator;
126
		$this->activityManager = $activityManager;
127
		$this->settingsManager = $settingsManager;
128
	}
129
130
	/**
131
	 * Share a path
132
	 *
133
	 * @param IShare $share
134
	 * @return IShare The share object
135
	 * @throws ShareNotFound
136
	 * @throws \Exception
137
	 */
138
	public function create(IShare $share) {
139
140
		$shareWith = $share->getSharedWith();
141
		/*
142
		 * Check if file is not already shared with the remote user
143
		 */
144
		$alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0);
145 View Code Duplication
		if (!empty($alreadyShared)) {
146
			$message = 'Sharing %s failed, this item is already shared with %s';
147
			$message_t = $this->l->t('Sharing %s failed, this item is already shared with %s', array($share->getNode()->getName(), $shareWith));
148
			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
149
			throw new \Exception($message_t);
150
		}
151
152
		$shareId = $this->createMailShare($share);
153
		$this->createActivity($share);
154
		$data = $this->getRawShare($shareId);
155
		return $this->createShareObject($data);
156
157
	}
158
159
	/**
160
	 * create activity if a file/folder was shared by mail
161
	 *
162
	 * @param IShare $share
163
	 */
164
	protected function createActivity(IShare $share) {
165
166
		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
167
168
		$this->publishActivity(
169
			Activity::SUBJECT_SHARED_EMAIL_SELF,
170
			[$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
171
			$share->getSharedBy(),
172
			$share->getNode()->getId(),
173
			$userFolder->getRelativePath($share->getNode()->getPath())
174
		);
175
176
		if ($share->getShareOwner() !== $share->getSharedBy()) {
177
			$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
178
			$fileId = $share->getNode()->getId();
179
			$nodes = $ownerFolder->getById($fileId);
180
			$ownerPath = $nodes[0]->getPath();
181
			$this->publishActivity(
182
				Activity::SUBJECT_SHARED_EMAIL_BY,
183
				[$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
184
				$share->getShareOwner(),
185
				$fileId,
186
				$ownerFolder->getRelativePath($ownerPath)
187
			);
188
		}
189
190
	}
191
192
	/**
193
	 * publish activity if a file/folder was shared by mail
194
	 *
195
	 * @param $subject
196
	 * @param $parameters
197
	 * @param $affectedUser
198
	 * @param $fileId
199
	 * @param $filePath
200
	 */
201 View Code Duplication
	protected function publishActivity($subject, $parameters, $affectedUser, $fileId, $filePath) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
202
		$event = $this->activityManager->generateEvent();
203
		$event->setApp('sharebymail')
204
			->setType('shared')
205
			->setSubject($subject, $parameters)
206
			->setAffectedUser($affectedUser)
207
			->setObject('files', $fileId, $filePath);
208
		$this->activityManager->publish($event);
209
210
	}
211
212
	/**
213
	 * @param IShare $share
214
	 * @return int
215
	 * @throws \Exception
216
	 */
217
	protected function createMailShare(IShare $share) {
218
		$share->setToken($this->generateToken());
219
		$shareId = $this->addShareToDB(
220
			$share->getNodeId(),
221
			$share->getNodeType(),
222
			$share->getSharedWith(),
223
			$share->getSharedBy(),
224
			$share->getShareOwner(),
225
			$share->getPermissions(),
226
			$share->getToken()
227
		);
228
229
		try {
230
			$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
231
				['token' => $share->getToken()]);
232
			$this->sendMailNotification($share->getNode()->getName(),
233
				$link,
234
				$share->getShareOwner(),
235
				$share->getSharedBy(), $share->getSharedWith());
236
		} catch (HintException $hintException) {
237
			$this->logger->error('Failed to send share by mail: ' . $hintException->getMessage());
238
			$this->removeShareFromTable($shareId);
239
			throw $hintException;
240
		} catch (\Exception $e) {
241
			$this->logger->error('Failed to send share by mail: ' . $e->getMessage());
242
			$this->removeShareFromTable($shareId);
243
			throw new HintException('Failed to send share by mail',
244
				$this->l->t('Failed to send share by E-mail'));
245
		}
246
247
		return $shareId;
248
249
	}
250
251
	protected function sendMailNotification($filename, $link, $owner, $initiator, $shareWith) {
252
		$ownerUser = $this->userManager->get($owner);
253
		$initiatorUser = $this->userManager->get($initiator);
254
		$ownerDisplayName = ($ownerUser instanceof IUser) ? $ownerUser->getDisplayName() : $owner;
255
		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
256 View Code Duplication
		if ($owner === $initiator) {
257
			$subject = (string)$this->l->t('%s shared »%s« with you', array($ownerDisplayName, $filename));
258
		} else {
259
			$subject = (string)$this->l->t('%s shared »%s« with you on behalf of %s', array($ownerDisplayName, $filename, $initiatorDisplayName));
260
		}
261
262
		$message = $this->mailer->createMessage();
263
264
		$emailTemplate = $this->mailer->createEMailTemplate();
265
266
		$emailTemplate->addHeader();
267
		$emailTemplate->addHeading($this->l->t('%s shared »%s« with you', [$ownerDisplayName, $filename]), false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
268
269 View Code Duplication
		if ($owner === $initiator) {
270
			$text = $this->l->t('%s shared »%s« with you.', [$ownerDisplayName, $filename]);
271
		} else {
272
			$text= $this->l->t('%s shared »%s« with you on behalf of %s.', [$ownerDisplayName, $filename, $initiator]);
273
		}
274
275
		$emailTemplate->addBodyText(
276
			$text . ' ' . $this->l->t('Click the button below to open it.'),
277
			$text
278
		);
279
280
		$emailTemplate->addBodyButton(
281
			$this->l->t('Open »%s«', [$filename]),
282
			$link
283
		);
284
		$emailTemplate->addFooter();
285
286
		$message->setTo([$shareWith]);
287
		$message->setSubject($subject);
288
		$message->setBody($emailTemplate->renderText(), 'text/plain');
289
		$message->setHtmlBody($emailTemplate->renderHTML());
290
		$this->mailer->send($message);
291
292
	}
293
294
	/**
295
	 * send password to recipient of a mail share
296
	 *
297
	 * @param string $filename
298
	 * @param string $initiator
299
	 * @param string $shareWith
300
	 */
301
	protected function sendPassword($filename, $initiator, $shareWith, $password) {
302
303
		if ($this->settingsManager->sendPasswordByMail() === false) {
304
			return;
305
		}
306
307
		$initiatorUser = $this->userManager->get($initiator);
308
		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
309
		$subject = (string)$this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName]);
310
311
		$message = $this->mailer->createMessage();
312
313
		$emailTemplate = $this->mailer->createEMailTemplate();
314
315
		$emailTemplate->addHeader();
316
		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]));
317
318
		$emailTemplate->addBodyText($this->l->t(
319
			'%s shared »%s« with you. You should have already received a separate mail with a link to access it.',
320
				[$initiatorDisplayName, $filename]
321
		));
322
		$emailTemplate->addBodyText($this->l->t('It is protected with the following password: %s', [$password]));
323
324
		$emailTemplate->addFooter();
325
326
		$message->setTo([$shareWith]);
327
		$message->setSubject($subject);
328
		$message->setBody($emailTemplate->renderText(), 'text/plain');
329
		$message->setHtmlBody($emailTemplate->renderHTML());
330
		$this->mailer->send($message);
331
332
	}
333
334
335
	/**
336
	 * generate share token
337
	 *
338
	 * @return string
339
	 */
340
	protected function generateToken() {
341
		$token = $this->secureRandom->generate(
342
			15, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
343
		return $token;
344
	}
345
346
	/**
347
	 * Get all children of this share
348
	 *
349
	 * @param IShare $parent
350
	 * @return IShare[]
351
	 */
352 View Code Duplication
	public function getChildren(IShare $parent) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
353
		$children = [];
354
355
		$qb = $this->dbConnection->getQueryBuilder();
356
		$qb->select('*')
357
			->from('share')
358
			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
359
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
360
			->orderBy('id');
361
362
		$cursor = $qb->execute();
363
		while($data = $cursor->fetch()) {
364
			$children[] = $this->createShareObject($data);
365
		}
366
		$cursor->closeCursor();
367
368
		return $children;
369
	}
370
371
	/**
372
	 * add share to the database and return the ID
373
	 *
374
	 * @param int $itemSource
375
	 * @param string $itemType
376
	 * @param string $shareWith
377
	 * @param string $sharedBy
378
	 * @param string $uidOwner
379
	 * @param int $permissions
380
	 * @param string $token
381
	 * @return int
382
	 */
383 View Code Duplication
	protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
384
		$qb = $this->dbConnection->getQueryBuilder();
385
		$qb->insert('share')
386
			->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
387
			->setValue('item_type', $qb->createNamedParameter($itemType))
388
			->setValue('item_source', $qb->createNamedParameter($itemSource))
389
			->setValue('file_source', $qb->createNamedParameter($itemSource))
390
			->setValue('share_with', $qb->createNamedParameter($shareWith))
391
			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
392
			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
393
			->setValue('permissions', $qb->createNamedParameter($permissions))
394
			->setValue('token', $qb->createNamedParameter($token))
395
			->setValue('stime', $qb->createNamedParameter(time()));
396
397
		/*
398
		 * Added to fix https://github.com/owncloud/core/issues/22215
399
		 * Can be removed once we get rid of ajax/share.php
400
		 */
401
		$qb->setValue('file_target', $qb->createNamedParameter(''));
402
403
		$qb->execute();
404
		$id = $qb->getLastInsertId();
405
406
		return (int)$id;
407
	}
408
409
	/**
410
	 * Update a share
411
	 *
412
	 * @param IShare $share
413
	 * @param string|null $plainTextPassword
414
	 * @return IShare The share object
415
	 */
416
	public function update(IShare $share, $plainTextPassword = null) {
417
418
		$originalShare = $this->getShareById($share->getId());
419
420
		// a real password was given
421
		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
422
423
		if($validPassword && $originalShare->getPassword() !== $share->getPassword()) {
424
			$this->sendPassword($share->getNode()->getName(), $share->getSharedBy(), $share->getSharedWith(), $plainTextPassword);
425
		}
426
		/*
427
		 * We allow updating the permissions and password of mail shares
428
		 */
429
		$qb = $this->dbConnection->getQueryBuilder();
430
		$qb->update('share')
431
			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
432
			->set('permissions', $qb->createNamedParameter($share->getPermissions()))
433
			->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
434
			->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
435
			->set('password', $qb->createNamedParameter($share->getPassword()))
436
			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
437
			->execute();
438
439
		return $share;
440
	}
441
442
	/**
443
	 * @inheritdoc
444
	 */
445
	public function move(IShare $share, $recipient) {
446
		/**
447
		 * nothing to do here, mail shares are only outgoing shares
448
		 */
449
		return $share;
450
	}
451
452
	/**
453
	 * Delete a share (owner unShares the file)
454
	 *
455
	 * @param IShare $share
456
	 */
457
	public function delete(IShare $share) {
458
		$this->removeShareFromTable($share->getId());
459
	}
460
461
	/**
462
	 * @inheritdoc
463
	 */
464
	public function deleteFromSelf(IShare $share, $recipient) {
465
		// nothing to do here, mail shares are only outgoing shares
466
		return;
467
	}
468
469
	/**
470
	 * @inheritdoc
471
	 */
472 View Code Duplication
	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
473
		$qb = $this->dbConnection->getQueryBuilder();
474
		$qb->select('*')
475
			->from('share');
476
477
		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
478
479
		/**
480
		 * Reshares for this user are shares where they are the owner.
481
		 */
482
		if ($reshares === false) {
483
			//Special case for old shares created via the web UI
484
			$or1 = $qb->expr()->andX(
485
				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
486
				$qb->expr()->isNull('uid_initiator')
487
			);
488
489
			$qb->andWhere(
490
				$qb->expr()->orX(
491
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
492
					$or1
493
				)
494
			);
495
		} else {
496
			$qb->andWhere(
497
				$qb->expr()->orX(
498
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
499
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
500
				)
501
			);
502
		}
503
504
		if ($node !== null) {
505
			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
506
		}
507
508
		if ($limit !== -1) {
509
			$qb->setMaxResults($limit);
510
		}
511
512
		$qb->setFirstResult($offset);
513
		$qb->orderBy('id');
514
515
		$cursor = $qb->execute();
516
		$shares = [];
517
		while($data = $cursor->fetch()) {
518
			$shares[] = $this->createShareObject($data);
519
		}
520
		$cursor->closeCursor();
521
522
		return $shares;
523
	}
524
525
	/**
526
	 * @inheritdoc
527
	 */
528 View Code Duplication
	public function getShareById($id, $recipientId = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
529
		$qb = $this->dbConnection->getQueryBuilder();
530
531
		$qb->select('*')
532
			->from('share')
533
			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
534
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
535
536
		$cursor = $qb->execute();
537
		$data = $cursor->fetch();
538
		$cursor->closeCursor();
539
540
		if ($data === false) {
541
			throw new ShareNotFound();
542
		}
543
544
		try {
545
			$share = $this->createShareObject($data);
546
		} catch (InvalidShare $e) {
547
			throw new ShareNotFound();
548
		}
549
550
		return $share;
551
	}
552
553
	/**
554
	 * Get shares for a given path
555
	 *
556
	 * @param \OCP\Files\Node $path
557
	 * @return IShare[]
558
	 */
559 View Code Duplication
	public function getSharesByPath(Node $path) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
560
		$qb = $this->dbConnection->getQueryBuilder();
561
562
		$cursor = $qb->select('*')
563
			->from('share')
564
			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
565
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
566
			->execute();
567
568
		$shares = [];
569
		while($data = $cursor->fetch()) {
570
			$shares[] = $this->createShareObject($data);
571
		}
572
		$cursor->closeCursor();
573
574
		return $shares;
575
	}
576
577
	/**
578
	 * @inheritdoc
579
	 */
580 View Code Duplication
	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
581
		/** @var IShare[] $shares */
582
		$shares = [];
583
584
		//Get shares directly with this user
585
		$qb = $this->dbConnection->getQueryBuilder();
586
		$qb->select('*')
587
			->from('share');
588
589
		// Order by id
590
		$qb->orderBy('id');
591
592
		// Set limit and offset
593
		if ($limit !== -1) {
594
			$qb->setMaxResults($limit);
595
		}
596
		$qb->setFirstResult($offset);
597
598
		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
599
		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
600
601
		// Filter by node if provided
602
		if ($node !== null) {
603
			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
604
		}
605
606
		$cursor = $qb->execute();
607
608
		while($data = $cursor->fetch()) {
609
			$shares[] = $this->createShareObject($data);
610
		}
611
		$cursor->closeCursor();
612
613
614
		return $shares;
615
	}
616
617
	/**
618
	 * Get a share by token
619
	 *
620
	 * @param string $token
621
	 * @return IShare
622
	 * @throws ShareNotFound
623
	 */
624 View Code Duplication
	public function getShareByToken($token) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
625
		$qb = $this->dbConnection->getQueryBuilder();
626
627
		$cursor = $qb->select('*')
628
			->from('share')
629
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
630
			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
631
			->execute();
632
633
		$data = $cursor->fetch();
634
635
		if ($data === false) {
636
			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
637
		}
638
639
		try {
640
			$share = $this->createShareObject($data);
641
		} catch (InvalidShare $e) {
642
			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
643
		}
644
645
		return $share;
646
	}
647
648
	/**
649
	 * remove share from table
650
	 *
651
	 * @param string $shareId
652
	 */
653
	protected function removeShareFromTable($shareId) {
654
		$qb = $this->dbConnection->getQueryBuilder();
655
		$qb->delete('share')
656
			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
657
		$qb->execute();
658
	}
659
660
	/**
661
	 * Create a share object from an database row
662
	 *
663
	 * @param array $data
664
	 * @return IShare
665
	 * @throws InvalidShare
666
	 * @throws ShareNotFound
667
	 */
668
	protected function createShareObject($data) {
669
670
		$share = new Share($this->rootFolder, $this->userManager);
671
		$share->setId((int)$data['id'])
672
			->setShareType((int)$data['share_type'])
673
			->setPermissions((int)$data['permissions'])
674
			->setTarget($data['file_target'])
675
			->setMailSend((bool)$data['mail_send'])
676
			->setToken($data['token']);
677
678
		$shareTime = new \DateTime();
679
		$shareTime->setTimestamp((int)$data['stime']);
680
		$share->setShareTime($shareTime);
681
		$share->setSharedWith($data['share_with']);
682
		$share->setPassword($data['password']);
683
684
		if ($data['uid_initiator'] !== null) {
685
			$share->setShareOwner($data['uid_owner']);
686
			$share->setSharedBy($data['uid_initiator']);
687
		} else {
688
			//OLD SHARE
689
			$share->setSharedBy($data['uid_owner']);
690
			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
691
692
			$owner = $path->getOwner();
693
			$share->setShareOwner($owner->getUID());
694
		}
695
696 View Code Duplication
		if ($data['expiration'] !== null) {
697
			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
698
			if ($expiration !== false) {
699
				$share->setExpirationDate($expiration);
700
			}
701
		}
702
703
		$share->setNodeId((int)$data['file_source']);
704
		$share->setNodeType($data['item_type']);
705
706
		$share->setProviderId($this->identifier());
707
708
		return $share;
709
	}
710
711
	/**
712
	 * Get the node with file $id for $user
713
	 *
714
	 * @param string $userId
715
	 * @param int $id
716
	 * @return \OCP\Files\File|\OCP\Files\Folder
717
	 * @throws InvalidShare
718
	 */
719 View Code Duplication
	private function getNode($userId, $id) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
720
		try {
721
			$userFolder = $this->rootFolder->getUserFolder($userId);
722
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class OCA\ShareByMail\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
723
			throw new InvalidShare();
724
		}
725
726
		$nodes = $userFolder->getById($id);
727
728
		if (empty($nodes)) {
729
			throw new InvalidShare();
730
		}
731
732
		return $nodes[0];
733
	}
734
735
	/**
736
	 * A user is deleted from the system
737
	 * So clean up the relevant shares.
738
	 *
739
	 * @param string $uid
740
	 * @param int $shareType
741
	 */
742 View Code Duplication
	public function userDeleted($uid, $shareType) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
743
		$qb = $this->dbConnection->getQueryBuilder();
744
745
		$qb->delete('share')
746
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
747
			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
748
			->execute();
749
	}
750
751
	/**
752
	 * This provider does not support group shares
753
	 *
754
	 * @param string $gid
755
	 */
756
	public function groupDeleted($gid) {
757
		return;
758
	}
759
760
	/**
761
	 * This provider does not support group shares
762
	 *
763
	 * @param string $uid
764
	 * @param string $gid
765
	 */
766
	public function userDeletedFromGroup($uid, $gid) {
767
		return;
768
	}
769
770
	/**
771
	 * get database row of a give share
772
	 *
773
	 * @param $id
774
	 * @return array
775
	 * @throws ShareNotFound
776
	 */
777 View Code Duplication
	protected function getRawShare($id) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
778
779
		// Now fetch the inserted share and create a complete share object
780
		$qb = $this->dbConnection->getQueryBuilder();
781
		$qb->select('*')
782
			->from('share')
783
			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
784
785
		$cursor = $qb->execute();
786
		$data = $cursor->fetch();
787
		$cursor->closeCursor();
788
789
		if ($data === false) {
790
			throw new ShareNotFound;
791
		}
792
793
		return $data;
794
	}
795
796 View Code Duplication
	public function getSharesInFolder($userId, Folder $node, $reshares) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
797
		$qb = $this->dbConnection->getQueryBuilder();
798
		$qb->select('*')
799
			->from('share', 's')
800
			->andWhere($qb->expr()->orX(
801
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
802
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
803
			))
804
			->andWhere(
805
				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
806
			);
807
808
		/**
809
		 * Reshares for this user are shares where they are the owner.
810
		 */
811
		if ($reshares === false) {
812
			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
813
		} else {
814
			$qb->andWhere(
815
				$qb->expr()->orX(
816
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
817
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
818
				)
819
			);
820
		}
821
822
		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
823
		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
824
825
		$qb->orderBy('id');
826
827
		$cursor = $qb->execute();
828
		$shares = [];
829
		while ($data = $cursor->fetch()) {
830
			$shares[$data['fileid']][] = $this->createShareObject($data);
831
		}
832
		$cursor->closeCursor();
833
834
		return $shares;
835
	}
836
837
	/**
838
	 * @inheritdoc
839
	 */
840
	public function getAccessList($nodes, $currentAccess) {
841
		$ids = [];
842
		foreach ($nodes as $node) {
843
			$ids[] = $node->getId();
844
		}
845
846
		$qb = $this->dbConnection->getQueryBuilder();
847
		$qb->select('share_with')
848
			->from('share')
849
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
850
			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
851
			->andWhere($qb->expr()->orX(
852
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
853
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
854
			))
855
			->setMaxResults(1);
856
		$cursor = $qb->execute();
857
858
		$mail = $cursor->fetch() !== false;
859
		$cursor->closeCursor();
860
861
		return ['public' => $mail];
862
	}
863
864
}
865