Passed
Push — master ( 72e6ca...592cc0 )
by John
12:30 queued 11s
created

AvatarController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
dl 0
loc 22
rs 9.9332
c 1
b 0
f 0
cc 1
nc 1
nop 11

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 * @author Lukas Reschke <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Roeland Jago Douma <[email protected]>
9
 * @author Thomas Müller <[email protected]>
10
 * @author Vincent Petry <[email protected]>
11
 * @author John Molakvoæ <[email protected]>
12
 *
13
 * @license AGPL-3.0
14
 *
15
 * This code is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License, version 3,
17
 * as published by the Free Software Foundation.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License, version 3,
25
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
26
 *
27
 */
28
29
namespace OC\Core\Controller;
30
31
use OC\AppFramework\Utility\TimeFactory;
32
use OCP\Accounts\IAccountManager;
33
use OCP\AppFramework\Controller;
34
use OCP\AppFramework\Http;
35
use OCP\AppFramework\Http\DataDisplayResponse;
36
use OCP\AppFramework\Http\FileDisplayResponse;
37
use OCP\AppFramework\Http\JSONResponse;
38
use OCP\Files\File;
39
use OCP\Files\IRootFolder;
40
use OCP\IAvatarManager;
41
use OCP\ICache;
42
use OCP\IL10N;
43
use OCP\ILogger;
44
use OCP\IRequest;
45
use OCP\IUserManager;
46
use OCP\IUserSession;
47
48
/**
49
 * Class AvatarController
50
 *
51
 * @package OC\Core\Controller
52
 */
53
class AvatarController extends Controller {
54
55
	/** @var IAvatarManager */
56
	protected $avatarManager;
57
58
	/** @var ICache */
59
	protected $cache;
60
61
	/** @var IL10N */
62
	protected $l;
63
64
	/** @var IUserManager */
65
	protected $userManager;
66
67
	/** @var IUserSession */
68
	protected $userSession;
69
70
	/** @var IRootFolder */
71
	protected $rootFolder;
72
73
	/** @var ILogger */
74
	protected $logger;
75
76
	/** @var string */
77
	protected $userId;
78
79
	/** @var TimeFactory */
80
	protected $timeFactory;
81
	/** @var IAccountManager */
82
	private $accountManager;
83
84
	public function __construct($appName,
85
								IRequest $request,
86
								IAvatarManager $avatarManager,
87
								ICache $cache,
88
								IL10N $l10n,
89
								IUserManager $userManager,
90
								IRootFolder $rootFolder,
91
								ILogger $logger,
92
								$userId,
93
								TimeFactory $timeFactory,
94
								IAccountManager $accountManager) {
95
		parent::__construct($appName, $request);
96
97
		$this->avatarManager = $avatarManager;
98
		$this->cache = $cache;
99
		$this->l = $l10n;
100
		$this->userManager = $userManager;
101
		$this->rootFolder = $rootFolder;
102
		$this->logger = $logger;
103
		$this->userId = $userId;
104
		$this->timeFactory = $timeFactory;
105
		$this->accountManager = $accountManager;
106
	}
107
108
109
	/**
110
	 * @NoAdminRequired
111
	 * @NoCSRFRequired
112
	 * @NoSameSiteCookieRequired
113
	 * @PublicPage
114
	 *
115
	 * @param string $userId
116
	 * @param int $size
117
	 * @return JSONResponse|FileDisplayResponse
118
	 */
119
	public function getAvatar($userId, $size) {
120
		// min/max size
121
		if ($size > 2048) {
122
			$size = 2048;
123
		} elseif ($size <= 0) {
124
			$size = 64;
125
		}
126
127
		$user = $this->userManager->get($userId);
128
		if ($user === null) {
129
			return new JSONResponse([], Http::STATUS_NOT_FOUND);
130
		}
131
132
		$account = $this->accountManager->getAccount($user);
133
		$scope = $account->getProperty(IAccountManager::PROPERTY_AVATAR)->getScope();
134
135
		if ($scope !== IAccountManager::VISIBILITY_PUBLIC && $this->userId === null) {
136
			// Public avatar access is not allowed
137
			return new JSONResponse([], Http::STATUS_NOT_FOUND);
138
		}
139
140
		try {
141
			$avatar = $this->avatarManager->getAvatar($userId);
142
			$avatarFile = $avatar->getFile($size);
143
			$resp = new FileDisplayResponse(
144
				$avatarFile,
145
				$avatar->isCustomAvatar() ? Http::STATUS_OK : Http::STATUS_CREATED,
146
				['Content-Type' => $avatarFile->getMimeType()]
147
			);
148
		} catch (\Exception $e) {
149
			return new JSONResponse([], Http::STATUS_NOT_FOUND);
150
		}
151
152
		// Cache for 30 minutes
153
		$resp->cacheFor(1800);
154
		return $resp;
155
	}
156
157
	/**
158
	 * @NoAdminRequired
159
	 *
160
	 * @param string $path
161
	 * @return JSONResponse
162
	 */
163
	public function postAvatar($path) {
164
		$files = $this->request->getUploadedFile('files');
165
166
		if (isset($path)) {
167
			$path = stripslashes($path);
168
			$userFolder = $this->rootFolder->getUserFolder($this->userId);
169
			/** @var File $node */
170
			$node = $userFolder->get($path);
171
			if (!($node instanceof File)) {
0 ignored issues
show
introduced by
$node is always a sub-type of OCP\Files\File.
Loading history...
172
				return new JSONResponse(['data' => ['message' => $this->l->t('Please select a file.')]]);
173
			}
174
			if ($node->getSize() > 20*1024*1024) {
175
				return new JSONResponse(
176
					['data' => ['message' => $this->l->t('File is too big')]],
177
					Http::STATUS_BAD_REQUEST
178
				);
179
			}
180
181
			if ($node->getMimeType() !== 'image/jpeg' && $node->getMimeType() !== 'image/png') {
182
				return new JSONResponse(
183
					['data' => ['message' => $this->l->t('The selected file is not an image.')]],
184
					Http::STATUS_BAD_REQUEST
185
				);
186
			}
187
188
			try {
189
				$content = $node->getContent();
190
			} catch (\OCP\Files\NotPermittedException $e) {
191
				return new JSONResponse(
192
					['data' => ['message' => $this->l->t('The selected file cannot be read.')]],
193
					Http::STATUS_BAD_REQUEST
194
				);
195
			}
196
		} elseif (!is_null($files)) {
0 ignored issues
show
introduced by
The condition is_null($files) is always false.
Loading history...
197
			if (
198
				$files['error'][0] === 0 &&
199
				 is_uploaded_file($files['tmp_name'][0]) &&
200
				!\OC\Files\Filesystem::isFileBlacklisted($files['tmp_name'][0])
201
			) {
202
				if ($files['size'][0] > 20*1024*1024) {
203
					return new JSONResponse(
204
						['data' => ['message' => $this->l->t('File is too big')]],
205
						Http::STATUS_BAD_REQUEST
206
					);
207
				}
208
				$this->cache->set('avatar_upload', file_get_contents($files['tmp_name'][0]), 7200);
209
				$content = $this->cache->get('avatar_upload');
210
				unlink($files['tmp_name'][0]);
211
			} else {
212
				return new JSONResponse(
213
					['data' => ['message' => $this->l->t('Invalid file provided')]],
214
					Http::STATUS_BAD_REQUEST
215
				);
216
			}
217
		} else {
218
			//Add imgfile
219
			return new JSONResponse(
220
				['data' => ['message' => $this->l->t('No image or file provided')]],
221
				Http::STATUS_BAD_REQUEST
222
			);
223
		}
224
225
		try {
226
			$image = new \OC_Image();
227
			$image->loadFromData($content);
228
			$image->readExif($content);
229
			$image->fixOrientation();
230
231
			if ($image->valid()) {
232
				$mimeType = $image->mimeType();
233
				if ($mimeType !== 'image/jpeg' && $mimeType !== 'image/png') {
234
					return new JSONResponse(
235
						['data' => ['message' => $this->l->t('Unknown filetype')]],
236
						Http::STATUS_OK
237
					);
238
				}
239
240
				$this->cache->set('tmpAvatar', $image->data(), 7200);
241
				return new JSONResponse(
242
					['data' => 'notsquare'],
243
					Http::STATUS_OK
244
				);
245
			} else {
246
				return new JSONResponse(
247
					['data' => ['message' => $this->l->t('Invalid image')]],
248
					Http::STATUS_OK
249
				);
250
			}
251
		} catch (\Exception $e) {
252
			$this->logger->logException($e, ['app' => 'core']);
253
			return new JSONResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_OK);
254
		}
255
	}
256
257
	/**
258
	 * @NoAdminRequired
259
     *
260
	 * @return JSONResponse
261
	 */
262
	public function deleteAvatar() {
263
		try {
264
			$avatar = $this->avatarManager->getAvatar($this->userId);
265
			$avatar->remove();
266
			return new JSONResponse();
267
		} catch (\Exception $e) {
268
			$this->logger->logException($e, ['app' => 'core']);
269
			return new JSONResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_BAD_REQUEST);
270
		}
271
	}
272
273
	/**
274
	 * @NoAdminRequired
275
	 *
276
	 * @return JSONResponse|DataDisplayResponse
277
	 */
278
	public function getTmpAvatar() {
279
		$tmpAvatar = $this->cache->get('tmpAvatar');
280
		if (is_null($tmpAvatar)) {
281
			return new JSONResponse(['data' => [
282
										'message' => $this->l->t("No temporary profile picture available, try again")
283
									]],
284
									Http::STATUS_NOT_FOUND);
285
		}
286
287
		$image = new \OC_Image();
288
		$image->loadFromData($tmpAvatar);
289
290
		$resp = new DataDisplayResponse($image->data(),
291
				Http::STATUS_OK,
292
				['Content-Type' => $image->mimeType()]);
293
294
		$resp->setETag((string)crc32($image->data()));
295
		$resp->cacheFor(0);
296
		$resp->setLastModified(new \DateTime('now', new \DateTimeZone('GMT')));
297
		return $resp;
298
	}
299
300
	/**
301
	 * @NoAdminRequired
302
	 *
303
	 * @param array $crop
304
	 * @return JSONResponse
305
	 */
306
	public function postCroppedAvatar($crop) {
307
		if (is_null($crop)) {
0 ignored issues
show
introduced by
The condition is_null($crop) is always false.
Loading history...
308
			return new JSONResponse(['data' => ['message' => $this->l->t("No crop data provided")]],
309
									Http::STATUS_BAD_REQUEST);
310
		}
311
312
		if (!isset($crop['x'], $crop['y'], $crop['w'], $crop['h'])) {
313
			return new JSONResponse(['data' => ['message' => $this->l->t("No valid crop data provided")]],
314
									Http::STATUS_BAD_REQUEST);
315
		}
316
317
		$tmpAvatar = $this->cache->get('tmpAvatar');
318
		if (is_null($tmpAvatar)) {
319
			return new JSONResponse(['data' => [
320
										'message' => $this->l->t("No temporary profile picture available, try again")
321
									]],
322
									Http::STATUS_BAD_REQUEST);
323
		}
324
325
		$image = new \OC_Image();
326
		$image->loadFromData($tmpAvatar);
327
		$image->crop($crop['x'], $crop['y'], (int)round($crop['w']), (int)round($crop['h']));
328
		try {
329
			$avatar = $this->avatarManager->getAvatar($this->userId);
330
			$avatar->set($image);
331
			// Clean up
332
			$this->cache->remove('tmpAvatar');
333
			return new JSONResponse(['status' => 'success']);
334
		} catch (\OC\NotSquareException $e) {
335
			return new JSONResponse(['data' => ['message' => $this->l->t('Crop is not square')]],
336
									Http::STATUS_BAD_REQUEST);
337
		} catch (\Exception $e) {
338
			$this->logger->logException($e, ['app' => 'core']);
339
			return new JSONResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_BAD_REQUEST);
340
		}
341
	}
342
}
343