Completed
Push — master ( 7da815...9b9d72 )
by Morris
21:22
created

ShareController::showAuthFailed()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 8
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 8
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Bjoern Schiessle <[email protected]>
7
 * @author Björn Schießle <[email protected]>
8
 * @author Georg Ehrke <[email protected]>
9
 * @author Joas Schilling <[email protected]>
10
 * @author Lukas Reschke <[email protected]>
11
 * @author Maxence Lange <[email protected]>
12
 * @author Morris Jobke <[email protected]>
13
 * @author Piotr Filiciak <[email protected]>
14
 * @author Robin Appelman <[email protected]>
15
 * @author Roeland Jago Douma <[email protected]>
16
 * @author Sascha Sambale <[email protected]>
17
 * @author Thomas Müller <[email protected]>
18
 * @author Vincent Petry <[email protected]>
19
 *
20
 * @license AGPL-3.0
21
 *
22
 * This code is free software: you can redistribute it and/or modify
23
 * it under the terms of the GNU Affero General Public License, version 3,
24
 * as published by the Free Software Foundation.
25
 *
26
 * This program is distributed in the hope that it will be useful,
27
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
 * GNU Affero General Public License for more details.
30
 *
31
 * You should have received a copy of the GNU Affero General Public License, version 3,
32
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
33
 *
34
 */
35
36
namespace OCA\Files_Sharing\Controller;
37
38
use OC_Files;
39
use OC_Util;
40
use OCA\FederatedFileSharing\FederatedShareProvider;
41
use OCP\AppFramework\AuthPublicShareController;
42
use OCP\AppFramework\Http\Template\SimpleMenuAction;
43
use OCP\AppFramework\Http\Template\ExternalShareMenuAction;
44
use OCP\AppFramework\Http\Template\LinkMenuAction;
45
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
46
use OCP\Defaults;
47
use OCP\IL10N;
48
use OCP\Template;
49
use OCP\Share;
50
use OCP\IRequest;
51
use OCP\AppFramework\Http\TemplateResponse;
52
use OCP\AppFramework\Http\NotFoundResponse;
53
use OCP\IURLGenerator;
54
use OCP\IConfig;
55
use OCP\ILogger;
56
use OCP\IUserManager;
57
use OCP\ISession;
58
use OCP\IPreview;
59
use OCA\Files_Sharing\Activity\Providers\Downloads;
60
use OCP\Files\NotFoundException;
61
use OCP\Files\IRootFolder;
62
use OCP\Share\Exceptions\ShareNotFound;
63
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
64
use Symfony\Component\EventDispatcher\GenericEvent;
65
use OCP\Share\IManager as ShareManager;
66
67
/**
68
 * Class ShareController
69
 *
70
 * @package OCA\Files_Sharing\Controllers
71
 */
72
class ShareController extends AuthPublicShareController {
73
74
	/** @var IConfig */
75
	protected $config;
76
	/** @var IUserManager */
77
	protected $userManager;
78
	/** @var ILogger */
79
	protected $logger;
80
	/** @var \OCP\Activity\IManager */
81
	protected $activityManager;
82
	/** @var IPreview */
83
	protected $previewManager;
84
	/** @var IRootFolder */
85
	protected $rootFolder;
86
	/** @var FederatedShareProvider */
87
	protected $federatedShareProvider;
88
	/** @var EventDispatcherInterface */
89
	protected $eventDispatcher;
90
	/** @var IL10N */
91
	protected $l10n;
92
	/** @var Defaults */
93
	protected $defaults;
94
	/** @var ShareManager */
95
	protected $shareManager;
96
97
	/** @var Share\IShare */
98
	protected $share;
99
100
	/**
101
	 * @param string $appName
102
	 * @param IRequest $request
103
	 * @param IConfig $config
104
	 * @param IURLGenerator $urlGenerator
105
	 * @param IUserManager $userManager
106
	 * @param ILogger $logger
107
	 * @param \OCP\Activity\IManager $activityManager
108
	 * @param \OCP\Share\IManager $shareManager
109
	 * @param ISession $session
110
	 * @param IPreview $previewManager
111
	 * @param IRootFolder $rootFolder
112
	 * @param FederatedShareProvider $federatedShareProvider
113
	 * @param EventDispatcherInterface $eventDispatcher
114
	 * @param IL10N $l10n
115
	 * @param Defaults $defaults
116
	 */
117
	public function __construct(string $appName,
118
								IRequest $request,
119
								IConfig $config,
120
								IURLGenerator $urlGenerator,
121
								IUserManager $userManager,
122
								ILogger $logger,
123
								\OCP\Activity\IManager $activityManager,
124
								ShareManager $shareManager,
125
								ISession $session,
126
								IPreview $previewManager,
127
								IRootFolder $rootFolder,
128
								FederatedShareProvider $federatedShareProvider,
129
								EventDispatcherInterface $eventDispatcher,
130
								IL10N $l10n,
131
								Defaults $defaults) {
132
		parent::__construct($appName, $request, $session, $urlGenerator);
133
134
		$this->config = $config;
135
		$this->userManager = $userManager;
136
		$this->logger = $logger;
137
		$this->activityManager = $activityManager;
138
		$this->previewManager = $previewManager;
139
		$this->rootFolder = $rootFolder;
140
		$this->federatedShareProvider = $federatedShareProvider;
141
		$this->eventDispatcher = $eventDispatcher;
142
		$this->l10n = $l10n;
143
		$this->defaults = $defaults;
144
		$this->shareManager = $shareManager;
145
	}
146
147
	/**
148
	 * @PublicPage
149
	 * @NoCSRFRequired
150
	 *
151
	 * Show the authentication page
152
	 * The form has to submit to the authenticate method route
153
	 */
154 View Code Duplication
	public function showAuthenticate(): TemplateResponse {
155
		$templateParameters = ['share' => $this->share];
156
157
		$event = new GenericEvent(null, $templateParameters);
158
		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
159
160
		return new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
161
	}
162
163
	/**
164
	 * The template to show when authentication failed
165
	 */
166 View Code Duplication
	protected function showAuthFailed(): TemplateResponse {
167
		$templateParameters = ['share' => $this->share, 'wrongpw' => true];
168
169
		$event = new GenericEvent(null, $templateParameters);
170
		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
171
172
		return new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
173
	}
174
175
	protected function verifyPassword(string $password): bool {
176
		return $this->shareManager->checkPassword($this->share, $password);
177
	}
178
179
	protected function getPasswordHash(): string {
180
		return $this->share->getPassword();
181
	}
182
183 View Code Duplication
	public function isValidToken(): bool {
184
		try {
185
			$this->share = $this->shareManager->getShareByToken($this->getToken());
186
		} catch (ShareNotFound $e) {
187
			return false;
188
		}
189
190
		return true;
191
	}
192
193
	protected function isPasswordProtected(): bool {
194
		return $this->share->getPassword() !== null;
195
	}
196
197
	protected function authSucceeded() {
198
		// For share this was always set so it is still used in other apps
199
		$this->session->set('public_link_authenticated', (string)$this->share->getId());
200
	}
201
202
	protected function authFailed() {
203
		$this->emitAccessShareHook($this->share, 403, 'Wrong password');
204
	}
205
206
	/**
207
	 * throws hooks when a share is attempted to be accessed
208
	 *
209
	 * @param \OCP\Share\IShare|string $share the Share instance if available,
210
	 * otherwise token
211
	 * @param int $errorCode
212
	 * @param string $errorMessage
213
	 * @throws \OC\HintException
214
	 * @throws \OC\ServerNotAvailableException
215
	 */
216
	protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
217
		$itemType = $itemSource = $uidOwner = '';
218
		$token = $share;
219
		$exception = null;
220
		if($share instanceof \OCP\Share\IShare) {
221
			try {
222
				$token = $share->getToken();
223
				$uidOwner = $share->getSharedBy();
224
				$itemType = $share->getNodeType();
225
				$itemSource = $share->getNodeId();
226
			} catch (\Exception $e) {
227
				// we log what we know and pass on the exception afterwards
228
				$exception = $e;
229
			}
230
		}
231
		\OC_Hook::emit(Share::class, 'share_link_access', [
232
			'itemType' => $itemType,
233
			'itemSource' => $itemSource,
234
			'uidOwner' => $uidOwner,
235
			'token' => $token,
236
			'errorCode' => $errorCode,
237
			'errorMessage' => $errorMessage,
238
		]);
239
		if(!is_null($exception)) {
240
			throw $exception;
241
		}
242
	}
243
244
	/**
245
	 * Validate the permissions of the share
246
	 *
247
	 * @param Share\IShare $share
248
	 * @return bool
249
	 */
250
	private function validateShare(\OCP\Share\IShare $share) {
251
		return $share->getNode()->isReadable() && $share->getNode()->isShareable();
252
	}
253
254
	/**
255
	 * @PublicPage
256
	 * @NoCSRFRequired
257
	 *
258
259
	 * @param string $path
260
	 * @return TemplateResponse
261
	 * @throws NotFoundException
262
	 * @throws \Exception
263
	 */
264
	public function showShare($path = ''): TemplateResponse {
265
		\OC_User::setIncognitoMode(true);
266
267
		// Check whether share exists
268
		try {
269
			$share = $this->shareManager->getShareByToken($this->getToken());
270
		} catch (ShareNotFound $e) {
271
			$this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
272
			throw new NotFoundException();
273
		}
274
275
		if (!$this->validateShare($share)) {
276
			throw new NotFoundException();
277
		}
278
		// We can't get the path of a file share
279
		try {
280
			if ($share->getNode() instanceof \OCP\Files\File && $path !== '') {
281
				$this->emitAccessShareHook($share, 404, 'Share not found');
282
				throw new NotFoundException();
283
			}
284
		} catch (\Exception $e) {
285
			$this->emitAccessShareHook($share, 404, 'Share not found');
286
			throw $e;
287
		}
288
289
		$shareTmpl = [];
290
		$shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
291
		$shareTmpl['owner'] = $share->getShareOwner();
292
		$shareTmpl['filename'] = $share->getNode()->getName();
293
		$shareTmpl['directory_path'] = $share->getTarget();
294
		$shareTmpl['note'] = $share->getNote();
295
		$shareTmpl['mimetype'] = $share->getNode()->getMimetype();
296
		$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($share->getNode()->getMimetype());
297
		$shareTmpl['dirToken'] = $this->getToken();
298
		$shareTmpl['sharingToken'] = $this->getToken();
299
		$shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
300
		$shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
301
		$shareTmpl['dir'] = '';
302
		$shareTmpl['nonHumanFileSize'] = $share->getNode()->getSize();
303
		$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize());
304
305
		// Show file list
306
		$hideFileList = false;
307
		if ($share->getNode() instanceof \OCP\Files\Folder) {
308
			/** @var \OCP\Files\Folder $rootFolder */
309
			$rootFolder = $share->getNode();
310
311
			try {
312
				$folderNode = $rootFolder->get($path);
313
			} catch (\OCP\Files\NotFoundException $e) {
314
				$this->emitAccessShareHook($share, 404, 'Share not found');
315
				throw new NotFoundException();
316
			}
317
318
			$shareTmpl['dir'] = $rootFolder->getRelativePath($folderNode->getPath());
319
320
			/*
321
			 * The OC_Util methods require a view. This just uses the node API
322
			 */
323
			$freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
324 View Code Duplication
			if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
325
				$freeSpace = max($freeSpace, 0);
326
			} else {
327
				$freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
328
			}
329
330
			$hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
331
			$maxUploadFilesize = $freeSpace;
332
333
			$folder = new Template('files', 'list', '');
334
			$folder->assign('dir', $rootFolder->getRelativePath($folderNode->getPath()));
335
			$folder->assign('dirToken', $this->getToken());
336
			$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
337
			$folder->assign('isPublic', true);
338
			$folder->assign('hideFileList', $hideFileList);
339
			$folder->assign('publicUploadEnabled', 'no');
340
			$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
341
			$folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
342
			$folder->assign('freeSpace', $freeSpace);
343
			$folder->assign('usedSpacePercent', 0);
344
			$folder->assign('trash', false);
345
			$shareTmpl['folder'] = $folder->fetchPage();
346
		}
347
348
		$shareTmpl['hideFileList'] = $hideFileList;
349
		$shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
350
		$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $this->getToken()]);
351
		$shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
352
		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
353
		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
354
		$shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
355
		$shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
356
		$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
357
		$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
358
		$ogPreview = '';
0 ignored issues
show
Unused Code introduced by
$ogPreview is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
359
		if ($shareTmpl['previewSupported']) {
360
			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
361
				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
362
			$ogPreview = $shareTmpl['previewImage'];
363
364
			// We just have direct previews for image files
365
			if ($share->getNode()->getMimePart() === 'image') {
366
				$shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
367
368
				$ogPreview = $shareTmpl['previewURL'];
369
370
				//Whatapp is kind of picky about their size requirements
371
				if ($this->request->isUserAgent(['/^WhatsApp/'])) {
372
					$ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
373
						'token' => $this->getToken(),
374
						'x' => 256,
375
						'y' => 256,
376
						'a' => true,
377
					]);
378
				}
379
			}
380
		} else {
381
			$shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
382
			$ogPreview = $shareTmpl['previewImage'];
383
		}
384
385
		// Load files we need
386
		\OCP\Util::addScript('files', 'file-upload');
387
		\OCP\Util::addStyle('files_sharing', 'publicView');
388
		\OCP\Util::addScript('files_sharing', 'public');
389
		\OCP\Util::addScript('files', 'fileactions');
390
		\OCP\Util::addScript('files', 'fileactionsmenu');
391
		\OCP\Util::addScript('files', 'jquery.fileupload');
392
		\OCP\Util::addScript('files_sharing', 'files_drop');
393
394
		if (isset($shareTmpl['folder'])) {
395
			// JS required for folders
396
			\OCP\Util::addStyle('files', 'merged');
397
			\OCP\Util::addScript('files', 'filesummary');
398
			\OCP\Util::addScript('files', 'breadcrumb');
399
			\OCP\Util::addScript('files', 'fileinfomodel');
400
			\OCP\Util::addScript('files', 'newfilemenu');
401
			\OCP\Util::addScript('files', 'files');
402
			\OCP\Util::addScript('files', 'filelist');
403
			\OCP\Util::addScript('files', 'keyboardshortcuts');
404
		}
405
406
		// OpenGraph Support: http://ogp.me/
407
		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
408
		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
409
		\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
410
		\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
411
		\OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
412
		\OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
413
414
		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts');
415
416
		$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
0 ignored issues
show
Deprecated Code introduced by
The class OCP\AppFramework\Http\ContentSecurityPolicy has been deprecated with message: 14.0.0 Use one of our stricter CSP policies

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
417
		$csp->addAllowedFrameDomain('\'self\'');
418
419
		$response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
420
		$response->setHeaderTitle($shareTmpl['filename']);
421
		$response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['displayName']]));
422
		$response->setHeaderActions([
423
			new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0),
424
			new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']),
425
			new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']),
426
			new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['displayName'], $shareTmpl['filename']),
427
		]);
428
429
		$response->setContentSecurityPolicy($csp);
430
431
		$this->emitAccessShareHook($share);
432
433
		return $response;
434
	}
435
436
	/**
437
	 * @PublicPage
438
	 * @NoCSRFRequired
439
	 *
440
	 * @param string $token
441
	 * @param string $files
442
	 * @param string $path
443
	 * @param string $downloadStartSecret
444
	 * @return void|\OCP\AppFramework\Http\Response
445
	 * @throws NotFoundException
446
	 */
447
	public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
448
		\OC_User::setIncognitoMode(true);
449
450
		$share = $this->shareManager->getShareByToken($token);
451
452
		if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
453
			return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
0 ignored issues
show
Documentation introduced by
'Share is read-only' is of type string, but the function expects a array|object.

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...
454
		}
455
456
		$files_list = null;
457
		if (!is_null($files)) { // download selected files
458
			$files_list = json_decode($files);
459
			// in case we get only a single file
460
			if ($files_list === null) {
461
				$files_list = [$files];
462
			}
463
			// Just in case $files is a single int like '1234'
464
			if (!is_array($files_list)) {
465
				$files_list = [$files_list];
466
			}
467
		}
468
469
470
		if (!$this->validateShare($share)) {
471
			throw new NotFoundException();
472
		}
473
474
		$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
475
		$originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
476
477
478
		// Single file share
479
		if ($share->getNode() instanceof \OCP\Files\File) {
480
			// Single file download
481
			$this->singleFileDownloaded($share, $share->getNode());
482
		}
483
		// Directory share
484
		else {
485
			/** @var \OCP\Files\Folder $node */
486
			$node = $share->getNode();
487
488
			// Try to get the path
489
			if ($path !== '') {
490
				try {
491
					$node = $node->get($path);
492
				} catch (NotFoundException $e) {
493
					$this->emitAccessShareHook($share, 404, 'Share not found');
494
					return new NotFoundResponse();
495
				}
496
			}
497
498
			$originalSharePath = $userFolder->getRelativePath($node->getPath());
499
500
			if ($node instanceof \OCP\Files\File) {
501
				// Single file download
502
				$this->singleFileDownloaded($share, $share->getNode());
503
			} else if (!empty($files_list)) {
504
				$this->fileListDownloaded($share, $files_list, $node);
0 ignored issues
show
Compatibility introduced by
$node of type object<OCP\Files\Node> is not a sub-type of object<OCP\Files\Folder>. It seems like you assume a child interface of the interface OCP\Files\Node to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
505
			} else {
506
				// The folder is downloaded
507
				$this->singleFileDownloaded($share, $share->getNode());
508
			}
509
		}
510
511
		/* FIXME: We should do this all nicely in OCP */
512
		OC_Util::tearDownFS();
513
		OC_Util::setupFS($share->getShareOwner());
514
515
		/**
516
		 * this sets a cookie to be able to recognize the start of the download
517
		 * the content must not be longer than 32 characters and must only contain
518
		 * alphanumeric characters
519
		 */
520 View Code Duplication
		if (!empty($downloadStartSecret)
521
			&& !isset($downloadStartSecret[32])
522
			&& preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
523
524
			// FIXME: set on the response once we use an actual app framework response
525
			setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
526
		}
527
528
		$this->emitAccessShareHook($share);
529
530
		$server_params = array( 'head' => $this->request->getMethod() === 'HEAD' );
531
532
		/**
533
		 * Http range requests support
534
		 */
535
		if (isset($_SERVER['HTTP_RANGE'])) {
536
			$server_params['range'] = $this->request->getHeader('Range');
537
		}
538
539
		// download selected files
540
		if (!is_null($files) && $files !== '') {
541
			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
542
			// after dispatching the request which results in a "Cannot modify header information" notice.
543
			OC_Files::get($originalSharePath, $files_list, $server_params);
0 ignored issues
show
Documentation introduced by
$files_list is of type array|null, 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...
544
			exit();
545
		} else {
546
			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
547
			// after dispatching the request which results in a "Cannot modify header information" notice.
548
			OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
549
			exit();
550
		}
551
	}
552
553
	/**
554
	 * create activity for every downloaded file
555
	 *
556
	 * @param Share\IShare $share
557
	 * @param array $files_list
558
	 * @param \OCP\Files\Folder $node
559
	 */
560
	protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
561
		foreach ($files_list as $file) {
562
			$subNode = $node->get($file);
563
			$this->singleFileDownloaded($share, $subNode);
564
		}
565
566
	}
567
568
	/**
569
	 * create activity if a single file was downloaded from a link share
570
	 *
571
	 * @param Share\IShare $share
572
	 */
573
	protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
574
575
		$fileId = $node->getId();
576
577
		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
578
		$userNodeList = $userFolder->getById($fileId);
579
		$userNode = $userNodeList[0];
580
		$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
581
		$userPath = $userFolder->getRelativePath($userNode->getPath());
582
		$ownerPath = $ownerFolder->getRelativePath($node->getPath());
583
584
		$parameters = [$userPath];
585
586
		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
587
			if ($node instanceof \OCP\Files\File) {
588
				$subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
589
			} else {
590
				$subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
591
			}
592
			$parameters[] = $share->getSharedWith();
593
		} else {
594
			if ($node instanceof \OCP\Files\File) {
595
				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
596
			} else {
597
				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
598
			}
599
		}
600
601
		$this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
602
603
		if ($share->getShareOwner() !== $share->getSharedBy()) {
604
			$parameters[0] = $ownerPath;
605
			$this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
606
		}
607
	}
608
609
	/**
610
	 * publish activity
611
	 *
612
	 * @param string $subject
613
	 * @param array $parameters
614
	 * @param string $affectedUser
615
	 * @param int $fileId
616
	 * @param string $filePath
617
	 */
618 View Code Duplication
	protected function publishActivity($subject,
619
										array $parameters,
620
										$affectedUser,
621
										$fileId,
622
										$filePath) {
623
624
		$event = $this->activityManager->generateEvent();
625
		$event->setApp('files_sharing')
626
			->setType('public_links')
627
			->setSubject($subject, $parameters)
628
			->setAffectedUser($affectedUser)
629
			->setObject('files', $fileId, $filePath);
630
		$this->activityManager->publish($event);
631
	}
632
633
634
}
635