PluginProbe
User Access Manager / 2.1.11
User Access Manager v2.1.11
2.3.20 2.3.19 2.3.18 2.3.17 2.3.16 2.3.15 2.3.14 2.3.13 trunk 0.6 0.6.1 0.6.2 0.7 0.7 Beta 0.7.0.1 0.8 0.8.0.1 0.8.0.2 0.9 0.9.1 0.9.1.1 0.9.1.2 0.9.1.3 0.9.1.4 1.0 All 136 releases
← All changes | src/Controller/Frontend/RedirectController.php +220 -170 trunk → 2.1.11 View file →
@@ -1,56 +1,140 @@
1 1 <?php
2 -
3 -declare(strict_types=1);
4 -
2 +/**
3 + * FrontendRedirectController.php
4 + *
5 + * The FrontendRedirectController class file.
6 + *
7 + * PHP versions 5
8 + *
9 + * @author Alexander Schneider <[email protected]>
10 + * @copyright 2008-2017 Alexander Schneider
11 + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2
12 + * @version SVN: $id$
13 + * @link http://wordpress.org/extend/plugins/user-access-manager/
14 + */
5 15 namespace UserAccessManager\Controller\Frontend;
6 16
7 -use JetBrains\PhpStorm\NoReturn;
8 17 use UserAccessManager\Access\AccessHandler;
9 18 use UserAccessManager\Cache\Cache;
10 19 use UserAccessManager\Config\MainConfig;
11 20 use UserAccessManager\Config\WordpressConfig;
12 21 use UserAccessManager\Controller\Controller;
13 -use UserAccessManager\Controller\Frontend\Authentication\LoginControllerTrait;
14 22 use UserAccessManager\Database\Database;
15 23 use UserAccessManager\File\FileHandler;
16 -use UserAccessManager\File\Delivery\FileObject;
17 -use UserAccessManager\File\Delivery\FileObjectFactory;
24 +use UserAccessManager\File\FileObject;
25 +use UserAccessManager\File\FileObjectFactory;
18 26 use UserAccessManager\Object\ObjectHandler;
19 -use UserAccessManager\UserGroup\UserGroupTypeException;
20 27 use UserAccessManager\Util\Util;
21 28 use UserAccessManager\Wrapper\Php;
22 29 use UserAccessManager\Wrapper\Wordpress;
23 30
31 +/**
32 + * Class FrontendRedirectController
33 + *
34 + * @package UserAccessManager\Controller
35 + */
24 36 class RedirectController extends Controller
25 37 {
26 38 use LoginControllerTrait;
27 39
28 - public const POST_URL_CACHE_KEY = 'PostUrls';
29 - public const REDIRECT_TO_PARAMETER = 'redirect_to';
40 + const POST_URL_CACHE_KEY = 'PostUrls';
30 41
42 + /**
43 + * @var MainConfig
44 + */
45 + private $mainConfig;
46 +
47 + /**
48 + * @var Database
49 + */
50 + private $database;
51 +
52 + /**
53 + * @var Cache
54 + */
55 + private $cache;
56 +
57 + /**
58 + * @var Util
59 + */
60 + private $util;
61 +
62 + /**
63 + * @var ObjectHandler
64 + */
65 + private $objectHandler;
66 +
67 + /**
68 + * @var AccessHandler
69 + */
70 + private $accessHandler;
71 +
72 + /**
73 + * @var FileHandler
74 + */
75 + private $fileHandler;
76 +
77 + /**
78 + * @var FileObjectFactory
79 + */
80 + private $fileObjectFactory;
81 +
82 + /**
83 + * RedirectController constructor.
84 + *
85 + * @param Php $php
86 + * @param Wordpress $wordpress
87 + * @param WordpressConfig $wordpressConfig
88 + * @param MainConfig $mainConfig
89 + * @param Database $database
90 + * @param Util $util
91 + * @param Cache $cache
92 + * @param ObjectHandler $objectHandler
93 + * @param AccessHandler $accessHandler
94 + * @param FileHandler $fileHandler
95 + * @param FileObjectFactory $fileObjectFactory
96 + */
31 97 public function __construct(
32 98 Php $php,
33 99 Wordpress $wordpress,
34 100 WordpressConfig $wordpressConfig,
35 - private MainConfig $mainConfig,
36 - private Database $database,
37 - private Util $util,
38 - private Cache $cache,
39 - private ObjectHandler $objectHandler,
40 - private AccessHandler $accessHandler,
41 - private FileHandler $fileHandler,
42 - private FileObjectFactory $fileObjectFactory
101 + MainConfig $mainConfig,
102 + Database $database,
103 + Util $util,
104 + Cache $cache,
105 + ObjectHandler $objectHandler,
106 + AccessHandler $accessHandler,
107 + FileHandler $fileHandler,
108 + FileObjectFactory $fileObjectFactory
43 109 ) {
44 110 parent::__construct($php, $wordpress, $wordpressConfig);
111 + $this->mainConfig = $mainConfig;
112 + $this->database = $database;
113 + $this->util = $util;
114 + $this->cache = $cache;
115 + $this->objectHandler = $objectHandler;
116 + $this->accessHandler = $accessHandler;
117 + $this->fileHandler = $fileHandler;
118 + $this->fileObjectFactory = $fileObjectFactory;
45 119 }
46 120
47 - protected function getWordpress(): Wordpress
121 + /**
122 + * @return Wordpress
123 + */
124 + protected function getWordpress()
48 125 {
49 126 return $this->wordpress;
50 127 }
51 128
52 - public function getPostIdByUrl(string $url): int
129 + /**
130 + * Returns the post by the given url.
131 + *
132 + * @param string $url The url of the post(attachment).
133 + *
134 + * @return int
135 + */
136 + public function getPostIdByUrl($url)
53 137 {
54 138 $postUrls = (array)$this->cache->getFromRuntimeCache(self::POST_URL_CACHE_KEY);
55 139
56 140 if (isset($postUrls[$url]) === true) {
@@ -57,147 +141,74 @@
57 141 return $postUrls[$url];
58 142 }
59 143
60 144 //Filter size
61 - $newUrlPieces = preg_split('/-[0-9]+x[0-9]+(_[a-z])?/', $url);
62 - $newUrl = (count($newUrlPieces) === 2) ? $newUrlPieces[0] . $newUrlPieces[1] : $newUrlPieces[0];
63 - $newUrl = preg_replace('/-pdf\.jpg$/', '.pdf', $newUrl);
145 + $newUrlPieces = preg_split('/-[0-9]{1,}x[0-9]{1,}(_[a-z])?/', $url);
146 + $newUrl = (count($newUrlPieces) === 2) ? $newUrlPieces[0].$newUrlPieces[1] : $newUrlPieces[0];
147 + $newUrl = preg_replace('/\-pdf\.jpg$/', '.pdf', $newUrl);
64 148
65 - $postId = $this->wordpress->attachmentUrlToPostId($newUrl);
66 -
67 - if ($postId === 0) {
68 - $newUrl = preg_replace('/(\\.[^.\\s]{3,4})$/', '-scaled$1', $newUrl);
69 - $postId = $this->wordpress->attachmentUrlToPostId($newUrl);
70 - }
71 -
72 - $postUrls[$url] = $postId;
149 + $postUrls[$url] = $this->wordpress->attachmentUrlToPostId($newUrl);
73 150 $this->cache->addToRuntimeCache(self::POST_URL_CACHE_KEY, $postUrls);
74 151
75 152 return $postUrls[$url];
76 153 }
77 154
78 - private function normalizeAttachmentUrl(array $uploadDirs, string $objectUrl): string
79 - {
80 - $uploadDir = str_replace(ABSPATH, '/', $uploadDirs['basedir']);
81 - $regex = '/.*' . str_replace('/', '\/', $uploadDir) . '\//i';
82 - $cleanObjectUrl = preg_replace($regex, '', $objectUrl);
83 - $uploadUrl = str_replace('/files', $uploadDir, $uploadDirs['baseurl']);
84 -
85 - return rtrim($uploadUrl, '/') . '/' . ltrim($cleanObjectUrl, '/');
86 - }
87 -
88 - private function isRegisteredSize(int $attachmentId, string $fileName): bool
89 - {
90 - $metaData = $this->wordpress->getAttachmentMetadata($attachmentId);
91 - $sizes = is_array($metaData) === true ? (array) ($metaData['sizes'] ?? []) : [];
92 -
93 - return in_array($fileName, array_column($sizes, 'file'), true);
94 - }
95 -
96 155 /**
97 - * Returns the file the request asks for and tells through $isImage whether it can be shown as image.
98 - * A requested generated size is only used if it is registered at the attachment and stored inside the
99 - * upload directory, so no arbitrary and no missing file becomes reachable. Generated sizes are always
100 - * images, also for documents like PDFs, where they are the preview images shown in the media library.
156 + * Returns the file object by the given type and url.
157 + *
158 + * @param string $objectType The type of the requested file.
159 + * @param string $objectUrl The file url.
160 + *
161 + * @return null|FileObject
101 162 */
102 - private function getAttachmentFile(
103 - int $attachmentId,
104 - string $attachedFile,
105 - string $requestedUrl,
106 - string $uploadBaseDir,
107 - ?bool &$isImage
108 - ): string {
109 - $requestedFileName = basename((string) parse_url($requestedUrl, PHP_URL_PATH));
110 - $sizeFile = dirname($attachedFile) . DIRECTORY_SEPARATOR . $requestedFileName;
111 -
112 - if ($requestedFileName !== basename($attachedFile)
113 - && $this->isRegisteredSize($attachmentId, $requestedFileName) === true
114 - && $this->isInsideUploadDirectory($sizeFile, $uploadBaseDir) === true
115 - ) {
116 - $isImage = true;
117 -
118 - return $sizeFile;
119 - }
120 -
121 - $isImage = $this->wordpress->attachmentIsImage($attachmentId);
122 -
123 - return $attachedFile;
124 - }
125 -
126 - private function getAttachmentFileObject(string $objectUrl): ?FileObject
163 + private function getFileSettingsByType($objectType, $objectUrl)
127 164 {
128 - $uploadDirs = $this->wordpress->getUploadDir();
129 - $requestedUrl = $this->normalizeAttachmentUrl($uploadDirs, $objectUrl);
130 - $postId = $this->getPostIdByUrl($requestedUrl);
165 + $fileObject = null;
131 166
132 - if ($postId < 1) {
133 - return null;
134 - }
167 + if ($objectType === ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
168 + $uploadDirs = $this->wordpress->getUploadDir();
169 + $uploadDir = str_replace(ABSPATH, '/', $uploadDirs['basedir']);
170 + $regex = '/.*'.str_replace('/', '\/', $uploadDir).'\//i';
171 + $cleanObjectUrl = preg_replace($regex, '', $objectUrl);
172 + $uploadUrl = str_replace('/files', $uploadDir, $uploadDirs['baseurl']);
173 + $objectUrl = rtrim($uploadUrl, '/').'/'.ltrim($cleanObjectUrl, '/');
135 174
136 - $post = $this->objectHandler->getPost($postId);
175 + $post = $this->objectHandler->getPost($this->getPostIdByUrl($objectUrl));
137 176
138 - if (($post->post_type ?? '') !== ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
139 - return null;
140 - }
177 + if ($post !== false
178 + && $post->post_type === ObjectHandler::ATTACHMENT_OBJECT_TYPE
179 + ) {
180 + $multiPath = str_replace('/files', $uploadDir, $uploadDirs['baseurl']);
141 181
142 - // Unfiltered, because the plugin denies the path through the get_attached_file filter for
143 - // users without access. Filtered it would hide the file from the access check below, which
144 - // then could not answer the request with the no rights page any more.
145 - $attachedFile = $this->wordpress->getAttachedFile($post->ID, true);
182 + $fileObject = $this->fileObjectFactory->createFileObject(
183 + $post->ID,
184 + $objectType,
185 + $uploadDirs['basedir'].str_replace($multiPath, '', $objectUrl),
186 + $this->wordpress->attachmentIsImage($post->ID)
187 + );
188 + }
189 + } else {
190 + $extraParameter = $this->getRequestParameter('uamextra');
146 191
147 - if ($attachedFile === false
148 - || $this->isInsideUploadDirectory($attachedFile, $uploadDirs['basedir']) === false
149 - ) {
150 - return null;
192 + $fileObject = $this->wordpress->applyFilters(
193 + 'uam_get_file_settings_by_type',
194 + $fileObject,
195 + $objectType,
196 + $objectUrl,
197 + $extraParameter
198 + );
151 199 }
152 200
153 - $file = $this->getAttachmentFile(
154 - $post->ID,
155 - $attachedFile,
156 - $requestedUrl,
157 - $uploadDirs['basedir'],
158 - $isImage
159 - );
160 -
161 - return $this->fileObjectFactory->createFileObject(
162 - $post->ID,
163 - ObjectHandler::ATTACHMENT_OBJECT_TYPE,
164 - $file,
165 - $isImage
166 - );
201 + return $fileObject;
167 202 }
168 203
169 - private function isInsideUploadDirectory(string $file, string $uploadBaseDir): bool
170 - {
171 - $realFile = $this->php->realpath($file);
172 - $realUploadBaseDir = $this->php->realpath($uploadBaseDir);
173 -
174 - return $realFile !== false
175 - && $realUploadBaseDir !== false
176 - && str_starts_with($realFile, $realUploadBaseDir . DIRECTORY_SEPARATOR);
177 - }
178 -
179 - private function getFileSettingsByType(string $objectType, string $objectUrl): ?FileObject
180 - {
181 - if ($objectType === ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
182 - return $this->getAttachmentFileObject($objectUrl);
183 - }
184 -
185 - $extraParameter = $this->getRequestParameter('uamextra');
186 -
187 - return $this->wordpress->applyFilters(
188 - 'uam_get_file_settings_by_type',
189 - null,
190 - $objectType,
191 - $objectUrl,
192 - $extraParameter
193 - );
194 - }
195 -
196 204 /**
197 - * @throws UserGroupTypeException
205 + * Delivers the content of the requested file.
206 + *
207 + * @param string $objectType The type of the requested file.
208 + * @param string $objectUrl The file url.
198 209 */
199 - public function getFile(string $objectType, string $objectUrl): void
210 + public function getFile($objectType, $objectUrl)
200 211 {
201 212 $fileObject = $this->getFileSettingsByType($objectType, $objectUrl);
202 213
203 214 if ($fileObject === null) {
@@ -210,9 +221,9 @@
210 221 if ($this->mainConfig->getNoAccessImageType() === 'custom') {
211 222 $file = $this->mainConfig->getCustomNoAccessImage();
212 223 } else {
213 224 $realPath = $this->wordpressConfig->getRealPath();
214 - $file = $realPath . 'assets' . DIRECTORY_SEPARATOR . 'gfx' . DIRECTORY_SEPARATOR . 'noAccessPic.png';
225 + $file = $realPath.'assets'.DIRECTORY_SEPARATOR.'gfx'.DIRECTORY_SEPARATOR.'noAccessPic.png';
215 226 }
216 227 } else {
217 228 $this->wordpress->wpDie(TXT_UAM_NO_RIGHTS_MESSAGE, TXT_UAM_NO_RIGHTS_TITLE, ['response' => 403]);
218 229 return;
@@ -220,9 +231,16 @@
220 231
221 232 $this->fileHandler->getFile($file, $fileObject->isImage());
222 233 }
223 234
224 - private function getRedirectUrlAndPermalink(?string &$permalink): ?string
235 + /**
236 + * Returns the redirect url and the permalink of the post if exists.
237 + *
238 + * @param null|string $permalink
239 + *
240 + * @return null|string
241 + */
242 + private function getRedirectUrlAndPermalink(&$permalink)
225 243 {
226 244 $permalink = null;
227 245 $redirect = $this->mainConfig->getRedirect();
228 246
@@ -238,11 +256,8 @@
238 256 } elseif ($redirect === 'custom_url') {
239 257 $url = $this->mainConfig->getRedirectCustomUrl();
240 258 } elseif ($redirect === 'login') {
241 259 $url = $this->getLoginUrl();
242 - } elseif ($redirect === 'origin') {
243 - $referer = $this->wordpress->getReferer();
244 - $url = $referer !== false ? $referer : $this->wordpress->getHomeUrl('/');
245 260 } else {
246 261 $url = $this->wordpress->getHomeUrl('/');
247 262 }
248 263
@@ -249,14 +264,16 @@
249 264 return $url;
250 265 }
251 266
252 267 /**
253 - * @throws UserGroupTypeException
268 + * Redirects the user to his destination.
269 + *
270 + * @param bool $checkPosts
254 271 */
255 - public function redirectUser(bool $checkPosts = true): void
272 + public function redirectUser($checkPosts = true)
256 273 {
257 274 if ($checkPosts === true) {
258 - $posts = $this->wordpress->getWpQuery()->get_posts();
275 + $posts = (array)$this->wordpress->getWpQuery()->get_posts();
259 276
260 277 foreach ($posts as $post) {
261 278 if ($this->accessHandler->checkObjectAccess($post->post_type, $post->ID)) {
262 279 return;
@@ -267,33 +284,43 @@
267 284 $url = $this->getRedirectUrlAndPermalink($permalink);
268 285 $currentUrl = $this->util->getCurrentUrl();
269 286
270 287 if ($url !== null && $url !== $currentUrl && $permalink !== $currentUrl) {
271 - if ($this->mainConfig->appendRedirectToParameter() === true) {
272 - $url = $this->wordpress->addQueryArg([self::REDIRECT_TO_PARAMETER => $currentUrl], $url);
273 - }
274 -
275 288 $this->wordpress->wpRedirect($url);
276 289 $this->php->callExit();
277 290 }
278 291 }
279 292
280 - private function getPostIdByName(string $name): int
293 + /**
294 + * Returns the post id by the post name.
295 + *
296 + * @param string $name
297 + *
298 + * @return int
299 + */
300 + private function getPostIdByName($name)
281 301 {
282 302 $postableTypes = implode('\',\'', $this->objectHandler->getPostTypes());
283 303
284 304 $query = $this->database->prepare(
285 - "SELECT `ID`
286 - FROM `{$this->database->getPostsTable()}`
287 - WHERE `post_name` = %s
288 - AND `post_type` IN ('$postableTypes')",
305 + "SELECT ID
306 + FROM {$this->database->getPostsTable()}
307 + WHERE post_name = %s
308 + AND post_type IN ('{$postableTypes}')",
289 309 $name
290 310 );
291 311
292 - return (int) $this->database->getVariable($query);
312 + return (int)$this->database->getVariable($query);
293 313 }
294 314
295 - private function extractObjectTypeAndId(mixed $pageParams, ?string &$objectType, int|string|null &$objectId): void
315 + /**
316 + * Extracts the object type and id.
317 + *
318 + * @param object $pageParams
319 + * @param null|string $objectType
320 + * @param null|string $objectId
321 + */
322 + private function extractObjectTypeAndId($pageParams, &$objectType, &$objectId)
296 323 {
297 324 $objectType = null;
298 325 $objectId = null;
299 326
@@ -316,18 +343,23 @@
316 343 } elseif (isset($pageParams->query_vars['pagename']) === true) {
317 344 $object = $this->wordpress->getPageByPath($pageParams->query_vars['pagename']);
318 345
319 346 if ($object !== null) {
320 - $objectType = $object->post_type ?? null;
321 - $objectId = $object->ID ?? null;
347 + $objectType = $object->post_type;
348 + $objectId = $object->ID;
322 349 }
323 350 }
324 351 }
325 352
326 353 /**
327 - * @throws UserGroupTypeException
354 + * Redirects to a page or to content.
355 + *
356 + * @param string $headers The headers which are given from wordpress.
357 + * @param object $pageParams The params of the current page.
358 + *
359 + * @return string
328 360 */
329 - public function redirect(?array $headers, mixed $pageParams): ?array
361 + public function redirect($headers, $pageParams)
330 362 {
331 363 $fileUrl = $this->getRequestParameter('uamgetfile');
332 364 $fileType = $this->getRequestParameter('uamfiletype');
333 365
@@ -345,9 +377,17 @@
345 377
346 378 return $headers;
347 379 }
348 380
349 - public function getFileUrl(string $url, int|string|null $id): string
381 + /**
382 + * Returns the url for a locked file.
383 + *
384 + * @param string $url The base url.
385 + * @param integer $id The _iId of the file.
386 + *
387 + * @return string
388 + */
389 + public function getFileUrl($url, $id)
350 390 {
351 391 // Nginx always supports real urls so we need the new urls only
352 392 // if we don't use nginx and mod_rewrite is disabled
353 393 if ($this->mainConfig->lockFile() === true
@@ -355,17 +395,17 @@
355 395 && $this->wordpress->gotModRewrite() === false
356 396 ) {
357 397 $post = $this->objectHandler->getPost($id);
358 398
359 - if ($post !== false) {
399 + if ($post !== null) {
360 400 $type = explode('/', $post->post_mime_type);
361 - $type = $type[1] ?? $type[0];
401 + $type = (isset($type[1]) === true) ? $type[1] : $type[0];
362 402
363 403 $lockedFileTypes = $this->mainConfig->getLockedFiles();
364 404 $fileTypes = explode(',', $lockedFileTypes);
365 405
366 406 if ($lockedFileTypes === 'all' || in_array($type, $fileTypes) === true) {
367 - $url = $this->wordpress->getHomeUrl('/') . '?uamfiletype=attachment&uamgetfile=' . $url;
407 + $url = $this->wordpress->getHomeUrl('/').'?uamfiletype=attachment&uamgetfile='.$url;
368 408 }
369 409 }
370 410 }
371 411
@@ -371,18 +411,28 @@
371 411
372 412 return $url;
373 413 }
374 414
375 - public function cachePostLinks(string $url, object $post): string
415 + /**
416 + * Caches the urls for the post for a later lookup.
417 + *
418 + * @param string $url The url of the post.
419 + * @param object $post The post object.
420 + *
421 + * @return string
422 + */
423 + public function cachePostLinks($url, $post)
376 424 {
377 - $postUrls = (array) $this->cache->getFromRuntimeCache(self::POST_URL_CACHE_KEY);
425 + $postUrls = (array)$this->cache->getFromRuntimeCache(self::POST_URL_CACHE_KEY);
378 426 $postUrls[$url] = $post->ID;
379 427 $this->cache->addToRuntimeCache(self::POST_URL_CACHE_KEY, $postUrls);
380 428 return $url;
381 429 }
382 430
383 - #[NoReturn]
384 - public function testXSendFile(): void
431 + /**
432 + * Tries to load the file via x send file
433 + */
434 + public function testXSendFile()
385 435 {
386 436 $this->fileHandler->deliverXSendFileTestFile();
387 437 }
388 438 }