Passed
Push — master ( 806169...264f14 )
by Roeland
11:48 queued 12s
created
apps/files_sharing/lib/Controller/ShareController.php 1 patch
Indentation   +623 added lines, -624 removed lines patch added patch discarded remove patch
@@ -78,632 +78,631 @@
 block discarded – undo
78 78
  */
79 79
 class ShareController extends AuthPublicShareController {
80 80
 
81
-	/** @var IConfig */
82
-	protected $config;
83
-	/** @var IUserManager */
84
-	protected $userManager;
85
-	/** @var ILogger */
86
-	protected $logger;
87
-	/** @var \OCP\Activity\IManager */
88
-	protected $activityManager;
89
-	/** @var IPreview */
90
-	protected $previewManager;
91
-	/** @var IRootFolder */
92
-	protected $rootFolder;
93
-	/** @var FederatedShareProvider */
94
-	protected $federatedShareProvider;
95
-	/** @var EventDispatcherInterface */
96
-	protected $eventDispatcher;
97
-	/** @var IL10N */
98
-	protected $l10n;
99
-	/** @var Defaults */
100
-	protected $defaults;
101
-	/** @var ShareManager */
102
-	protected $shareManager;
103
-
104
-	/** @var Share\IShare */
105
-	protected $share;
106
-
107
-	/**
108
-	 * @param string $appName
109
-	 * @param IRequest $request
110
-	 * @param IConfig $config
111
-	 * @param IURLGenerator $urlGenerator
112
-	 * @param IUserManager $userManager
113
-	 * @param ILogger $logger
114
-	 * @param \OCP\Activity\IManager $activityManager
115
-	 * @param \OCP\Share\IManager $shareManager
116
-	 * @param ISession $session
117
-	 * @param IPreview $previewManager
118
-	 * @param IRootFolder $rootFolder
119
-	 * @param FederatedShareProvider $federatedShareProvider
120
-	 * @param EventDispatcherInterface $eventDispatcher
121
-	 * @param IL10N $l10n
122
-	 * @param Defaults $defaults
123
-	 */
124
-	public function __construct(string $appName,
125
-								IRequest $request,
126
-								IConfig $config,
127
-								IURLGenerator $urlGenerator,
128
-								IUserManager $userManager,
129
-								ILogger $logger,
130
-								\OCP\Activity\IManager $activityManager,
131
-								ShareManager $shareManager,
132
-								ISession $session,
133
-								IPreview $previewManager,
134
-								IRootFolder $rootFolder,
135
-								FederatedShareProvider $federatedShareProvider,
136
-								EventDispatcherInterface $eventDispatcher,
137
-								IL10N $l10n,
138
-								Defaults $defaults) {
139
-		parent::__construct($appName, $request, $session, $urlGenerator);
140
-
141
-		$this->config = $config;
142
-		$this->userManager = $userManager;
143
-		$this->logger = $logger;
144
-		$this->activityManager = $activityManager;
145
-		$this->previewManager = $previewManager;
146
-		$this->rootFolder = $rootFolder;
147
-		$this->federatedShareProvider = $federatedShareProvider;
148
-		$this->eventDispatcher = $eventDispatcher;
149
-		$this->l10n = $l10n;
150
-		$this->defaults = $defaults;
151
-		$this->shareManager = $shareManager;
152
-	}
153
-
154
-	/**
155
-	 * @PublicPage
156
-	 * @NoCSRFRequired
157
-	 *
158
-	 * Show the authentication page
159
-	 * The form has to submit to the authenticate method route
160
-	 */
161
-	public function showAuthenticate(): TemplateResponse {
162
-		$templateParameters = ['share' => $this->share];
163
-
164
-		$event = new GenericEvent(null, $templateParameters);
165
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
166
-
167
-		$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
168
-		if ($this->share->getSendPasswordByTalk()) {
169
-			$csp = new ContentSecurityPolicy();
170
-			$csp->addAllowedConnectDomain('*');
171
-			$csp->addAllowedMediaDomain('blob:');
172
-			$response->setContentSecurityPolicy($csp);
173
-		}
174
-
175
-		return $response;
176
-	}
177
-
178
-	/**
179
-	 * The template to show when authentication failed
180
-	 */
181
-	protected function showAuthFailed(): TemplateResponse {
182
-		$templateParameters = ['share' => $this->share, 'wrongpw' => true];
183
-
184
-		$event = new GenericEvent(null, $templateParameters);
185
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
186
-
187
-		$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
188
-		if ($this->share->getSendPasswordByTalk()) {
189
-			$csp = new ContentSecurityPolicy();
190
-			$csp->addAllowedConnectDomain('*');
191
-			$csp->addAllowedMediaDomain('blob:');
192
-			$response->setContentSecurityPolicy($csp);
193
-		}
194
-
195
-		return $response;
196
-	}
197
-
198
-	protected function verifyPassword(string $password): bool {
199
-		return $this->shareManager->checkPassword($this->share, $password);
200
-	}
201
-
202
-	protected function getPasswordHash(): string {
203
-		return $this->share->getPassword();
204
-	}
205
-
206
-	public function isValidToken(): bool {
207
-		try {
208
-			$this->share = $this->shareManager->getShareByToken($this->getToken());
209
-		} catch (ShareNotFound $e) {
210
-			return false;
211
-		}
212
-
213
-		return true;
214
-	}
215
-
216
-	protected function isPasswordProtected(): bool {
217
-		return $this->share->getPassword() !== null;
218
-	}
219
-
220
-	protected function authSucceeded() {
221
-		// For share this was always set so it is still used in other apps
222
-		$this->session->set('public_link_authenticated', (string)$this->share->getId());
223
-	}
224
-
225
-	protected function authFailed() {
226
-		$this->emitAccessShareHook($this->share, 403, 'Wrong password');
227
-	}
228
-
229
-	/**
230
-	 * throws hooks when a share is attempted to be accessed
231
-	 *
232
-	 * @param \OCP\Share\IShare|string $share the Share instance if available,
233
-	 * otherwise token
234
-	 * @param int $errorCode
235
-	 * @param string $errorMessage
236
-	 * @throws \OC\HintException
237
-	 * @throws \OC\ServerNotAvailableException
238
-	 */
239
-	protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
240
-		$itemType = $itemSource = $uidOwner = '';
241
-		$token = $share;
242
-		$exception = null;
243
-		if($share instanceof \OCP\Share\IShare) {
244
-			try {
245
-				$token = $share->getToken();
246
-				$uidOwner = $share->getSharedBy();
247
-				$itemType = $share->getNodeType();
248
-				$itemSource = $share->getNodeId();
249
-			} catch (\Exception $e) {
250
-				// we log what we know and pass on the exception afterwards
251
-				$exception = $e;
252
-			}
253
-		}
254
-		\OC_Hook::emit(Share::class, 'share_link_access', [
255
-			'itemType' => $itemType,
256
-			'itemSource' => $itemSource,
257
-			'uidOwner' => $uidOwner,
258
-			'token' => $token,
259
-			'errorCode' => $errorCode,
260
-			'errorMessage' => $errorMessage,
261
-		]);
262
-		if(!is_null($exception)) {
263
-			throw $exception;
264
-		}
265
-	}
266
-
267
-	/**
268
-	 * Validate the permissions of the share
269
-	 *
270
-	 * @param Share\IShare $share
271
-	 * @return bool
272
-	 */
273
-	private function validateShare(\OCP\Share\IShare $share) {
274
-		// If the owner is disabled no access to the linke is granted
275
-		$owner = $this->userManager->get($share->getShareOwner());
276
-		if ($owner === null || !$owner->isEnabled()) {
277
-			return false;
278
-		}
279
-
280
-		// If the initiator of the share is disabled no access is granted
281
-		$initiator = $this->userManager->get($share->getSharedBy());
282
-		if ($initiator === null || !$initiator->isEnabled()) {
283
-			return false;
284
-		}
285
-
286
-		return $share->getNode()->isReadable() && $share->getNode()->isShareable();
287
-	}
288
-
289
-	/**
290
-	 * @PublicPage
291
-	 * @NoCSRFRequired
292
-	 *
293
-
294
-	 * @param string $path
295
-	 * @return TemplateResponse
296
-	 * @throws NotFoundException
297
-	 * @throws \Exception
298
-	 */
299
-	public function showShare($path = ''): TemplateResponse {
300
-		\OC_User::setIncognitoMode(true);
301
-
302
-		// Check whether share exists
303
-		try {
304
-			$share = $this->shareManager->getShareByToken($this->getToken());
305
-		} catch (ShareNotFound $e) {
306
-			$this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
307
-			throw new NotFoundException();
308
-		}
309
-
310
-		if (!$this->validateShare($share)) {
311
-			throw new NotFoundException();
312
-		}
313
-
314
-		$shareNode = $share->getNode();
315
-
316
-		// We can't get the path of a file share
317
-		try {
318
-			if ($shareNode instanceof \OCP\Files\File && $path !== '') {
319
-				$this->emitAccessShareHook($share, 404, 'Share not found');
320
-				throw new NotFoundException();
321
-			}
322
-		} catch (\Exception $e) {
323
-			$this->emitAccessShareHook($share, 404, 'Share not found');
324
-			throw $e;
325
-		}
326
-
327
-		$shareTmpl = [];
328
-		$shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
329
-		$shareTmpl['owner'] = $share->getShareOwner();
330
-		$shareTmpl['filename'] = $shareNode->getName();
331
-		$shareTmpl['directory_path'] = $share->getTarget();
332
-		$shareTmpl['note'] = $share->getNote();
333
-		$shareTmpl['mimetype'] = $shareNode->getMimetype();
334
-		$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
335
-		$shareTmpl['dirToken'] = $this->getToken();
336
-		$shareTmpl['sharingToken'] = $this->getToken();
337
-		$shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
338
-		$shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
339
-		$shareTmpl['dir'] = '';
340
-		$shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
341
-		$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
342
-		$shareTmpl['hideDownload'] = $share->getHideDownload();
343
-
344
-		$hideFileList = false;
345
-
346
-		if ($shareNode instanceof \OCP\Files\Folder) {
347
-
348
-			$shareIsFolder = true;
349
-
350
-			try {
351
-				$folderNode = $shareNode->get($path);
352
-			} catch (\OCP\Files\NotFoundException $e) {
353
-				$this->emitAccessShareHook($share, 404, 'Share not found');
354
-				throw new NotFoundException();
355
-			}
356
-
357
-			$shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
358
-
359
-			/*
81
+    /** @var IConfig */
82
+    protected $config;
83
+    /** @var IUserManager */
84
+    protected $userManager;
85
+    /** @var ILogger */
86
+    protected $logger;
87
+    /** @var \OCP\Activity\IManager */
88
+    protected $activityManager;
89
+    /** @var IPreview */
90
+    protected $previewManager;
91
+    /** @var IRootFolder */
92
+    protected $rootFolder;
93
+    /** @var FederatedShareProvider */
94
+    protected $federatedShareProvider;
95
+    /** @var EventDispatcherInterface */
96
+    protected $eventDispatcher;
97
+    /** @var IL10N */
98
+    protected $l10n;
99
+    /** @var Defaults */
100
+    protected $defaults;
101
+    /** @var ShareManager */
102
+    protected $shareManager;
103
+
104
+    /** @var Share\IShare */
105
+    protected $share;
106
+
107
+    /**
108
+     * @param string $appName
109
+     * @param IRequest $request
110
+     * @param IConfig $config
111
+     * @param IURLGenerator $urlGenerator
112
+     * @param IUserManager $userManager
113
+     * @param ILogger $logger
114
+     * @param \OCP\Activity\IManager $activityManager
115
+     * @param \OCP\Share\IManager $shareManager
116
+     * @param ISession $session
117
+     * @param IPreview $previewManager
118
+     * @param IRootFolder $rootFolder
119
+     * @param FederatedShareProvider $federatedShareProvider
120
+     * @param EventDispatcherInterface $eventDispatcher
121
+     * @param IL10N $l10n
122
+     * @param Defaults $defaults
123
+     */
124
+    public function __construct(string $appName,
125
+                                IRequest $request,
126
+                                IConfig $config,
127
+                                IURLGenerator $urlGenerator,
128
+                                IUserManager $userManager,
129
+                                ILogger $logger,
130
+                                \OCP\Activity\IManager $activityManager,
131
+                                ShareManager $shareManager,
132
+                                ISession $session,
133
+                                IPreview $previewManager,
134
+                                IRootFolder $rootFolder,
135
+                                FederatedShareProvider $federatedShareProvider,
136
+                                EventDispatcherInterface $eventDispatcher,
137
+                                IL10N $l10n,
138
+                                Defaults $defaults) {
139
+        parent::__construct($appName, $request, $session, $urlGenerator);
140
+
141
+        $this->config = $config;
142
+        $this->userManager = $userManager;
143
+        $this->logger = $logger;
144
+        $this->activityManager = $activityManager;
145
+        $this->previewManager = $previewManager;
146
+        $this->rootFolder = $rootFolder;
147
+        $this->federatedShareProvider = $federatedShareProvider;
148
+        $this->eventDispatcher = $eventDispatcher;
149
+        $this->l10n = $l10n;
150
+        $this->defaults = $defaults;
151
+        $this->shareManager = $shareManager;
152
+    }
153
+
154
+    /**
155
+     * @PublicPage
156
+     * @NoCSRFRequired
157
+     *
158
+     * Show the authentication page
159
+     * The form has to submit to the authenticate method route
160
+     */
161
+    public function showAuthenticate(): TemplateResponse {
162
+        $templateParameters = ['share' => $this->share];
163
+
164
+        $event = new GenericEvent(null, $templateParameters);
165
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
166
+
167
+        $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
168
+        if ($this->share->getSendPasswordByTalk()) {
169
+            $csp = new ContentSecurityPolicy();
170
+            $csp->addAllowedConnectDomain('*');
171
+            $csp->addAllowedMediaDomain('blob:');
172
+            $response->setContentSecurityPolicy($csp);
173
+        }
174
+
175
+        return $response;
176
+    }
177
+
178
+    /**
179
+     * The template to show when authentication failed
180
+     */
181
+    protected function showAuthFailed(): TemplateResponse {
182
+        $templateParameters = ['share' => $this->share, 'wrongpw' => true];
183
+
184
+        $event = new GenericEvent(null, $templateParameters);
185
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
186
+
187
+        $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
188
+        if ($this->share->getSendPasswordByTalk()) {
189
+            $csp = new ContentSecurityPolicy();
190
+            $csp->addAllowedConnectDomain('*');
191
+            $csp->addAllowedMediaDomain('blob:');
192
+            $response->setContentSecurityPolicy($csp);
193
+        }
194
+
195
+        return $response;
196
+    }
197
+
198
+    protected function verifyPassword(string $password): bool {
199
+        return $this->shareManager->checkPassword($this->share, $password);
200
+    }
201
+
202
+    protected function getPasswordHash(): string {
203
+        return $this->share->getPassword();
204
+    }
205
+
206
+    public function isValidToken(): bool {
207
+        try {
208
+            $this->share = $this->shareManager->getShareByToken($this->getToken());
209
+        } catch (ShareNotFound $e) {
210
+            return false;
211
+        }
212
+
213
+        return true;
214
+    }
215
+
216
+    protected function isPasswordProtected(): bool {
217
+        return $this->share->getPassword() !== null;
218
+    }
219
+
220
+    protected function authSucceeded() {
221
+        // For share this was always set so it is still used in other apps
222
+        $this->session->set('public_link_authenticated', (string)$this->share->getId());
223
+    }
224
+
225
+    protected function authFailed() {
226
+        $this->emitAccessShareHook($this->share, 403, 'Wrong password');
227
+    }
228
+
229
+    /**
230
+     * throws hooks when a share is attempted to be accessed
231
+     *
232
+     * @param \OCP\Share\IShare|string $share the Share instance if available,
233
+     * otherwise token
234
+     * @param int $errorCode
235
+     * @param string $errorMessage
236
+     * @throws \OC\HintException
237
+     * @throws \OC\ServerNotAvailableException
238
+     */
239
+    protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
240
+        $itemType = $itemSource = $uidOwner = '';
241
+        $token = $share;
242
+        $exception = null;
243
+        if($share instanceof \OCP\Share\IShare) {
244
+            try {
245
+                $token = $share->getToken();
246
+                $uidOwner = $share->getSharedBy();
247
+                $itemType = $share->getNodeType();
248
+                $itemSource = $share->getNodeId();
249
+            } catch (\Exception $e) {
250
+                // we log what we know and pass on the exception afterwards
251
+                $exception = $e;
252
+            }
253
+        }
254
+        \OC_Hook::emit(Share::class, 'share_link_access', [
255
+            'itemType' => $itemType,
256
+            'itemSource' => $itemSource,
257
+            'uidOwner' => $uidOwner,
258
+            'token' => $token,
259
+            'errorCode' => $errorCode,
260
+            'errorMessage' => $errorMessage,
261
+        ]);
262
+        if(!is_null($exception)) {
263
+            throw $exception;
264
+        }
265
+    }
266
+
267
+    /**
268
+     * Validate the permissions of the share
269
+     *
270
+     * @param Share\IShare $share
271
+     * @return bool
272
+     */
273
+    private function validateShare(\OCP\Share\IShare $share) {
274
+        // If the owner is disabled no access to the linke is granted
275
+        $owner = $this->userManager->get($share->getShareOwner());
276
+        if ($owner === null || !$owner->isEnabled()) {
277
+            return false;
278
+        }
279
+
280
+        // If the initiator of the share is disabled no access is granted
281
+        $initiator = $this->userManager->get($share->getSharedBy());
282
+        if ($initiator === null || !$initiator->isEnabled()) {
283
+            return false;
284
+        }
285
+
286
+        return $share->getNode()->isReadable() && $share->getNode()->isShareable();
287
+    }
288
+
289
+    /**
290
+     * @PublicPage
291
+     * @NoCSRFRequired
292
+     *
293
+     * @param string $path
294
+     * @return TemplateResponse
295
+     * @throws NotFoundException
296
+     * @throws \Exception
297
+     */
298
+    public function showShare($path = ''): TemplateResponse {
299
+        \OC_User::setIncognitoMode(true);
300
+
301
+        // Check whether share exists
302
+        try {
303
+            $share = $this->shareManager->getShareByToken($this->getToken());
304
+        } catch (ShareNotFound $e) {
305
+            $this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
306
+            throw new NotFoundException();
307
+        }
308
+
309
+        if (!$this->validateShare($share)) {
310
+            throw new NotFoundException();
311
+        }
312
+
313
+        $shareNode = $share->getNode();
314
+
315
+        // We can't get the path of a file share
316
+        try {
317
+            if ($shareNode instanceof \OCP\Files\File && $path !== '') {
318
+                $this->emitAccessShareHook($share, 404, 'Share not found');
319
+                throw new NotFoundException();
320
+            }
321
+        } catch (\Exception $e) {
322
+            $this->emitAccessShareHook($share, 404, 'Share not found');
323
+            throw $e;
324
+        }
325
+
326
+        $shareTmpl = [];
327
+        $shareTmpl['displayName'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
328
+        $shareTmpl['owner'] = $share->getShareOwner();
329
+        $shareTmpl['filename'] = $shareNode->getName();
330
+        $shareTmpl['directory_path'] = $share->getTarget();
331
+        $shareTmpl['note'] = $share->getNote();
332
+        $shareTmpl['mimetype'] = $shareNode->getMimetype();
333
+        $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
334
+        $shareTmpl['dirToken'] = $this->getToken();
335
+        $shareTmpl['sharingToken'] = $this->getToken();
336
+        $shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
337
+        $shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
338
+        $shareTmpl['dir'] = '';
339
+        $shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
340
+        $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
341
+        $shareTmpl['hideDownload'] = $share->getHideDownload();
342
+
343
+        $hideFileList = false;
344
+
345
+        if ($shareNode instanceof \OCP\Files\Folder) {
346
+
347
+            $shareIsFolder = true;
348
+
349
+            try {
350
+                $folderNode = $shareNode->get($path);
351
+            } catch (\OCP\Files\NotFoundException $e) {
352
+                $this->emitAccessShareHook($share, 404, 'Share not found');
353
+                throw new NotFoundException();
354
+            }
355
+
356
+            $shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
357
+
358
+            /*
360 359
 			 * The OC_Util methods require a view. This just uses the node API
361 360
 			 */
362
-			$freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
363
-			if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
364
-				$freeSpace = max($freeSpace, 0);
365
-			} else {
366
-				$freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
367
-			}
368
-
369
-			$hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
370
-			$maxUploadFilesize = $freeSpace;
371
-
372
-			$folder = new Template('files', 'list', '');
373
-			$folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
374
-			$folder->assign('dirToken', $this->getToken());
375
-			$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
376
-			$folder->assign('isPublic', true);
377
-			$folder->assign('hideFileList', $hideFileList);
378
-			$folder->assign('publicUploadEnabled', 'no');
379
-			// default to list view
380
-			$folder->assign('showgridview', false);
381
-			$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
382
-			$folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
383
-			$folder->assign('freeSpace', $freeSpace);
384
-			$folder->assign('usedSpacePercent', 0);
385
-			$folder->assign('trash', false);
386
-			$shareTmpl['folder'] = $folder->fetchPage();
387
-		} else {
388
-			$shareIsFolder = false;
389
-		}
390
-
391
-		// default to list view
392
-		$shareTmpl['showgridview'] = false;
393
-
394
-		$shareTmpl['hideFileList'] = $hideFileList;
395
-		$shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
396
-		$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $this->getToken()]);
397
-		$shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
398
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
399
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
400
-		$shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
401
-		$shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
402
-		$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
403
-		$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
404
-
405
-		if ($shareTmpl['previewSupported']) {
406
-			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
407
-				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
408
-			$ogPreview = $shareTmpl['previewImage'];
409
-
410
-			// We just have direct previews for image files
411
-			if ($shareNode->getMimePart() === 'image') {
412
-				$shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
413
-
414
-				$ogPreview = $shareTmpl['previewURL'];
415
-
416
-				//Whatapp is kind of picky about their size requirements
417
-				if ($this->request->isUserAgent(['/^WhatsApp/'])) {
418
-					$ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
419
-						'token' => $this->getToken(),
420
-						'x' => 256,
421
-						'y' => 256,
422
-						'a' => true,
423
-					]);
424
-				}
425
-			}
426
-		} else {
427
-			$shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
428
-			$ogPreview = $shareTmpl['previewImage'];
429
-		}
430
-
431
-		// Load files we need
432
-		\OCP\Util::addScript('files', 'semaphore');
433
-		\OCP\Util::addScript('files', 'file-upload');
434
-		\OCP\Util::addStyle('files_sharing', 'publicView');
435
-		\OCP\Util::addScript('files_sharing', 'public');
436
-		\OCP\Util::addScript('files_sharing', 'templates');
437
-		\OCP\Util::addScript('files', 'fileactions');
438
-		\OCP\Util::addScript('files', 'fileactionsmenu');
439
-		\OCP\Util::addScript('files', 'jquery.fileupload');
440
-		\OCP\Util::addScript('files_sharing', 'files_drop');
441
-
442
-		if (isset($shareTmpl['folder'])) {
443
-			// JS required for folders
444
-			\OCP\Util::addStyle('files', 'merged');
445
-			\OCP\Util::addScript('files', 'filesummary');
446
-			\OCP\Util::addScript('files', 'templates');
447
-			\OCP\Util::addScript('files', 'breadcrumb');
448
-			\OCP\Util::addScript('files', 'fileinfomodel');
449
-			\OCP\Util::addScript('files', 'newfilemenu');
450
-			\OCP\Util::addScript('files', 'files');
451
-			\OCP\Util::addScript('files', 'filemultiselectmenu');
452
-			\OCP\Util::addScript('files', 'filelist');
453
-			\OCP\Util::addScript('files', 'keyboardshortcuts');
454
-			\OCP\Util::addScript('files', 'operationprogressbar');
455
-		}
456
-
457
-		// OpenGraph Support: http://ogp.me/
458
-		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
459
-		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
460
-		\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
461
-		\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
462
-		\OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
463
-		\OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
464
-
465
-		$event = new GenericEvent(null, ['share' => $share]);
466
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts', $event);
467
-
468
-		$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
469
-		$csp->addAllowedFrameDomain('\'self\'');
470
-
471
-		$response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
472
-		$response->setHeaderTitle($shareTmpl['filename']);
473
-		$response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['displayName']]));
474
-
475
-		$isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;
476
-
477
-		if ($isNoneFileDropFolder && !$share->getHideDownload()) {
478
-			\OCP\Util::addScript('files_sharing', 'public_note');
479
-
480
-			$downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
481
-			$downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
482
-			$download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
483
-			$downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
484
-			$directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
485
-			$externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['displayName'], $shareTmpl['filename']);
486
-
487
-			$responseComposer = [];
488
-
489
-			if ($shareIsFolder) {
490
-				$responseComposer[] = $downloadAllWhite;
491
-				$responseComposer[] = $downloadAll;
492
-			} else {
493
-				$responseComposer[] = $downloadWhite;
494
-				$responseComposer[] = $download;
495
-			}
496
-			$responseComposer[] = $directLink;
497
-			if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
498
-				$responseComposer[] = $externalShare;
499
-			}
500
-
501
-			$response->setHeaderActions($responseComposer);
502
-		}
503
-
504
-		$response->setContentSecurityPolicy($csp);
505
-
506
-		$this->emitAccessShareHook($share);
507
-
508
-		return $response;
509
-	}
510
-
511
-	/**
512
-	 * @PublicPage
513
-	 * @NoCSRFRequired
514
-	 *
515
-	 * @param string $token
516
-	 * @param string $files
517
-	 * @param string $path
518
-	 * @param string $downloadStartSecret
519
-	 * @return void|\OCP\AppFramework\Http\Response
520
-	 * @throws NotFoundException
521
-	 */
522
-	public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
523
-		\OC_User::setIncognitoMode(true);
524
-
525
-		$share = $this->shareManager->getShareByToken($token);
526
-
527
-		if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
528
-			return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
529
-		}
530
-
531
-		$files_list = null;
532
-		if (!is_null($files)) { // download selected files
533
-			$files_list = json_decode($files);
534
-			// in case we get only a single file
535
-			if ($files_list === null) {
536
-				$files_list = [$files];
537
-			}
538
-			// Just in case $files is a single int like '1234'
539
-			if (!is_array($files_list)) {
540
-				$files_list = [$files_list];
541
-			}
542
-		}
543
-
544
-
545
-		if (!$this->validateShare($share)) {
546
-			throw new NotFoundException();
547
-		}
548
-
549
-		$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
550
-		$originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
551
-
552
-
553
-		// Single file share
554
-		if ($share->getNode() instanceof \OCP\Files\File) {
555
-			// Single file download
556
-			$this->singleFileDownloaded($share, $share->getNode());
557
-		}
558
-		// Directory share
559
-		else {
560
-			/** @var \OCP\Files\Folder $node */
561
-			$node = $share->getNode();
562
-
563
-			// Try to get the path
564
-			if ($path !== '') {
565
-				try {
566
-					$node = $node->get($path);
567
-				} catch (NotFoundException $e) {
568
-					$this->emitAccessShareHook($share, 404, 'Share not found');
569
-					return new NotFoundResponse();
570
-				}
571
-			}
572
-
573
-			$originalSharePath = $userFolder->getRelativePath($node->getPath());
574
-
575
-			if ($node instanceof \OCP\Files\File) {
576
-				// Single file download
577
-				$this->singleFileDownloaded($share, $share->getNode());
578
-			} else if (!empty($files_list)) {
579
-				$this->fileListDownloaded($share, $files_list, $node);
580
-			} else {
581
-				// The folder is downloaded
582
-				$this->singleFileDownloaded($share, $share->getNode());
583
-			}
584
-		}
585
-
586
-		/* FIXME: We should do this all nicely in OCP */
587
-		OC_Util::tearDownFS();
588
-		OC_Util::setupFS($share->getShareOwner());
589
-
590
-		/**
591
-		 * this sets a cookie to be able to recognize the start of the download
592
-		 * the content must not be longer than 32 characters and must only contain
593
-		 * alphanumeric characters
594
-		 */
595
-		if (!empty($downloadStartSecret)
596
-			&& !isset($downloadStartSecret[32])
597
-			&& preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
598
-
599
-			// FIXME: set on the response once we use an actual app framework response
600
-			setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
601
-		}
602
-
603
-		$this->emitAccessShareHook($share);
604
-
605
-		$server_params = array( 'head' => $this->request->getMethod() === 'HEAD' );
606
-
607
-		/**
608
-		 * Http range requests support
609
-		 */
610
-		if (isset($_SERVER['HTTP_RANGE'])) {
611
-			$server_params['range'] = $this->request->getHeader('Range');
612
-		}
613
-
614
-		// download selected files
615
-		if (!is_null($files) && $files !== '') {
616
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
617
-			// after dispatching the request which results in a "Cannot modify header information" notice.
618
-			OC_Files::get($originalSharePath, $files_list, $server_params);
619
-			exit();
620
-		} else {
621
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
622
-			// after dispatching the request which results in a "Cannot modify header information" notice.
623
-			OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
624
-			exit();
625
-		}
626
-	}
627
-
628
-	/**
629
-	 * create activity for every downloaded file
630
-	 *
631
-	 * @param Share\IShare $share
632
-	 * @param array $files_list
633
-	 * @param \OCP\Files\Folder $node
634
-	 */
635
-	protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
636
-		foreach ($files_list as $file) {
637
-			$subNode = $node->get($file);
638
-			$this->singleFileDownloaded($share, $subNode);
639
-		}
640
-
641
-	}
642
-
643
-	/**
644
-	 * create activity if a single file was downloaded from a link share
645
-	 *
646
-	 * @param Share\IShare $share
647
-	 */
648
-	protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
649
-
650
-		$fileId = $node->getId();
651
-
652
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
653
-		$userNodeList = $userFolder->getById($fileId);
654
-		$userNode = $userNodeList[0];
655
-		$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
656
-		$userPath = $userFolder->getRelativePath($userNode->getPath());
657
-		$ownerPath = $ownerFolder->getRelativePath($node->getPath());
658
-
659
-		$parameters = [$userPath];
660
-
661
-		if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
662
-			if ($node instanceof \OCP\Files\File) {
663
-				$subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
664
-			} else {
665
-				$subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
666
-			}
667
-			$parameters[] = $share->getSharedWith();
668
-		} else {
669
-			if ($node instanceof \OCP\Files\File) {
670
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
671
-			} else {
672
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
673
-			}
674
-		}
675
-
676
-		$this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
677
-
678
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
679
-			$parameters[0] = $ownerPath;
680
-			$this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
681
-		}
682
-	}
683
-
684
-	/**
685
-	 * publish activity
686
-	 *
687
-	 * @param string $subject
688
-	 * @param array $parameters
689
-	 * @param string $affectedUser
690
-	 * @param int $fileId
691
-	 * @param string $filePath
692
-	 */
693
-	protected function publishActivity($subject,
694
-										array $parameters,
695
-										$affectedUser,
696
-										$fileId,
697
-										$filePath) {
698
-
699
-		$event = $this->activityManager->generateEvent();
700
-		$event->setApp('files_sharing')
701
-			->setType('public_links')
702
-			->setSubject($subject, $parameters)
703
-			->setAffectedUser($affectedUser)
704
-			->setObject('files', $fileId, $filePath);
705
-		$this->activityManager->publish($event);
706
-	}
361
+            $freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
362
+            if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
363
+                $freeSpace = max($freeSpace, 0);
364
+            } else {
365
+                $freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
366
+            }
367
+
368
+            $hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
369
+            $maxUploadFilesize = $freeSpace;
370
+
371
+            $folder = new Template('files', 'list', '');
372
+            $folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
373
+            $folder->assign('dirToken', $this->getToken());
374
+            $folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
375
+            $folder->assign('isPublic', true);
376
+            $folder->assign('hideFileList', $hideFileList);
377
+            $folder->assign('publicUploadEnabled', 'no');
378
+            // default to list view
379
+            $folder->assign('showgridview', false);
380
+            $folder->assign('uploadMaxFilesize', $maxUploadFilesize);
381
+            $folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
382
+            $folder->assign('freeSpace', $freeSpace);
383
+            $folder->assign('usedSpacePercent', 0);
384
+            $folder->assign('trash', false);
385
+            $shareTmpl['folder'] = $folder->fetchPage();
386
+        } else {
387
+            $shareIsFolder = false;
388
+        }
389
+
390
+        // default to list view
391
+        $shareTmpl['showgridview'] = false;
392
+
393
+        $shareTmpl['hideFileList'] = $hideFileList;
394
+        $shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
395
+        $shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $this->getToken()]);
396
+        $shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
397
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
398
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
399
+        $shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
400
+        $shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
401
+        $shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
402
+        $shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
403
+
404
+        if ($shareTmpl['previewSupported']) {
405
+            $shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute( 'files_sharing.PublicPreview.getPreview',
406
+                ['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
407
+            $ogPreview = $shareTmpl['previewImage'];
408
+
409
+            // We just have direct previews for image files
410
+            if ($shareNode->getMimePart() === 'image') {
411
+                $shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
412
+
413
+                $ogPreview = $shareTmpl['previewURL'];
414
+
415
+                //Whatapp is kind of picky about their size requirements
416
+                if ($this->request->isUserAgent(['/^WhatsApp/'])) {
417
+                    $ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
418
+                        'token' => $this->getToken(),
419
+                        'x' => 256,
420
+                        'y' => 256,
421
+                        'a' => true,
422
+                    ]);
423
+                }
424
+            }
425
+        } else {
426
+            $shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
427
+            $ogPreview = $shareTmpl['previewImage'];
428
+        }
429
+
430
+        // Load files we need
431
+        \OCP\Util::addScript('files', 'semaphore');
432
+        \OCP\Util::addScript('files', 'file-upload');
433
+        \OCP\Util::addStyle('files_sharing', 'publicView');
434
+        \OCP\Util::addScript('files_sharing', 'public');
435
+        \OCP\Util::addScript('files_sharing', 'templates');
436
+        \OCP\Util::addScript('files', 'fileactions');
437
+        \OCP\Util::addScript('files', 'fileactionsmenu');
438
+        \OCP\Util::addScript('files', 'jquery.fileupload');
439
+        \OCP\Util::addScript('files_sharing', 'files_drop');
440
+
441
+        if (isset($shareTmpl['folder'])) {
442
+            // JS required for folders
443
+            \OCP\Util::addStyle('files', 'merged');
444
+            \OCP\Util::addScript('files', 'filesummary');
445
+            \OCP\Util::addScript('files', 'templates');
446
+            \OCP\Util::addScript('files', 'breadcrumb');
447
+            \OCP\Util::addScript('files', 'fileinfomodel');
448
+            \OCP\Util::addScript('files', 'newfilemenu');
449
+            \OCP\Util::addScript('files', 'files');
450
+            \OCP\Util::addScript('files', 'filemultiselectmenu');
451
+            \OCP\Util::addScript('files', 'filelist');
452
+            \OCP\Util::addScript('files', 'keyboardshortcuts');
453
+            \OCP\Util::addScript('files', 'operationprogressbar');
454
+        }
455
+
456
+        // OpenGraph Support: http://ogp.me/
457
+        \OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
458
+        \OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
459
+        \OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
460
+        \OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
461
+        \OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
462
+        \OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
463
+
464
+        $event = new GenericEvent(null, ['share' => $share]);
465
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts', $event);
466
+
467
+        $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
468
+        $csp->addAllowedFrameDomain('\'self\'');
469
+
470
+        $response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
471
+        $response->setHeaderTitle($shareTmpl['filename']);
472
+        $response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['displayName']]));
473
+
474
+        $isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;
475
+
476
+        if ($isNoneFileDropFolder && !$share->getHideDownload()) {
477
+            \OCP\Util::addScript('files_sharing', 'public_note');
478
+
479
+            $downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
480
+            $downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
481
+            $download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
482
+            $downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
483
+            $directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
484
+            $externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['displayName'], $shareTmpl['filename']);
485
+
486
+            $responseComposer = [];
487
+
488
+            if ($shareIsFolder) {
489
+                $responseComposer[] = $downloadAllWhite;
490
+                $responseComposer[] = $downloadAll;
491
+            } else {
492
+                $responseComposer[] = $downloadWhite;
493
+                $responseComposer[] = $download;
494
+            }
495
+            $responseComposer[] = $directLink;
496
+            if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
497
+                $responseComposer[] = $externalShare;
498
+            }
499
+
500
+            $response->setHeaderActions($responseComposer);
501
+        }
502
+
503
+        $response->setContentSecurityPolicy($csp);
504
+
505
+        $this->emitAccessShareHook($share);
506
+
507
+        return $response;
508
+    }
509
+
510
+    /**
511
+     * @PublicPage
512
+     * @NoCSRFRequired
513
+     *
514
+     * @param string $token
515
+     * @param string $files
516
+     * @param string $path
517
+     * @param string $downloadStartSecret
518
+     * @return void|\OCP\AppFramework\Http\Response
519
+     * @throws NotFoundException
520
+     */
521
+    public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
522
+        \OC_User::setIncognitoMode(true);
523
+
524
+        $share = $this->shareManager->getShareByToken($token);
525
+
526
+        if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
527
+            return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
528
+        }
529
+
530
+        $files_list = null;
531
+        if (!is_null($files)) { // download selected files
532
+            $files_list = json_decode($files);
533
+            // in case we get only a single file
534
+            if ($files_list === null) {
535
+                $files_list = [$files];
536
+            }
537
+            // Just in case $files is a single int like '1234'
538
+            if (!is_array($files_list)) {
539
+                $files_list = [$files_list];
540
+            }
541
+        }
542
+
543
+
544
+        if (!$this->validateShare($share)) {
545
+            throw new NotFoundException();
546
+        }
547
+
548
+        $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
549
+        $originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
550
+
551
+
552
+        // Single file share
553
+        if ($share->getNode() instanceof \OCP\Files\File) {
554
+            // Single file download
555
+            $this->singleFileDownloaded($share, $share->getNode());
556
+        }
557
+        // Directory share
558
+        else {
559
+            /** @var \OCP\Files\Folder $node */
560
+            $node = $share->getNode();
561
+
562
+            // Try to get the path
563
+            if ($path !== '') {
564
+                try {
565
+                    $node = $node->get($path);
566
+                } catch (NotFoundException $e) {
567
+                    $this->emitAccessShareHook($share, 404, 'Share not found');
568
+                    return new NotFoundResponse();
569
+                }
570
+            }
571
+
572
+            $originalSharePath = $userFolder->getRelativePath($node->getPath());
573
+
574
+            if ($node instanceof \OCP\Files\File) {
575
+                // Single file download
576
+                $this->singleFileDownloaded($share, $share->getNode());
577
+            } else if (!empty($files_list)) {
578
+                $this->fileListDownloaded($share, $files_list, $node);
579
+            } else {
580
+                // The folder is downloaded
581
+                $this->singleFileDownloaded($share, $share->getNode());
582
+            }
583
+        }
584
+
585
+        /* FIXME: We should do this all nicely in OCP */
586
+        OC_Util::tearDownFS();
587
+        OC_Util::setupFS($share->getShareOwner());
588
+
589
+        /**
590
+         * this sets a cookie to be able to recognize the start of the download
591
+         * the content must not be longer than 32 characters and must only contain
592
+         * alphanumeric characters
593
+         */
594
+        if (!empty($downloadStartSecret)
595
+            && !isset($downloadStartSecret[32])
596
+            && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
597
+
598
+            // FIXME: set on the response once we use an actual app framework response
599
+            setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
600
+        }
601
+
602
+        $this->emitAccessShareHook($share);
603
+
604
+        $server_params = array( 'head' => $this->request->getMethod() === 'HEAD' );
605
+
606
+        /**
607
+         * Http range requests support
608
+         */
609
+        if (isset($_SERVER['HTTP_RANGE'])) {
610
+            $server_params['range'] = $this->request->getHeader('Range');
611
+        }
612
+
613
+        // download selected files
614
+        if (!is_null($files) && $files !== '') {
615
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
616
+            // after dispatching the request which results in a "Cannot modify header information" notice.
617
+            OC_Files::get($originalSharePath, $files_list, $server_params);
618
+            exit();
619
+        } else {
620
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
621
+            // after dispatching the request which results in a "Cannot modify header information" notice.
622
+            OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
623
+            exit();
624
+        }
625
+    }
626
+
627
+    /**
628
+     * create activity for every downloaded file
629
+     *
630
+     * @param Share\IShare $share
631
+     * @param array $files_list
632
+     * @param \OCP\Files\Folder $node
633
+     */
634
+    protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
635
+        foreach ($files_list as $file) {
636
+            $subNode = $node->get($file);
637
+            $this->singleFileDownloaded($share, $subNode);
638
+        }
639
+
640
+    }
641
+
642
+    /**
643
+     * create activity if a single file was downloaded from a link share
644
+     *
645
+     * @param Share\IShare $share
646
+     */
647
+    protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
648
+
649
+        $fileId = $node->getId();
650
+
651
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
652
+        $userNodeList = $userFolder->getById($fileId);
653
+        $userNode = $userNodeList[0];
654
+        $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
655
+        $userPath = $userFolder->getRelativePath($userNode->getPath());
656
+        $ownerPath = $ownerFolder->getRelativePath($node->getPath());
657
+
658
+        $parameters = [$userPath];
659
+
660
+        if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
661
+            if ($node instanceof \OCP\Files\File) {
662
+                $subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
663
+            } else {
664
+                $subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
665
+            }
666
+            $parameters[] = $share->getSharedWith();
667
+        } else {
668
+            if ($node instanceof \OCP\Files\File) {
669
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
670
+            } else {
671
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
672
+            }
673
+        }
674
+
675
+        $this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
676
+
677
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
678
+            $parameters[0] = $ownerPath;
679
+            $this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
680
+        }
681
+    }
682
+
683
+    /**
684
+     * publish activity
685
+     *
686
+     * @param string $subject
687
+     * @param array $parameters
688
+     * @param string $affectedUser
689
+     * @param int $fileId
690
+     * @param string $filePath
691
+     */
692
+    protected function publishActivity($subject,
693
+                                        array $parameters,
694
+                                        $affectedUser,
695
+                                        $fileId,
696
+                                        $filePath) {
697
+
698
+        $event = $this->activityManager->generateEvent();
699
+        $event->setApp('files_sharing')
700
+            ->setType('public_links')
701
+            ->setSubject($subject, $parameters)
702
+            ->setAffectedUser($affectedUser)
703
+            ->setObject('files', $fileId, $filePath);
704
+        $this->activityManager->publish($event);
705
+    }
707 706
 
708 707
 
709 708
 }
Please login to merge, or discard this patch.