PluginProbe
User Access Manager / 2.3.17
User Access Manager v2.3.17
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
user-access-manager / src / Controller / Frontend / RedirectController.php

RedirectController.php in User Access Manager 2.3.17, at src/Controller/Frontend/RedirectController.php

336 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace UserAccessManager\Controller\Frontend;
6
7 use JetBrains\PhpStorm\NoReturn;
8 use UserAccessManager\Access\AccessHandler;
9 use UserAccessManager\Cache\Cache;
10 use UserAccessManager\Config\MainConfig;
11 use UserAccessManager\Config\WordpressConfig;
12 use UserAccessManager\Controller\Controller;
13 use UserAccessManager\Database\Database;
14 use UserAccessManager\File\FileHandler;
15 use UserAccessManager\File\FileObject;
16 use UserAccessManager\File\FileObjectFactory;
17 use UserAccessManager\Object\ObjectHandler;
18 use UserAccessManager\UserGroup\UserGroupTypeException;
19 use UserAccessManager\Util\Util;
20 use UserAccessManager\Wrapper\Php;
21 use UserAccessManager\Wrapper\Wordpress;
22
23 class RedirectController extends Controller
24 {
25 use LoginControllerTrait;
26
27 public const POST_URL_CACHE_KEY = 'PostUrls';
28 public const REDIRECT_TO_PARAMETER = 'redirect_to';
29
30 public function __construct(
31 Php $php,
32 Wordpress $wordpress,
33 WordpressConfig $wordpressConfig,
34 private MainConfig $mainConfig,
35 private Database $database,
36 private Util $util,
37 private Cache $cache,
38 private ObjectHandler $objectHandler,
39 private AccessHandler $accessHandler,
40 private FileHandler $fileHandler,
41 private FileObjectFactory $fileObjectFactory
42 ) {
43 parent::__construct($php, $wordpress, $wordpressConfig);
44 }
45
46 protected function getWordpress(): Wordpress
47 {
48 return $this->wordpress;
49 }
50
51 public function getPostIdByUrl(string $url): int
52 {
53 $postUrls = (array)$this->cache->getFromRuntimeCache(self::POST_URL_CACHE_KEY);
54
55 if (isset($postUrls[$url]) === true) {
56 return $postUrls[$url];
57 }
58
59 //Filter size
60 $newUrlPieces = preg_split('/-[0-9]+x[0-9]+(_[a-z])?/', $url);
61 $newUrl = (count($newUrlPieces) === 2) ? $newUrlPieces[0] . $newUrlPieces[1] : $newUrlPieces[0];
62 $newUrl = preg_replace('/-pdf\.jpg$/', '.pdf', $newUrl);
63
64 $postId = $this->wordpress->attachmentUrlToPostId($newUrl);
65
66 if ($postId === 0) {
67 $newUrl = preg_replace('/(\\.[^.\\s]{3,4})$/', '-scaled$1', $newUrl);
68 $postId = $this->wordpress->attachmentUrlToPostId($newUrl);
69 }
70
71 $postUrls[$url] = $postId;
72 $this->cache->addToRuntimeCache(self::POST_URL_CACHE_KEY, $postUrls);
73
74 return $postUrls[$url];
75 }
76
77 private function normalizeAttachmentUrl(array $uploadDirs, string $objectUrl): string
78 {
79 $uploadDir = str_replace(ABSPATH, '/', $uploadDirs['basedir']);
80 $regex = '/.*' . str_replace('/', '\/', $uploadDir) . '\//i';
81 $cleanObjectUrl = preg_replace($regex, '', $objectUrl);
82 $uploadUrl = str_replace('/files', $uploadDir, $uploadDirs['baseurl']);
83
84 return rtrim($uploadUrl, '/') . '/' . ltrim($cleanObjectUrl, '/');
85 }
86
87 private function getAttachmentFileObject(string $objectUrl): ?FileObject
88 {
89 $uploadDirs = $this->wordpress->getUploadDir();
90 $postId = $this->getPostIdByUrl($this->normalizeAttachmentUrl($uploadDirs, $objectUrl));
91
92 if ($postId < 1) {
93 return null;
94 }
95
96 $post = $this->objectHandler->getPost($postId);
97
98 if (($post->post_type ?? '') !== ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
99 return null;
100 }
101
102 $file = $this->wordpress->getAttachedFile($post->ID);
103
104 if ($file === false || $this->isInsideUploadDirectory($file, $uploadDirs['basedir']) === false) {
105 return null;
106 }
107
108 return $this->fileObjectFactory->createFileObject(
109 $post->ID,
110 ObjectHandler::ATTACHMENT_OBJECT_TYPE,
111 $file,
112 $this->wordpress->attachmentIsImage($post->ID)
113 );
114 }
115
116 private function isInsideUploadDirectory(string $file, string $uploadBaseDir): bool
117 {
118 $realFile = $this->php->realpath($file);
119 $realUploadBaseDir = $this->php->realpath($uploadBaseDir);
120
121 return $realFile !== false
122 && $realUploadBaseDir !== false
123 && str_starts_with($realFile, $realUploadBaseDir . DIRECTORY_SEPARATOR);
124 }
125
126 private function getFileSettingsByType(string $objectType, string $objectUrl): ?FileObject
127 {
128 if ($objectType === ObjectHandler::ATTACHMENT_OBJECT_TYPE) {
129 return $this->getAttachmentFileObject($objectUrl);
130 }
131
132 $extraParameter = $this->getRequestParameter('uamextra');
133
134 return $this->wordpress->applyFilters(
135 'uam_get_file_settings_by_type',
136 null,
137 $objectType,
138 $objectUrl,
139 $extraParameter
140 );
141 }
142
143 /**
144 * @throws UserGroupTypeException
145 */
146 public function getFile(string $objectType, string $objectUrl): void
147 {
148 $fileObject = $this->getFileSettingsByType($objectType, $objectUrl);
149
150 if ($fileObject === null) {
151 return;
152 }
153
154 if ($this->accessHandler->checkObjectAccess($fileObject->getType(), $fileObject->getId()) === true) {
155 $file = $fileObject->getFile();
156 } elseif ($fileObject->isImage() === true) {
157 if ($this->mainConfig->getNoAccessImageType() === 'custom') {
158 $file = $this->mainConfig->getCustomNoAccessImage();
159 } else {
160 $realPath = $this->wordpressConfig->getRealPath();
161 $file = $realPath . 'assets' . DIRECTORY_SEPARATOR . 'gfx' . DIRECTORY_SEPARATOR . 'noAccessPic.png';
162 }
163 } else {
164 $this->wordpress->wpDie(TXT_UAM_NO_RIGHTS_MESSAGE, TXT_UAM_NO_RIGHTS_TITLE, ['response' => 403]);
165 return;
166 }
167
168 $this->fileHandler->getFile($file, $fileObject->isImage());
169 }
170
171 private function getRedirectUrlAndPermalink(?string &$permalink): ?string
172 {
173 $permalink = null;
174 $redirect = $this->mainConfig->getRedirect();
175
176 if ($redirect === 'custom_page') {
177 $redirectCustomPage = $this->mainConfig->getRedirectCustomPage();
178 $post = $this->objectHandler->getPost($redirectCustomPage);
179 $url = null;
180
181 if ($post !== false) {
182 $url = $post->guid;
183 $permalink = $this->wordpress->getPageLink($post);
184 }
185 } elseif ($redirect === 'custom_url') {
186 $url = $this->mainConfig->getRedirectCustomUrl();
187 } elseif ($redirect === 'login') {
188 $url = $this->getLoginUrl();
189 } elseif ($redirect === 'origin') {
190 $referer = $this->wordpress->getReferer();
191 $url = $referer !== false ? $referer : $this->wordpress->getHomeUrl('/');
192 } else {
193 $url = $this->wordpress->getHomeUrl('/');
194 }
195
196 return $url;
197 }
198
199 /**
200 * @throws UserGroupTypeException
201 */
202 public function redirectUser(bool $checkPosts = true): void
203 {
204 if ($checkPosts === true) {
205 $posts = $this->wordpress->getWpQuery()->get_posts();
206
207 foreach ($posts as $post) {
208 if ($this->accessHandler->checkObjectAccess($post->post_type, $post->ID)) {
209 return;
210 }
211 }
212 }
213
214 $url = $this->getRedirectUrlAndPermalink($permalink);
215 $currentUrl = $this->util->getCurrentUrl();
216
217 if ($url !== null && $url !== $currentUrl && $permalink !== $currentUrl) {
218 if ($this->mainConfig->appendRedirectToParameter() === true) {
219 $url = $this->wordpress->addQueryArg([self::REDIRECT_TO_PARAMETER => $currentUrl], $url);
220 }
221
222 $this->wordpress->wpRedirect($url);
223 $this->php->callExit();
224 }
225 }
226
227 private function getPostIdByName(string $name): int
228 {
229 $postableTypes = implode('\',\'', $this->objectHandler->getPostTypes());
230
231 $query = $this->database->prepare(
232 "SELECT ID
233 FROM {$this->database->getPostsTable()}
234 WHERE post_name = %s
235 AND post_type IN ('$postableTypes')",
236 $name
237 );
238
239 return (int) $this->database->getVariable($query);
240 }
241
242 private function extractObjectTypeAndId(mixed $pageParams, ?string &$objectType, int|string|null &$objectId): void
243 {
244 $objectType = null;
245 $objectId = null;
246
247 $simpleTypes = [
248 'p' => ObjectHandler::GENERAL_POST_OBJECT_TYPE,
249 'page_id' => ObjectHandler::GENERAL_POST_OBJECT_TYPE,
250 'cat_id' => ObjectHandler::GENERAL_TERM_OBJECT_TYPE
251 ];
252
253 foreach ($simpleTypes as $queryVar => $newObjectType) {
254 if (isset($pageParams->query_vars[$queryVar]) === true) {
255 $objectType = $newObjectType;
256 $objectId = $pageParams->query_vars[$queryVar];
257 }
258 }
259
260 if (isset($pageParams->query_vars['name']) === true) {
261 $objectType = ObjectHandler::GENERAL_POST_OBJECT_TYPE;
262 $objectId = $this->getPostIdByName($pageParams->query_vars['name']);
263 } elseif (isset($pageParams->query_vars['pagename']) === true) {
264 $object = $this->wordpress->getPageByPath($pageParams->query_vars['pagename']);
265
266 if ($object !== null) {
267 $objectType = $object->post_type ?? null;
268 $objectId = $object->ID ?? null;
269 }
270 }
271 }
272
273 /**
274 * @throws UserGroupTypeException
275 */
276 public function redirect(?array $headers, mixed $pageParams): ?array
277 {
278 $fileUrl = $this->getRequestParameter('uamgetfile');
279 $fileType = $this->getRequestParameter('uamfiletype');
280
281 if ($fileUrl !== null && $fileType !== null) {
282 $this->getFile($fileType, $fileUrl);
283 } elseif ($this->wordpressConfig->atAdminPanel() === false
284 && $this->mainConfig->getRedirect() !== 'false'
285 ) {
286 $this->extractObjectTypeAndId($pageParams, $objectType, $objectId);
287
288 if ($this->accessHandler->checkObjectAccess($objectType, $objectId) === false) {
289 $this->redirectUser(false);
290 }
291 }
292
293 return $headers;
294 }
295
296 public function getFileUrl(string $url, int|string|null $id): string
297 {
298 // Nginx always supports real urls so we need the new urls only
299 // if we don't use nginx and mod_rewrite is disabled
300 if ($this->mainConfig->lockFile() === true
301 && $this->wordpress->isNginx() === false
302 && $this->wordpress->gotModRewrite() === false
303 ) {
304 $post = $this->objectHandler->getPost($id);
305
306 if ($post !== false) {
307 $type = explode('/', $post->post_mime_type);
308 $type = $type[1] ?? $type[0];
309
310 $lockedFileTypes = $this->mainConfig->getLockedFiles();
311 $fileTypes = explode(',', $lockedFileTypes);
312
313 if ($lockedFileTypes === 'all' || in_array($type, $fileTypes) === true) {
314 $url = $this->wordpress->getHomeUrl('/') . '?uamfiletype=attachment&uamgetfile=' . $url;
315 }
316 }
317 }
318
319 return $url;
320 }
321
322 public function cachePostLinks(string $url, object $post): string
323 {
324 $postUrls = (array) $this->cache->getFromRuntimeCache(self::POST_URL_CACHE_KEY);
325 $postUrls[$url] = $post->ID;
326 $this->cache->addToRuntimeCache(self::POST_URL_CACHE_KEY, $postUrls);
327 return $url;
328 }
329
330 #[NoReturn]
331 public function testXSendFile(): void
332 {
333 $this->fileHandler->deliverXSendFileTestFile();
334 }
335 }
336