Completed
Push — master ( 9adfa6...ca9d25 )
by Morris
22:40 queued 11:31
created

ShareByMailProvider::delete()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
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
		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
		$htmlBody = $this->createMailBody('mail', $filename, $link, $ownerDisplayName, $initiatorDisplayName);
264
		$textBody = $this->createMailBody('altmail', $filename, $link, $ownerDisplayName, $initiatorDisplayName);
265
		$message->setTo([$shareWith]);
266
		$message->setSubject($subject);
267
		$message->setBody($textBody, 'text/plain');
268
		$message->setHtmlBody($htmlBody);
269
		$this->mailer->send($message);
270
271
	}
272
273
	/**
274
	 * create mail body
275
	 *
276
	 * @param $filename
277
	 * @param $link
278
	 * @param $owner
279
	 * @param $initiator
280
	 * @return string plain text mail
281
	 * @throws HintException
282
	 */
283
	protected function createMailBody($template, $filename, $link, $owner, $initiator) {
284
285
		$mailBodyTemplate = new Template('sharebymail', $template, '');
286
		$mailBodyTemplate->assign ('filename', \OCP\Util::sanitizeHTML($filename));
287
		$mailBodyTemplate->assign ('link', $link);
288
		$mailBodyTemplate->assign ('owner', \OCP\Util::sanitizeHTML($owner));
289
		$mailBodyTemplate->assign ('initiator', \OCP\Util::sanitizeHTML($initiator));
290
		$mailBodyTemplate->assign ('onBehalfOf', $initiator !== $owner);
291
		$mailBody = $mailBodyTemplate->fetchPage();
292
293
		if (is_string($mailBody)) {
294
			return $mailBody;
295
		}
296
297
		throw new HintException('Failed to create the E-mail',
298
			$this->l->t('Failed to create the E-mail'));
299
	}
300
301
	/**
302
	 * send password to recipient of a mail share
303
	 *
304
	 * @param string $filename
305
	 * @param string $initiator
306
	 * @param string $shareWith
307
	 */
308
	protected function sendPassword($filename, $initiator, $shareWith, $password) {
309
310
		if ($this->settingsManager->sendPasswordByMail() === false) {
311
			return;
312
		}
313
314
		$initiatorUser = $this->userManager->get($initiator);
315
		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
316
		$subject = (string)$this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName]);
317
318
		$message = $this->mailer->createMessage();
319
		$htmlBody = $this->createMailBodyToSendPassword('mailpassword', $filename, $initiatorDisplayName, $password);
320
		$textBody = $this->createMailBodyToSendPassword('altmailpassword', $filename,$initiatorDisplayName, $password);
321
		$message->setTo([$shareWith]);
322
		$message->setSubject($subject);
323
		$message->setBody($textBody, 'text/plain');
324
		$message->setHtmlBody($htmlBody);
325
		$this->mailer->send($message);
326
327
	}
328
329
	/**
330
	 * create mail body to send password to recipient
331
	 *
332
	 * @param string $filename
333
	 * @param string $initiator
334
	 * @param string $password
335
	 * @return string plain text mail
336
	 * @throws HintException
337
	 */
338
	protected function createMailBodyToSendPassword($template, $filename, $initiator, $password) {
339
340
		$mailBodyTemplate = new Template('sharebymail', $template, '');
341
		$mailBodyTemplate->assign ('filename', \OCP\Util::sanitizeHTML($filename));
342
		$mailBodyTemplate->assign ('password', \OCP\Util::sanitizeHTML($password));
343
		$mailBodyTemplate->assign ('initiator', \OCP\Util::sanitizeHTML($initiator));
344
		$mailBody = $mailBodyTemplate->fetchPage();
345
346
		if (is_string($mailBody)) {
347
			return $mailBody;
348
		}
349
350
		throw new HintException('Failed to create the E-mail',
351
			$this->l->t('Failed to create the E-mail'));
352
	}
353
354
355
	/**
356
	 * generate share token
357
	 *
358
	 * @return string
359
	 */
360
	protected function generateToken() {
361
		$token = $this->secureRandom->generate(
362
			15, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
363
		return $token;
364
	}
365
366
	/**
367
	 * Get all children of this share
368
	 *
369
	 * @param IShare $parent
370
	 * @return IShare[]
371
	 */
372 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...
373
		$children = [];
374
375
		$qb = $this->dbConnection->getQueryBuilder();
376
		$qb->select('*')
377
			->from('share')
378
			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
379
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
380
			->orderBy('id');
381
382
		$cursor = $qb->execute();
383
		while($data = $cursor->fetch()) {
384
			$children[] = $this->createShareObject($data);
385
		}
386
		$cursor->closeCursor();
387
388
		return $children;
389
	}
390
391
	/**
392
	 * add share to the database and return the ID
393
	 *
394
	 * @param int $itemSource
395
	 * @param string $itemType
396
	 * @param string $shareWith
397
	 * @param string $sharedBy
398
	 * @param string $uidOwner
399
	 * @param int $permissions
400
	 * @param string $token
401
	 * @return int
402
	 */
403 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...
404
		$qb = $this->dbConnection->getQueryBuilder();
405
		$qb->insert('share')
406
			->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
407
			->setValue('item_type', $qb->createNamedParameter($itemType))
408
			->setValue('item_source', $qb->createNamedParameter($itemSource))
409
			->setValue('file_source', $qb->createNamedParameter($itemSource))
410
			->setValue('share_with', $qb->createNamedParameter($shareWith))
411
			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
412
			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
413
			->setValue('permissions', $qb->createNamedParameter($permissions))
414
			->setValue('token', $qb->createNamedParameter($token))
415
			->setValue('stime', $qb->createNamedParameter(time()));
416
417
		/*
418
		 * Added to fix https://github.com/owncloud/core/issues/22215
419
		 * Can be removed once we get rid of ajax/share.php
420
		 */
421
		$qb->setValue('file_target', $qb->createNamedParameter(''));
422
423
		$qb->execute();
424
		$id = $qb->getLastInsertId();
425
426
		return (int)$id;
427
	}
428
429
	/**
430
	 * Update a share
431
	 *
432
	 * @param IShare $share
433
	 * @param string|null $plainTextPassword
434
	 * @return IShare The share object
435
	 */
436
	public function update(IShare $share, $plainTextPassword = null) {
437
438
		$originalShare = $this->getShareById($share->getId());
439
440
		// a real password was given
441
		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
442
443
		if($validPassword && $originalShare->getPassword() !== $share->getPassword()) {
444
			$this->sendPassword($share->getNode()->getName(), $share->getSharedBy(), $share->getSharedWith(), $plainTextPassword);
445
		}
446
		/*
447
		 * We allow updating the permissions and password of mail shares
448
		 */
449
		$qb = $this->dbConnection->getQueryBuilder();
450
		$qb->update('share')
451
			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
452
			->set('permissions', $qb->createNamedParameter($share->getPermissions()))
453
			->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
454
			->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
455
			->set('password', $qb->createNamedParameter($share->getPassword()))
456
			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
457
			->execute();
458
459
		return $share;
460
	}
461
462
	/**
463
	 * @inheritdoc
464
	 */
465
	public function move(IShare $share, $recipient) {
466
		/**
467
		 * nothing to do here, mail shares are only outgoing shares
468
		 */
469
		return $share;
470
	}
471
472
	/**
473
	 * Delete a share (owner unShares the file)
474
	 *
475
	 * @param IShare $share
476
	 */
477
	public function delete(IShare $share) {
478
		$this->removeShareFromTable($share->getId());
479
	}
480
481
	/**
482
	 * @inheritdoc
483
	 */
484
	public function deleteFromSelf(IShare $share, $recipient) {
485
		// nothing to do here, mail shares are only outgoing shares
486
		return;
487
	}
488
489
	/**
490
	 * @inheritdoc
491
	 */
492 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...
493
		$qb = $this->dbConnection->getQueryBuilder();
494
		$qb->select('*')
495
			->from('share');
496
497
		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
498
499
		/**
500
		 * Reshares for this user are shares where they are the owner.
501
		 */
502
		if ($reshares === false) {
503
			//Special case for old shares created via the web UI
504
			$or1 = $qb->expr()->andX(
505
				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
506
				$qb->expr()->isNull('uid_initiator')
507
			);
508
509
			$qb->andWhere(
510
				$qb->expr()->orX(
511
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
512
					$or1
513
				)
514
			);
515
		} else {
516
			$qb->andWhere(
517
				$qb->expr()->orX(
518
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
519
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
520
				)
521
			);
522
		}
523
524
		if ($node !== null) {
525
			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
526
		}
527
528
		if ($limit !== -1) {
529
			$qb->setMaxResults($limit);
530
		}
531
532
		$qb->setFirstResult($offset);
533
		$qb->orderBy('id');
534
535
		$cursor = $qb->execute();
536
		$shares = [];
537
		while($data = $cursor->fetch()) {
538
			$shares[] = $this->createShareObject($data);
539
		}
540
		$cursor->closeCursor();
541
542
		return $shares;
543
	}
544
545
	/**
546
	 * @inheritdoc
547
	 */
548 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...
549
		$qb = $this->dbConnection->getQueryBuilder();
550
551
		$qb->select('*')
552
			->from('share')
553
			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
554
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
555
556
		$cursor = $qb->execute();
557
		$data = $cursor->fetch();
558
		$cursor->closeCursor();
559
560
		if ($data === false) {
561
			throw new ShareNotFound();
562
		}
563
564
		try {
565
			$share = $this->createShareObject($data);
566
		} catch (InvalidShare $e) {
567
			throw new ShareNotFound();
568
		}
569
570
		return $share;
571
	}
572
573
	/**
574
	 * Get shares for a given path
575
	 *
576
	 * @param \OCP\Files\Node $path
577
	 * @return IShare[]
578
	 */
579 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...
580
		$qb = $this->dbConnection->getQueryBuilder();
581
582
		$cursor = $qb->select('*')
583
			->from('share')
584
			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
585
			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
586
			->execute();
587
588
		$shares = [];
589
		while($data = $cursor->fetch()) {
590
			$shares[] = $this->createShareObject($data);
591
		}
592
		$cursor->closeCursor();
593
594
		return $shares;
595
	}
596
597
	/**
598
	 * @inheritdoc
599
	 */
600 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...
601
		/** @var IShare[] $shares */
602
		$shares = [];
603
604
		//Get shares directly with this user
605
		$qb = $this->dbConnection->getQueryBuilder();
606
		$qb->select('*')
607
			->from('share');
608
609
		// Order by id
610
		$qb->orderBy('id');
611
612
		// Set limit and offset
613
		if ($limit !== -1) {
614
			$qb->setMaxResults($limit);
615
		}
616
		$qb->setFirstResult($offset);
617
618
		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
619
		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
620
621
		// Filter by node if provided
622
		if ($node !== null) {
623
			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
624
		}
625
626
		$cursor = $qb->execute();
627
628
		while($data = $cursor->fetch()) {
629
			$shares[] = $this->createShareObject($data);
630
		}
631
		$cursor->closeCursor();
632
633
634
		return $shares;
635
	}
636
637
	/**
638
	 * Get a share by token
639
	 *
640
	 * @param string $token
641
	 * @return IShare
642
	 * @throws ShareNotFound
643
	 */
644 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...
645
		$qb = $this->dbConnection->getQueryBuilder();
646
647
		$cursor = $qb->select('*')
648
			->from('share')
649
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
650
			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
651
			->execute();
652
653
		$data = $cursor->fetch();
654
655
		if ($data === false) {
656
			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
657
		}
658
659
		try {
660
			$share = $this->createShareObject($data);
661
		} catch (InvalidShare $e) {
662
			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
663
		}
664
665
		return $share;
666
	}
667
668
	/**
669
	 * remove share from table
670
	 *
671
	 * @param string $shareId
672
	 */
673
	protected function removeShareFromTable($shareId) {
674
		$qb = $this->dbConnection->getQueryBuilder();
675
		$qb->delete('share')
676
			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
677
		$qb->execute();
678
	}
679
680
	/**
681
	 * Create a share object from an database row
682
	 *
683
	 * @param array $data
684
	 * @return IShare
685
	 * @throws InvalidShare
686
	 * @throws ShareNotFound
687
	 */
688
	protected function createShareObject($data) {
689
690
		$share = new Share($this->rootFolder, $this->userManager);
691
		$share->setId((int)$data['id'])
692
			->setShareType((int)$data['share_type'])
693
			->setPermissions((int)$data['permissions'])
694
			->setTarget($data['file_target'])
695
			->setMailSend((bool)$data['mail_send'])
696
			->setToken($data['token']);
697
698
		$shareTime = new \DateTime();
699
		$shareTime->setTimestamp((int)$data['stime']);
700
		$share->setShareTime($shareTime);
701
		$share->setSharedWith($data['share_with']);
702
		$share->setPassword($data['password']);
703
704
		if ($data['uid_initiator'] !== null) {
705
			$share->setShareOwner($data['uid_owner']);
706
			$share->setSharedBy($data['uid_initiator']);
707
		} else {
708
			//OLD SHARE
709
			$share->setSharedBy($data['uid_owner']);
710
			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
711
712
			$owner = $path->getOwner();
713
			$share->setShareOwner($owner->getUID());
714
		}
715
716 View Code Duplication
		if ($data['expiration'] !== null) {
717
			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
718
			if ($expiration !== false) {
719
				$share->setExpirationDate($expiration);
720
			}
721
		}
722
723
		$share->setNodeId((int)$data['file_source']);
724
		$share->setNodeType($data['item_type']);
725
726
		$share->setProviderId($this->identifier());
727
728
		return $share;
729
	}
730
731
	/**
732
	 * Get the node with file $id for $user
733
	 *
734
	 * @param string $userId
735
	 * @param int $id
736
	 * @return \OCP\Files\File|\OCP\Files\Folder
737
	 * @throws InvalidShare
738
	 */
739 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...
740
		try {
741
			$userFolder = $this->rootFolder->getUserFolder($userId);
742
		} 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...
743
			throw new InvalidShare();
744
		}
745
746
		$nodes = $userFolder->getById($id);
747
748
		if (empty($nodes)) {
749
			throw new InvalidShare();
750
		}
751
752
		return $nodes[0];
753
	}
754
755
	/**
756
	 * A user is deleted from the system
757
	 * So clean up the relevant shares.
758
	 *
759
	 * @param string $uid
760
	 * @param int $shareType
761
	 */
762 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...
763
		$qb = $this->dbConnection->getQueryBuilder();
764
765
		$qb->delete('share')
766
			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
767
			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
768
			->execute();
769
	}
770
771
	/**
772
	 * This provider does not support group shares
773
	 *
774
	 * @param string $gid
775
	 */
776
	public function groupDeleted($gid) {
777
		return;
778
	}
779
780
	/**
781
	 * This provider does not support group shares
782
	 *
783
	 * @param string $uid
784
	 * @param string $gid
785
	 */
786
	public function userDeletedFromGroup($uid, $gid) {
787
		return;
788
	}
789
790
	/**
791
	 * get database row of a give share
792
	 *
793
	 * @param $id
794
	 * @return array
795
	 * @throws ShareNotFound
796
	 */
797 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...
798
799
		// Now fetch the inserted share and create a complete share object
800
		$qb = $this->dbConnection->getQueryBuilder();
801
		$qb->select('*')
802
			->from('share')
803
			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
804
805
		$cursor = $qb->execute();
806
		$data = $cursor->fetch();
807
		$cursor->closeCursor();
808
809
		if ($data === false) {
810
			throw new ShareNotFound;
811
		}
812
813
		return $data;
814
	}
815
816 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...
817
		$qb = $this->dbConnection->getQueryBuilder();
818
		$qb->select('*')
819
			->from('share', 's')
820
			->andWhere($qb->expr()->orX(
821
				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
822
				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
823
			))
824
			->andWhere(
825
				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
826
			);
827
828
		/**
829
		 * Reshares for this user are shares where they are the owner.
830
		 */
831
		if ($reshares === false) {
832
			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
833
		} else {
834
			$qb->andWhere(
835
				$qb->expr()->orX(
836
					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
837
					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
838
				)
839
			);
840
		}
841
842
		$qb->innerJoin('s', 'filecache' ,'f', 's.file_source = f.fileid');
843
		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
844
845
		$qb->orderBy('id');
846
847
		$cursor = $qb->execute();
848
		$shares = [];
849
		while ($data = $cursor->fetch()) {
850
			$shares[$data['fileid']][] = $this->createShareObject($data);
851
		}
852
		$cursor->closeCursor();
853
854
		return $shares;
855
	}
856
857
}
858