Passed
Push — master ( 9ca045...4164c5 )
by Maxence
02:09
created

Website::hasToBeOwnedBy()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
c 0
b 0
f 0
rs 10
cc 2
eloc 2
nc 1
nop 1
1
<?php
2
/**
3
 * CMS Pico - Integration of Pico within your files to create websites.
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Maxence Lange <[email protected]>
9
 * @copyright 2017
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
namespace OCA\CMSPico\Model;
28
29
use Exception;
30
use OC\Files\View;
31
use OCA\CMSPico\AppInfo\Application;
32
use OCA\CMSPico\Exceptions\CheckCharsException;
33
use OCA\CMSPico\Exceptions\ContentDirIsNotLocalException;
34
use OCA\CMSPico\Exceptions\MinCharsException;
35
use OCA\CMSPico\Exceptions\PathContainSpecificFoldersException;
36
use OCA\CMSPico\Exceptions\UserIsNotOwnerException;
37
use OCA\CMSPico\Exceptions\WebpageDoesNotExistException;
38
use OCA\CMSPico\Exceptions\WebsiteIsPrivateException;
39
use OCA\CMSPico\Service\MiscService;
40
use OCP\Files\IRootFolder;
41
use OCP\Files\NotFoundException;
42
use OCP\IL10N;
43
44
class Website extends WebsiteCore {
45
46
47
	const TYPE_PUBLIC = 1;
48
	const TYPE_PRIVATE = 2;
49
50
	const SITE_LENGTH_MIN = 3;
51
	const NAME_LENGTH_MIN = 5;
52
53
	/** @var IL10N */
54
	private $l10n;
55
56
	/** @var IRootFolder */
57
	private $rootFolder;
58
59
	/** @var View */
60
	private $ownerView;
61
62
63
	/**
64
	 * Website constructor.
65
	 */
66
	public function __construct() {
67
		$this->l10n = \OC::$server->getL10N(Application::APP_NAME);
68
		$this->rootFolder = \OC::$server->getRootFolder();
69
70
		parent::__construct();
71
	}
72
73
74
	/**
75
	 *
76
	 */
77
	private function initSiteOwnerView() {
78
79
		if ($this->ownerView !== null) {
80
			return;
81
		}
82
83
		$this->ownerView = new View($this->getUserId() . '/files/');
84
	}
85
86
87
	/**
88
	 * @return string
89
	 */
90
	public function getAbsolutePath() {
91
92
		$this->initSiteOwnerView();
93
94
		$path = $this->ownerView->getLocalFile($this->getPath());
95
		MiscService::endSlash($path);
96
97
		return $path;
98
	}
99
100
101
	/**
102
	 * @param string $local
103
	 *
104
	 * @throws WebsiteIsPrivateException
105
	 */
106
	private function hasToBeReadableByViewer($local = '') {
107
108
		$fileId = $this->getPageFileId($local);
109
		$viewerFiles = $this->rootFolder->getUserFolder($this->getViewer())
110
										->getById($fileId);
111
112
		foreach ($viewerFiles as $file) {
113
			if ($file->isReadable()) {
114
				return;
115
			}
116
		}
117
118
		throw new WebpageIsNotReadableException();
0 ignored issues
show
Bug introduced by
The type OCA\CMSPico\Model\WebpageIsNotReadableException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
119
	}
120
121
122
	/**
123
	 * @param string $local
124
	 *
125
	 * @return int
126
	 * @throws WebpageDoesNotExistException
127
	 */
128
	public function getPageFileId($local = '') {
129
130
		try {
131
			$ownerFile = $this->rootFolder->getUserFolder($this->getUserId())
132
										  ->get($this->getPath() . $local);
133
134
			return $ownerFile->getId();
135
		} catch (NotFoundException $e) {
136
			throw new WebpageDoesNotExistException($this->l10n->t('Webpage does not exist'));
137
		}
138
	}
139
140
141
	/**
142
	 * @param string $userId
143
	 *
144
	 * @throws UserIsNotOwnerException
145
	 */
146
	public function hasToBeOwnedBy($userId) {
147
		if ($this->getUserId() !== $userId) {
148
			throw new UserIsNotOwnerException($this->l10n->t('You are not the owner of this website'));
149
		}
150
	}
151
152
153
	/**
154
	 * @param string $path
155
	 *
156
	 * @throws ContentDirIsNotLocalException
157
	 */
158
	public function contentMustBeLocal($path) {
159
160
		try {
161
			$this->pathCantContainSpecificFolders($path);
162
			if (strpos($path, $this->getAbsolutePath()) !== 0) {
163
				throw new PathContainSpecificFoldersException();
164
			}
165
166
		} catch (PathContainSpecificFoldersException $e) {
167
			throw new ContentDirIsNotLocalException($this->l10n->t('Content Directory is not valid.'));
168
		}
169
	}
170
171
172
	/**
173
	 * @param string $path
174
	 *
175
	 * @return bool|string
176
	 */
177
	public function getRelativePath($path) {
178
		if (substr($path, 0, 1) !== '/') {
179
			return $path;
180
		}
181
182
		return substr($path, strlen($this->getAbsolutePath()));
183
	}
184
185
186
	/**
187
	 * @param string $local
188
	 * @param array $meta
189
	 *
190
	 * @throws WebsiteIsPrivateException
191
	 */
192
	public function viewerMustHaveAccess($local, $meta) {
193
194
		try {
195
			$relativePath = $this->getRelativePath($local);
196
			if ($this->pageIsPublic($meta)) {
197
				return;
198
			}
199
200
			if ($this->getViewer() === $this->getUserId()) {
201
				return;
202
			}
203
204
			$this->hasToBeReadableByViewer($relativePath);
205
206
		} catch (Exception $e) {
207
			throw new WebsiteIsPrivateException(
208
				$this->l10n->t('Website is private. You do not have access to this website')
209
			);
210
		}
211
	}
212
213
214
	/**
215
	 * @param array $meta
216
	 *
217
	 * @return bool
218
	 */
219
	private function pageIsPublic($meta) {
220
221
		if (key_exists('access', $meta) && strtolower($meta['access']) === 'private') {
222
			return false;
223
		}
224
225
		if ($this->getOption('private') === '1') {
226
			return false;
227
		}
228
229
		return true;
230
	}
231
232
233
	/**
234
	 * @throws CheckCharsException
235
	 * @throws MinCharsException
236
	 * @throws PathContainSpecificFoldersException
237
	 */
238
	public function hasToBeFilledWithValidEntries() {
239
240
		$this->hasToBeFilledWithNonEmptyValues();
241
		$this->pathCantContainSpecificFolders();
242
243
		if (MiscService::checkChars($this->getSite(), MiscService::ALPHA_NUMERIC_SCORES) === false) {
244
			throw new CheckCharsException(
245
				$this->l10n->t('The address of the website can only contains alpha numeric chars')
246
			);
247
		}
248
	}
249
250
251
	/**
252
	 * @throws MinCharsException
253
	 */
254
	private function hasToBeFilledWithNonEmptyValues() {
255
		if (strlen($this->getSite()) < self::SITE_LENGTH_MIN) {
256
			throw new MinCharsException($this->l10n->t('The address of the website must be longer'));
257
		}
258
259
		if (strlen($this->getName()) < self::NAME_LENGTH_MIN) {
260
			throw new MinCharsException($this->l10n->t('The name of the website must be longer'));
261
		}
262
	}
263
264
265
	/**
266
	 * this is overkill - NC does not allow to create directory outside of the users' filesystem
267
	 * Not sure that there is a single use for this security check
268
	 *
269
	 * @param string $path
270
	 *
271
	 * @throws PathContainSpecificFoldersException
272
	 */
273
	private function pathCantContainSpecificFolders($path = '') {
274
		if ($path === '') {
275
			$path = $this->getPath();
276
		}
277
278
		$limit = ['.', '..'];
279
280
		$folders = explode('/', $path);
281
		foreach ($folders as $folder) {
282
			if (in_array($folder, $limit)) {
283
				throw new PathContainSpecificFoldersException(
284
					$this->l10n->t('Path is malformed, please check.')
285
				);
286
			}
287
		}
288
	}
289
}