PluginProbe ʕ •ᴥ•ʔ
LiteSpeed Cache / 7.6.1
LiteSpeed Cache v7.6.1
trunk 1.0.15 1.9.1.1 2.9.9.2 3.6.4 4.6 5.7.0.1 6.5.4 7.0.0.1 7.0.1 7.1 7.2 7.3 7.3.0.1 7.4 7.5 7.5.0.1 7.6 7.6.1 7.6.2 7.7 7.8 7.8.0.1 7.8.1
litespeed-cache / src / router.cls.php
litespeed-cache / src Last commit date
cdn 7 months ago data_structure 7 months ago activation.cls.php 7 months ago admin-display.cls.php 7 months ago admin-settings.cls.php 7 months ago admin.cls.php 7 months ago api.cls.php 7 months ago avatar.cls.php 7 months ago base.cls.php 7 months ago cdn.cls.php 7 months ago cloud.cls.php 7 months ago conf.cls.php 7 months ago control.cls.php 7 months ago core.cls.php 7 months ago crawler-map.cls.php 7 months ago crawler.cls.php 7 months ago css.cls.php 7 months ago data.cls.php 7 months ago data.upgrade.func.php 7 months ago db-optm.cls.php 7 months ago debug2.cls.php 7 months ago doc.cls.php 7 months ago error.cls.php 7 months ago esi.cls.php 7 months ago file.cls.php 7 months ago gui.cls.php 7 months ago health.cls.php 7 months ago htaccess.cls.php 7 months ago img-optm.cls.php 7 months ago import.cls.php 7 months ago import.preset.cls.php 7 months ago lang.cls.php 7 months ago localization.cls.php 7 months ago media.cls.php 7 months ago metabox.cls.php 7 months ago object-cache-wp.cls.php 7 months ago object-cache.cls.php 7 months ago object.lib.php 7 months ago optimize.cls.php 7 months ago optimizer.cls.php 7 months ago placeholder.cls.php 7 months ago purge.cls.php 7 months ago report.cls.php 7 months ago rest.cls.php 7 months ago root.cls.php 7 months ago router.cls.php 7 months ago str.cls.php 7 months ago tag.cls.php 7 months ago task.cls.php 7 months ago tool.cls.php 7 months ago ucss.cls.php 7 months ago utility.cls.php 7 months ago vary.cls.php 7 months ago vpi.cls.php 7 months ago
router.cls.php
834 lines
1 <?php
2 // phpcs:ignoreFile
3
4 /**
5 * The core plugin router class.
6 *
7 * This generate the valid action.
8 *
9 * @since 1.1.0
10 */
11
12 namespace LiteSpeed;
13
14 defined('WPINC') || exit();
15
16 class Router extends Base {
17
18 const LOG_TAG = '[Router]';
19
20 const NONCE = 'LSCWP_NONCE';
21 const ACTION = 'LSCWP_CTRL';
22
23 const ACTION_SAVE_SETTINGS_NETWORK = 'save-settings-network';
24 const ACTION_DB_OPTM = 'db_optm';
25 const ACTION_PLACEHOLDER = 'placeholder';
26 const ACTION_AVATAR = 'avatar';
27 const ACTION_SAVE_SETTINGS = 'save-settings';
28 const ACTION_CLOUD = 'cloud';
29 const ACTION_IMG_OPTM = 'img_optm';
30 const ACTION_HEALTH = 'health';
31 const ACTION_CRAWLER = 'crawler';
32 const ACTION_PURGE = 'purge';
33 const ACTION_CONF = 'conf';
34 const ACTION_ACTIVATION = 'activation';
35 const ACTION_CSS = 'css';
36 const ACTION_UCSS = 'ucss';
37 const ACTION_VPI = 'vpi';
38 const ACTION_PRESET = 'preset';
39 const ACTION_IMPORT = 'import';
40 const ACTION_REPORT = 'report';
41 const ACTION_DEBUG2 = 'debug2';
42 const ACTION_CDN_CLOUDFLARE = 'CDN\Cloudflare';
43 const ACTION_ADMIN_DISPLAY = 'admin_display';
44 const ACTION_TMP_DISABLE = 'tmp_disable';
45
46 // List all handlers here
47 private static $_HANDLERS = array(
48 self::ACTION_ADMIN_DISPLAY,
49 self::ACTION_ACTIVATION,
50 self::ACTION_AVATAR,
51 self::ACTION_CDN_CLOUDFLARE,
52 self::ACTION_CLOUD,
53 self::ACTION_CONF,
54 self::ACTION_CRAWLER,
55 self::ACTION_CSS,
56 self::ACTION_UCSS,
57 self::ACTION_VPI,
58 self::ACTION_DB_OPTM,
59 self::ACTION_DEBUG2,
60 self::ACTION_HEALTH,
61 self::ACTION_IMG_OPTM,
62 self::ACTION_PRESET,
63 self::ACTION_IMPORT,
64 self::ACTION_PLACEHOLDER,
65 self::ACTION_PURGE,
66 self::ACTION_REPORT,
67 );
68
69 const TYPE = 'litespeed_type';
70
71 const ITEM_HASH = 'hash';
72 const ITEM_FLASH_HASH = 'flash_hash';
73
74 private static $_esi_enabled;
75 private static $_is_ajax;
76 private static $_is_logged_in;
77 private static $_ip;
78 private static $_action;
79 private static $_is_admin_ip;
80 private static $_frontend_path;
81
82 /**
83 * Redirect to self to continue operation
84 *
85 * Note: must return when use this func. CLI/Cron call won't die in this func.
86 *
87 * @since 3.0
88 * @access public
89 */
90 public static function self_redirect( $action, $type ) {
91 if (defined('LITESPEED_CLI') || wp_doing_cron()) {
92 Admin_Display::success('To be continued'); // Show for CLI
93 return;
94 }
95
96 // Add i to avoid browser too many redirected warning
97 $i = !empty($_GET['litespeed_i']) ? $_GET['litespeed_i'] : 0;
98 ++$i;
99
100 $link = Utility::build_url($action, $type, false, null, array( 'litespeed_i' => $i ));
101
102 $url = html_entity_decode($link);
103 exit("<meta http-equiv='refresh' content='0;url=$url'>");
104 }
105
106 /**
107 * Check if can run optimize
108 *
109 * @since 1.3
110 * @since 2.3.1 Relocated from cdn.cls
111 * @access public
112 */
113 public function can_optm() {
114 $can = true;
115
116 if (is_user_logged_in() && $this->conf(self::O_OPTM_GUEST_ONLY)) {
117 $can = false;
118 } elseif (is_admin()) {
119 $can = false;
120 } elseif (is_feed()) {
121 $can = false;
122 } elseif (is_preview()) {
123 $can = false;
124 } elseif (self::is_ajax()) {
125 $can = false;
126 }
127
128 if (self::_is_login_page()) {
129 Debug2::debug('[Router] Optm bypassed: login/reg page');
130 $can = false;
131 }
132
133 $can_final = apply_filters('litespeed_can_optm', $can);
134
135 if ($can_final != $can) {
136 Debug2::debug('[Router] Optm bypassed: filter');
137 }
138
139 return $can_final;
140 }
141
142 /**
143 * Check referer page to see if its from admin
144 *
145 * @since 2.4.2.1
146 * @access public
147 */
148 public static function from_admin() {
149 return !empty($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], get_admin_url()) === 0;
150 }
151
152 /**
153 * Check if it can use CDN replacement
154 *
155 * @since 1.2.3
156 * @since 2.3.1 Relocated from cdn.cls
157 * @access public
158 */
159 public static function can_cdn() {
160 $can = true;
161
162 if (is_admin()) {
163 if (!self::is_ajax()) {
164 Debug2::debug2('[Router] CDN bypassed: is not ajax call');
165 $can = false;
166 }
167
168 if (self::from_admin()) {
169 Debug2::debug2('[Router] CDN bypassed: ajax call from admin');
170 $can = false;
171 }
172 } elseif (is_feed()) {
173 $can = false;
174 } elseif (is_preview()) {
175 $can = false;
176 }
177
178 /**
179 * Bypass cron to avoid deregister jq notice `Do not deregister the <code>jquery-core</code> script in the administration area.`
180 *
181 * @since 2.7.2
182 */
183 if (wp_doing_cron()) {
184 $can = false;
185 }
186
187 /**
188 * Bypass login/reg page
189 *
190 * @since 1.6
191 */
192 if (self::_is_login_page()) {
193 Debug2::debug('[Router] CDN bypassed: login/reg page');
194 $can = false;
195 }
196
197 /**
198 * Bypass post/page link setting
199 *
200 * @since 2.9.8.5
201 */
202 $rest_prefix = function_exists('rest_get_url_prefix') ? rest_get_url_prefix() : apply_filters('rest_url_prefix', 'wp-json');
203 if (
204 !empty($_SERVER['REQUEST_URI']) &&
205 strpos($_SERVER['REQUEST_URI'], $rest_prefix . '/wp/v2/media') !== false &&
206 isset($_SERVER['HTTP_REFERER']) &&
207 strpos($_SERVER['HTTP_REFERER'], 'wp-admin') !== false
208 ) {
209 Debug2::debug('[Router] CDN bypassed: wp-json on admin page');
210 $can = false;
211 }
212
213 $can_final = apply_filters('litespeed_can_cdn', $can);
214
215 if ($can_final != $can) {
216 Debug2::debug('[Router] CDN bypassed: filter');
217 }
218
219 return $can_final;
220 }
221
222 /**
223 * Check if is login page or not
224 *
225 * @since 2.3.1
226 * @access protected
227 */
228 protected static function _is_login_page() {
229 if (in_array($GLOBALS['pagenow'], array( 'wp-login.php', 'wp-register.php' ), true)) {
230 return true;
231 }
232
233 return false;
234 }
235
236 /**
237 * UCSS/Crawler role simulator
238 *
239 * @since 1.9.1
240 * @since 3.3 Renamed from `is_crawler_role_simulation`
241 */
242 public function is_role_simulation() {
243 if (is_admin()) {
244 return;
245 }
246
247 if (empty($_COOKIE['litespeed_hash']) && empty($_COOKIE['litespeed_flash_hash'])) {
248 return;
249 }
250
251 self::debug('🪪 starting role validation');
252
253 // Check if is from crawler
254 // if ( empty( $_SERVER[ 'HTTP_USER_AGENT' ] ) || strpos( $_SERVER[ 'HTTP_USER_AGENT' ], Crawler::FAST_USER_AGENT ) !== 0 ) {
255 // Debug2::debug( '[Router] user agent not match' );
256 // return;
257 // }
258 $server_ip = $this->conf(self::O_SERVER_IP);
259 if (!$server_ip || self::get_ip() !== $server_ip) {
260 self::debug('❌❌ Role simulate uid denied! Not localhost visit!');
261 Control::set_nocache('Role simulate uid denied');
262 return;
263 }
264
265 // Flash hash validation
266 if (!empty($_COOKIE['litespeed_flash_hash'])) {
267 $hash_data = self::get_option(self::ITEM_FLASH_HASH, array());
268 if ($hash_data && is_array($hash_data) && !empty($hash_data['hash']) && !empty($hash_data['ts']) && !empty($hash_data['uid'])) {
269 if (time() - $hash_data['ts'] < 120 && $_COOKIE['litespeed_flash_hash'] == $hash_data['hash']) {
270 self::debug('🪪 Role simulator flash hash matched, escalating user to be uid=' . $hash_data['uid']);
271 self::delete_option(self::ITEM_FLASH_HASH);
272 wp_set_current_user($hash_data['uid']);
273 return;
274 }
275 }
276 }
277 // Hash validation
278 if (!empty($_COOKIE['litespeed_hash'])) {
279 $hash_data = self::get_option(self::ITEM_HASH, array());
280 if ($hash_data && is_array($hash_data) && !empty($hash_data['hash']) && !empty($hash_data['ts']) && !empty($hash_data['uid'])) {
281 $RUN_DURATION = $this->cls('Crawler')->get_crawler_duration();
282 if (time() - $hash_data['ts'] < $RUN_DURATION && $_COOKIE['litespeed_hash'] == $hash_data['hash']) {
283 self::debug('🪪 Role simulator hash matched, escalating user to be uid=' . $hash_data['uid']);
284 wp_set_current_user($hash_data['uid']);
285 return;
286 }
287 }
288 }
289
290 self::debug('❌ WARNING: role simulator hash not match');
291 }
292
293 /**
294 * Get a short ttl hash (2mins)
295 *
296 * @since 6.4
297 */
298 public function get_flash_hash( $uid ) {
299 $hash_data = self::get_option(self::ITEM_FLASH_HASH, array());
300 if ($hash_data && is_array($hash_data) && !empty($hash_data['hash']) && !empty($hash_data['ts'])) {
301 if (time() - $hash_data['ts'] < 60) {
302 return $hash_data['hash'];
303 }
304 }
305
306 // Check if this user has editor access or not
307 if (user_can($uid, 'edit_posts')) {
308 self::debug('🛑 The user with id ' . $uid . ' has editor access, which is not allowed for the role simulator.');
309 return '';
310 }
311
312 $hash = Str::rrand(32);
313 self::update_option(self::ITEM_FLASH_HASH, array(
314 'hash' => $hash,
315 'ts' => time(),
316 'uid' => $uid,
317 ));
318 return $hash;
319 }
320
321 /**
322 * Get a security hash
323 *
324 * @since 3.3
325 */
326 public function get_hash( $uid ) {
327 // Check if this user has editor access or not
328 if (user_can($uid, 'edit_posts')) {
329 self::debug('🛑 The user with id ' . $uid . ' has editor access, which is not allowed for the role simulator.');
330 return '';
331 }
332
333 // As this is called only when starting crawling, not per page, no need to reuse
334 $hash = Str::rrand(32);
335 self::update_option(self::ITEM_HASH, array(
336 'hash' => $hash,
337 'ts' => time(),
338 'uid' => $uid,
339 ));
340 return $hash;
341 }
342
343 /**
344 * Get user role
345 *
346 * @since 1.6.2
347 */
348 public static function get_role( $uid = null ) {
349 if (defined('LITESPEED_WP_ROLE')) {
350 return LITESPEED_WP_ROLE;
351 }
352
353 if ($uid === null) {
354 $uid = get_current_user_id();
355 }
356
357 $role = false;
358 if ($uid) {
359 $user = get_userdata($uid);
360 if (isset($user->roles) && is_array($user->roles)) {
361 $tmp = array_values($user->roles);
362 $role = implode(',', $tmp); // Combine for PHP5.3 const compatibility
363 }
364 }
365 Debug2::debug('[Router] get_role: ' . $role);
366
367 if (!$role) {
368 return $role;
369 // Guest user
370 Debug2::debug('[Router] role: guest');
371
372 /**
373 * Fix double login issue
374 * The previous user init refactoring didn't fix this bcos this is in login process and the user role could change
375 *
376 * @see https://github.com/litespeedtech/lscache_wp/commit/69e7bc71d0de5cd58961bae953380b581abdc088
377 * @since 2.9.8 Won't assign const if in login process
378 */
379 if (substr_compare(wp_login_url(), $GLOBALS['pagenow'], -strlen($GLOBALS['pagenow'])) === 0) {
380 return $role;
381 }
382 }
383
384 define('LITESPEED_WP_ROLE', $role);
385
386 return LITESPEED_WP_ROLE;
387 }
388
389 /**
390 * Get frontend path
391 *
392 * @since 1.2.2
393 * @access public
394 * @return boolean
395 */
396 public static function frontend_path() {
397 // todo: move to htaccess.cls ?
398 if (!isset(self::$_frontend_path)) {
399 $frontend = rtrim(ABSPATH, '/'); // /home/user/public_html/frontend
400 // get home path failed. Trac ticket #37668 (e.g. frontend:/blog backend:/wordpress)
401 if (!$frontend) {
402 Debug2::debug('[Router] No ABSPATH, generating from home option');
403 $frontend = parse_url(get_option('home'));
404 $frontend = !empty($frontend['path']) ? $frontend['path'] : '';
405 $frontend = $_SERVER['DOCUMENT_ROOT'] . $frontend;
406 }
407 $frontend = realpath($frontend);
408
409 self::$_frontend_path = $frontend;
410 }
411 return self::$_frontend_path;
412 }
413
414 /**
415 * Check if ESI is enabled or not
416 *
417 * @since 1.2.0
418 * @access public
419 * @return boolean
420 */
421 public function esi_enabled() {
422 if (!isset(self::$_esi_enabled)) {
423 self::$_esi_enabled = defined('LITESPEED_ON') && $this->conf(self::O_ESI);
424 if (!empty($_REQUEST[self::ACTION])) {
425 self::$_esi_enabled = false;
426 }
427 }
428 return self::$_esi_enabled;
429 }
430
431 /**
432 * Check if crawler is enabled on server level
433 *
434 * @since 1.1.1
435 * @access public
436 */
437 public static function can_crawl() {
438 if (isset($_SERVER['X-LSCACHE']) && strpos($_SERVER['X-LSCACHE'], 'crawler') === false) {
439 return false;
440 }
441
442 // CLI will bypass this check as crawler library can always do the 428 check
443 if (defined('LITESPEED_CLI')) {
444 return true;
445 }
446
447 return true;
448 }
449
450 /**
451 * Check action
452 *
453 * @since 1.1.0
454 * @access public
455 * @return string
456 */
457 public static function get_action() {
458 if (!isset(self::$_action)) {
459 self::$_action = false;
460 self::cls()->verify_action();
461 if (self::$_action) {
462 defined('LSCWP_LOG') && Debug2::debug('[Router] LSCWP_CTRL verified: ' . var_export(self::$_action, true));
463 }
464 }
465 return self::$_action;
466 }
467
468 /**
469 * Check if is logged in
470 *
471 * @since 1.1.3
472 * @access public
473 * @return boolean
474 */
475 public static function is_logged_in() {
476 if (!isset(self::$_is_logged_in)) {
477 self::$_is_logged_in = is_user_logged_in();
478 }
479 return self::$_is_logged_in;
480 }
481
482 /**
483 * Check if is ajax call
484 *
485 * @since 1.1.0
486 * @access public
487 * @return boolean
488 */
489 public static function is_ajax() {
490 if (!isset(self::$_is_ajax)) {
491 self::$_is_ajax = wp_doing_ajax();
492 }
493 return self::$_is_ajax;
494 }
495
496 /**
497 * Check if is admin ip
498 *
499 * @since 1.1.0
500 * @access public
501 * @return boolean
502 */
503 public function is_admin_ip() {
504 if (!isset(self::$_is_admin_ip)) {
505 $ips = $this->conf(self::O_DEBUG_IPS);
506
507 self::$_is_admin_ip = $this->ip_access($ips);
508 }
509 return self::$_is_admin_ip;
510 }
511
512 /**
513 * Get type value
514 *
515 * @since 1.6
516 * @access public
517 */
518 public static function verify_type() {
519 if (empty($_REQUEST[self::TYPE])) {
520 Debug2::debug('[Router] no type', 2);
521 return false;
522 }
523
524 Debug2::debug('[Router] parsed type: ' . $_REQUEST[self::TYPE], 2);
525
526 return $_REQUEST[self::TYPE];
527 }
528
529 /**
530 * Check privilege and nonce for the action
531 *
532 * @since 1.1.0
533 * @access private
534 */
535 private function verify_action() {
536 if (empty($_REQUEST[self::ACTION])) {
537 Debug2::debug2('[Router] LSCWP_CTRL bypassed empty');
538 return;
539 }
540
541 $action = stripslashes($_REQUEST[self::ACTION]);
542
543 if (!$action) {
544 return;
545 }
546
547 $_is_public_action = false;
548
549 // Each action must have a valid nonce unless its from admin ip and is public action
550 // Validate requests nonce (from admin logged in page or cli)
551 if (!$this->verify_nonce($action)) {
552 // check if it is from admin ip
553 if (!$this->is_admin_ip()) {
554 Debug2::debug('[Router] LSCWP_CTRL query string - did not match admin IP: ' . $action);
555 return;
556 }
557
558 // check if it is public action
559 if (
560 !in_array($action, array(
561 Core::ACTION_QS_NOCACHE,
562 Core::ACTION_QS_PURGE,
563 Core::ACTION_QS_PURGE_SINGLE,
564 Core::ACTION_QS_SHOW_HEADERS,
565 Core::ACTION_QS_PURGE_ALL,
566 Core::ACTION_QS_PURGE_EMPTYCACHE,
567 ))
568 ) {
569 Debug2::debug('[Router] LSCWP_CTRL query string - did not match admin IP Actions: ' . $action);
570 return;
571 }
572
573 if (apply_filters('litespeed_qs_forbidden', false)) {
574 Debug2::debug('[Router] LSCWP_CTRL forbidden by hook litespeed_qs_forbidden');
575 return;
576 }
577
578 $_is_public_action = true;
579 }
580
581 /* Now it is a valid action, lets log and check the permission */
582 Debug2::debug('[Router] LSCWP_CTRL: ' . $action);
583
584 // OK, as we want to do something magic, lets check if its allowed
585 $_is_multisite = is_multisite();
586 $_is_network_admin = $_is_multisite && is_network_admin();
587 $_can_network_option = $_is_network_admin && current_user_can('manage_network_options');
588 $_can_option = current_user_can('manage_options');
589
590 switch ($action) {
591 case self::ACTION_TMP_DISABLE: // Disable LSC for 24H
592 Debug2::tmp_disable();
593 Admin::redirect("?page=litespeed-toolbox#settings-debug");
594 return;
595
596 case self::ACTION_SAVE_SETTINGS_NETWORK: // Save network settings
597 if ($_can_network_option) {
598 self::$_action = $action;
599 }
600 return;
601
602 case Core::ACTION_PURGE_BY:
603 if (defined('LITESPEED_ON') && ($_can_network_option || $_can_option || self::is_ajax())) {
604 // here may need more security
605 self::$_action = $action;
606 }
607 return;
608
609 case self::ACTION_DB_OPTM:
610 if ($_can_network_option || $_can_option) {
611 self::$_action = $action;
612 }
613 return;
614
615 case Core::ACTION_PURGE_EMPTYCACHE: // todo: moved to purge.cls type action
616 if ((defined('LITESPEED_ON') || $_is_network_admin) && ($_can_network_option || (!$_is_multisite && $_can_option))) {
617 self::$_action = $action;
618 }
619 return;
620
621 case Core::ACTION_QS_NOCACHE:
622 case Core::ACTION_QS_PURGE:
623 case Core::ACTION_QS_PURGE_SINGLE:
624 case Core::ACTION_QS_SHOW_HEADERS:
625 case Core::ACTION_QS_PURGE_ALL:
626 case Core::ACTION_QS_PURGE_EMPTYCACHE:
627 if (defined('LITESPEED_ON') && ($_is_public_action || self::is_ajax())) {
628 self::$_action = $action;
629 }
630 return;
631
632 case self::ACTION_ADMIN_DISPLAY:
633 case self::ACTION_PLACEHOLDER:
634 case self::ACTION_AVATAR:
635 case self::ACTION_IMG_OPTM:
636 case self::ACTION_CLOUD:
637 case self::ACTION_CDN_CLOUDFLARE:
638 case self::ACTION_CRAWLER:
639 case self::ACTION_PRESET:
640 case self::ACTION_IMPORT:
641 case self::ACTION_REPORT:
642 case self::ACTION_CSS:
643 case self::ACTION_UCSS:
644 case self::ACTION_VPI:
645 case self::ACTION_CONF:
646 case self::ACTION_ACTIVATION:
647 case self::ACTION_HEALTH:
648 case self::ACTION_SAVE_SETTINGS: // Save settings
649 if ($_can_option && !$_is_network_admin) {
650 self::$_action = $action;
651 }
652 return;
653
654 case self::ACTION_PURGE:
655 case self::ACTION_DEBUG2:
656 if ($_can_network_option || $_can_option) {
657 self::$_action = $action;
658 }
659 return;
660
661 case Core::ACTION_DISMISS:
662 /**
663 * Non ajax call can dismiss too
664 *
665 * @since 2.9
666 */
667 // if ( self::is_ajax() ) {
668 self::$_action = $action;
669 // }
670 return;
671
672 default:
673 Debug2::debug('[Router] LSCWP_CTRL match failed: ' . $action);
674 return;
675 }
676 }
677
678 /**
679 * Verify nonce
680 *
681 * @since 1.1.0
682 * @access public
683 * @param string $action
684 * @return bool
685 */
686 public function verify_nonce( $action ) {
687 if (!isset($_REQUEST[self::NONCE]) || !wp_verify_nonce($_REQUEST[self::NONCE], $action)) {
688 return false;
689 } else {
690 return true;
691 }
692 }
693
694 /**
695 * Check if the ip is in the range
696 *
697 * @since 1.1.0
698 * @access public
699 */
700 public function ip_access( $ip_list ) {
701 if (!$ip_list) {
702 return false;
703 }
704 if (!isset(self::$_ip)) {
705 self::$_ip = self::get_ip();
706 }
707
708 if (!self::$_ip) {
709 return false;
710 }
711 // $uip = explode('.', $_ip);
712 // if(empty($uip) || count($uip) != 4) Return false;
713 // foreach($ip_list as $key => $ip) $ip_list[$key] = explode('.', trim($ip));
714 // foreach($ip_list as $key => $ip) {
715 // if(count($ip) != 4) continue;
716 // for($i = 0; $i <= 3; $i++) if($ip[$i] == '*') $ip_list[$key][$i] = $uip[$i];
717 // }
718 return in_array(self::$_ip, $ip_list);
719 }
720
721 /**
722 * Get client ip
723 *
724 * @since 1.1.0
725 * @since 1.6.5 changed to public
726 * @access public
727 * @return string
728 */
729 public static function get_ip() {
730 $_ip = '';
731 // if ( function_exists( 'apache_request_headers' ) ) {
732 // $apache_headers = apache_request_headers();
733 // $_ip = ! empty( $apache_headers['True-Client-IP'] ) ? $apache_headers['True-Client-IP'] : false;
734 // if ( ! $_ip ) {
735 // $_ip = ! empty( $apache_headers['X-Forwarded-For'] ) ? $apache_headers['X-Forwarded-For'] : false;
736 // $_ip = explode( ',', $_ip );
737 // $_ip = $_ip[ 0 ];
738 // }
739
740 // }
741
742 if (!$_ip) {
743 $_ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : false;
744 }
745 return $_ip;
746 }
747
748 /**
749 * Check if opcode cache is enabled
750 *
751 * @since 1.8.2
752 * @access public
753 */
754 public static function opcache_enabled() {
755 return function_exists('opcache_reset') && ini_get('opcache.enable');
756 }
757
758 /**
759 * Check if opcode cache is restricted and file that is requesting.
760 * https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.restrict-api
761 *
762 * @since 7.3
763 * @access public
764 */
765 public static function opcache_restricted($file)
766 {
767 $restrict_value = ini_get('opcache.restrict_api');
768 if ($restrict_value) {
769 if ( !$file || false === strpos($restrict_value, $file) ) {
770 return true;
771 }
772 }
773
774 return false;
775 }
776
777 /**
778 * Handle static files
779 *
780 * @since 3.0
781 */
782 public function serve_static() {
783 if (!empty($_SERVER['SCRIPT_URI'])) {
784 if (strpos($_SERVER['SCRIPT_URI'], LITESPEED_STATIC_URL . '/') !== 0) {
785 return;
786 }
787 $path = substr($_SERVER['SCRIPT_URI'], strlen(LITESPEED_STATIC_URL . '/'));
788 } elseif (!empty($_SERVER['REQUEST_URI'])) {
789 $static_path = parse_url(LITESPEED_STATIC_URL, PHP_URL_PATH) . '/';
790 if (strpos($_SERVER['REQUEST_URI'], $static_path) !== 0) {
791 return;
792 }
793 $path = substr(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), strlen($static_path));
794 } else {
795 return;
796 }
797
798 $path = explode('/', $path, 2);
799
800 if (empty($path[0]) || empty($path[1])) {
801 return;
802 }
803
804 switch ($path[0]) {
805 case 'avatar':
806 $this->cls('Avatar')->serve_static($path[1]);
807 break;
808
809 case 'localres':
810 $this->cls('Localization')->serve_static($path[1]);
811 break;
812
813 default:
814 break;
815 }
816 }
817
818 /**
819 * Handle all request actions from main cls
820 *
821 * This is different than other handlers
822 *
823 * @since 3.0
824 * @access public
825 */
826 public function handler( $cls ) {
827 if (!in_array($cls, self::$_HANDLERS)) {
828 return;
829 }
830
831 return $this->cls($cls)->handler();
832 }
833 }
834