$i ) ); $url = html_entity_decode( $link ); exit( "" ); } /** * Check if can run optimize * * @since 1.3 * @since 2.3.1 Relocated from cdn.cls * @access public */ public function can_optm() { $can = true; if ( is_user_logged_in() && $this->conf( self::O_OPTM_GUEST_ONLY ) ) { $can = false; } elseif ( is_admin() ) { $can = false; } elseif ( is_feed() ) { $can = false; } elseif ( is_preview() ) { $can = false; } elseif ( self::is_ajax() ) { $can = false; } if ( self::_is_login_page() ) { Debug2::debug( '[Router] Optm bypassed: login/reg page' ); $can = false; } $can_final = apply_filters( 'litespeed_can_optm', $can ); if ( $can_final != $can ) { Debug2::debug( '[Router] Optm bypassed: filter' ); } return $can_final; } /** * Check referer page to see if its from admin * * @since 2.4.2.1 * @access public */ public static function from_admin() { return ! empty( $_SERVER[ 'HTTP_REFERER' ] ) && strpos( $_SERVER[ 'HTTP_REFERER' ], get_admin_url() ) === 0; } /** * Check if it can use CDN replacement * * @since 1.2.3 * @since 2.3.1 Relocated from cdn.cls * @access public */ public static function can_cdn() { $can = true; if ( is_admin() ) { if ( ! self::is_ajax() ) { Debug2::debug2( '[Router] CDN bypassed: is not ajax call' ); $can = false; } if ( self::from_admin() ) { Debug2::debug2( '[Router] CDN bypassed: ajax call from admin' ); $can = false; } } elseif ( is_feed() ) { $can = false; } elseif ( is_preview() ) { $can = false; } /** * Bypass cron to avoid deregister jq notice `Do not deregister the jquery-core script in the administration area.` * @since 2.7.2 */ if ( defined( 'DOING_CRON' ) ) { $can = false; } /** * Bypass login/reg page * @since 1.6 */ if ( self::_is_login_page() ) { Debug2::debug( '[Router] CDN bypassed: login/reg page' ); $can = false; } /** * Bypass post/page link setting * @since 2.9.8.5 */ $rest_prefix = function_exists( 'rest_get_url_prefix' ) ? rest_get_url_prefix() : apply_filters( 'rest_url_prefix', 'wp-json' ); if ( strpos( $_SERVER[ 'REQUEST_URI' ], $rest_prefix . '/wp/v2/media' ) !== false && strpos( $_SERVER[ 'HTTP_REFERER' ], 'wp-admin') !== false ) { Debug2::debug( '[Router] CDN bypassed: wp-json on admin page' ); $can = false; } $can_final = apply_filters( 'litespeed_can_cdn', $can ); if ( $can_final != $can ) { Debug2::debug( '[Router] CDN bypassed: filter' ); } return $can_final; } /** * Check if is login page or not * * @since 2.3.1 * @access protected */ protected static function _is_login_page() { if ( in_array( $GLOBALS[ 'pagenow' ], array( 'wp-login.php', 'wp-register.php' ), true ) ) { return true; } return false; } /** * UCSS/Crawler role simulator * * @since 1.9.1 * @since 3.3 Renamed from `is_crawler_role_simulation` */ public function is_role_simulation() { if( is_admin() ) { return; } if ( empty( $_COOKIE[ 'litespeed_role' ] ) || empty( $_COOKIE[ 'litespeed_hash' ] ) ) { return; } Debug2::debug( '[Router] starting role validation' ); // Check if is from crawler // if ( empty( $_SERVER[ 'HTTP_USER_AGENT' ] ) || strpos( $_SERVER[ 'HTTP_USER_AGENT' ], Crawler::FAST_USER_AGENT ) !== 0 ) { // Debug2::debug( '[Router] user agent not match' ); // return; // } // Hash validation $hash = self::get_option( self::ITEM_HASH ); if ( ! $hash || $_COOKIE[ 'litespeed_hash' ] != $hash ) { Debug2::debug( '[Router] hash not match ' . $_COOKIE[ 'litespeed_hash' ] . ' != ' . $hash ); return; } $role_uid = $_COOKIE[ 'litespeed_role' ]; Debug2::debug( '[Router] role simulate litespeed_role uid ' . $role_uid ); // wp_set_current_user( $role_uid ); } /** * Get a security hash * * @since 3.3 */ public static function get_hash() { // Reuse previous hash if existed $hash = self::get_option( self::ITEM_HASH ); if ( $hash ) { return $hash; } $hash = Str::rrand( 6 ); self::update_option( self::ITEM_HASH, $hash ); return $hash; } /** * Get user role * * @since 1.6.2 */ public static function get_role( $uid = null ) { if ( defined( 'LITESPEED_WP_ROLE' ) ) { return LITESPEED_WP_ROLE; } if ( $uid === null ) { $uid = get_current_user_id(); } $role = false; if ( $uid ) { $user = get_userdata( $uid ); if ( isset( $user->roles ) && is_array( $user->roles ) ) { $tmp = array_values( $user->roles ); $role = array_shift( $tmp ); } } Debug2::debug( '[Router] get_role: ' . $role ); if ( ! $role ) { return $role; // Guest user Debug2::debug( '[Router] role: guest' ); /** * Fix double login issue * The previous user init refactoring didn't fix this bcos this is in login process and the user role could change * @see https://github.com/litespeedtech/lscache_wp/commit/69e7bc71d0de5cd58961bae953380b581abdc088 * @since 2.9.8 Won't assign const if in login process */ if ( substr_compare( wp_login_url(), $GLOBALS[ 'pagenow' ], -strlen( $GLOBALS[ 'pagenow' ] ) ) === 0 ) { return $role; } } define( 'LITESPEED_WP_ROLE', $role ); return LITESPEED_WP_ROLE; } /** * Get frontend path * * @since 1.2.2 * @access public * @return boolean */ public static function frontend_path() { //todo: move to htaccess.cls ? if ( ! isset( self::$_frontend_path ) ) { $frontend = rtrim( ABSPATH, '/' ); // /home/user/public_html/frontend // get home path failed. Trac ticket #37668 (e.g. frontend:/blog backend:/wordpress) if ( ! $frontend ) { Debug2::debug( '[Router] No ABSPATH, generating from home option' ); $frontend = parse_url( get_option( 'home' ) ); $frontend = ! empty( $frontend[ 'path' ] ) ? $frontend[ 'path' ] : ''; $frontend = $_SERVER[ 'DOCUMENT_ROOT' ] . $frontend; } $frontend = realpath( $frontend ); self::$_frontend_path = $frontend; } return self::$_frontend_path; } /** * Check if ESI is enabled or not * * @since 1.2.0 * @access public * @return boolean */ public function esi_enabled() { if ( ! isset( self::$_esi_enabled ) ) { self::$_esi_enabled = defined( 'LITESPEED_ON' ) && $this->conf( self::O_ESI ); if( ! empty( $_REQUEST[ self::ACTION ] ) ) { self::$_esi_enabled = false; } } return self::$_esi_enabled; } /** * Check if crawler is enabled on server level * * @since 1.1.1 * @access public */ public static function can_crawl() { if ( isset( $_SERVER[ 'X-LSCACHE' ] ) && strpos( $_SERVER[ 'X-LSCACHE' ], 'crawler' ) === false ) { return false; } // CLI will bypass this check as crawler library can always do the 428 check if ( defined( 'LITESPEED_CLI' ) ) { return true; } return true; } /** * Check action * * @since 1.1.0 * @access public * @return string */ public static function get_action() { if ( ! isset( self::$_action ) ) { self::$_action = false; self::cls()->verify_action(); if ( self::$_action ) { defined( 'LSCWP_LOG' ) && Debug2::debug( '[Router] LSCWP_CTRL verified: ' . var_export( self::$_action, true ) ); } } return self::$_action; } /** * Check if is logged in * * @since 1.1.3 * @access public * @return boolean */ public static function is_logged_in() { if ( ! isset( self::$_is_logged_in ) ) { self::$_is_logged_in = is_user_logged_in(); } return self::$_is_logged_in; } /** * Check if is ajax call * * @since 1.1.0 * @access public * @return boolean */ public static function is_ajax() { if ( ! isset( self::$_is_ajax ) ) { self::$_is_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX; } return self::$_is_ajax; } /** * Check if is admin ip * * @since 1.1.0 * @access public * @return boolean */ public function is_admin_ip() { if ( ! isset( self::$_is_admin_ip ) ) { $ips = $this->conf( self::O_DEBUG_IPS ); self::$_is_admin_ip = $this->ip_access( $ips ); } return self::$_is_admin_ip; } /** * Get type value * * @since 1.6 * @access public */ public static function verify_type() { if ( empty( $_REQUEST[ self::TYPE ] ) ) { Debug2::debug( '[Router] no type', 2 ); return false; } Debug2::debug( '[Router] parsed type: ' . $_REQUEST[ self::TYPE ], 2 ); return $_REQUEST[ self::TYPE ]; } /** * Check privilege and nonce for the action * * @since 1.1.0 * @access private */ private function verify_action() { if ( empty( $_REQUEST[ Router::ACTION ] ) ) { Debug2::debug2( '[Router] LSCWP_CTRL bypassed empty' ); return; } $action = stripslashes($_REQUEST[ Router::ACTION ]); if ( ! $action ) { return; } $_is_public_action = false; // Each action must have a valid nonce unless its from admin ip and is public action // Validate requests nonce (from admin logged in page or cli) if ( ! $this->verify_nonce( $action ) ) { // check if it is from admin ip if ( ! $this->is_admin_ip() ) { Debug2::debug( '[Router] LSCWP_CTRL query string - did not match admin IP: ' . $action ); return; } // check if it is public action if ( ! in_array( $action, array( Core::ACTION_QS_NOCACHE, Core::ACTION_QS_PURGE, Core::ACTION_QS_PURGE_SINGLE, Core::ACTION_QS_SHOW_HEADERS, Core::ACTION_QS_PURGE_ALL, Core::ACTION_QS_PURGE_EMPTYCACHE, ) ) ) { Debug2::debug( '[Router] LSCWP_CTRL query string - did not match admin IP Actions: ' . $action ); return; } $_is_public_action = true; } /* Now it is a valid action, lets log and check the permission */ Debug2::debug( '[Router] LSCWP_CTRL: ' . $action ); // OK, as we want to do something magic, lets check if its allowed $_is_multisite = is_multisite(); $_is_network_admin = $_is_multisite && is_network_admin(); $_can_network_option = $_is_network_admin && current_user_can( 'manage_network_options' ); $_can_option = current_user_can( 'manage_options' ); switch ( $action ) { // Save htaccess case self::ACTION_SAVE_HTACCESS: if ( ( ! $_is_multisite && $_can_option ) || $_can_network_option ) { self::$_action = $action; } return; // Save network settings case self::ACTION_SAVE_SETTINGS_NETWORK: if ( $_can_network_option ) { self::$_action = $action; } return; case Core::ACTION_PURGE_BY: if ( defined( 'LITESPEED_ON' ) && ( $_can_network_option || $_can_option || self::is_ajax() ) ) {//here may need more security self::$_action = $action; } return; case self::ACTION_DB_OPTM: if ( $_can_network_option || $_can_option ) { self::$_action = $action; } return; case Core::ACTION_PURGE_EMPTYCACHE:// todo: moved to purge.cls type action if ( defined( 'LITESPEED_ON' ) && ( $_can_network_option || ( ! $_is_multisite && $_can_option ) ) ) { self::$_action = $action; } return; case Core::ACTION_QS_NOCACHE: case Core::ACTION_QS_PURGE: case Core::ACTION_QS_PURGE_SINGLE: case Core::ACTION_QS_SHOW_HEADERS: case Core::ACTION_QS_PURGE_ALL: case Core::ACTION_QS_PURGE_EMPTYCACHE: if ( defined( 'LITESPEED_ON' ) && ( $_is_public_action || self::is_ajax() ) ) { self::$_action = $action; } return; case self::ACTION_PLACEHOLDER: case self::ACTION_AVATAR: case self::ACTION_IMG_OPTM: case self::ACTION_CLOUD: case self::ACTION_CDN_CLOUDFLARE: case self::ACTION_CRAWLER: case self::ACTION_IMPORT: case self::ACTION_REPORT: case self::ACTION_CSS: case self::ACTION_CONF: case self::ACTION_ACTIVATION: case self::ACTION_HEALTH: case self::ACTION_SAVE_SETTINGS: // Save settings if ( $_can_option && ! $_is_network_admin ) { self::$_action = $action; } return; case self::ACTION_PURGE: case self::ACTION_DEBUG2: if ( $_can_network_option || $_can_option ) { self::$_action = $action; } return; case Core::ACTION_DISMISS: /** * Non ajax call can dismiss too * @since 2.9 */ // if ( self::is_ajax() ) { self::$_action = $action; // } return; default: Debug2::debug( '[Router] LSCWP_CTRL match falied: ' . $action ); return; } } /** * Verify nonce * * @since 1.1.0 * @access private * @param string $action * @return bool */ private function verify_nonce( $action ) { if ( ! isset( $_REQUEST[ Router::NONCE ] ) || ! wp_verify_nonce( $_REQUEST[ Router::NONCE ], $action ) ) { return false; } else{ return true; } } /** * Check if the ip is in the range * * @since 1.1.0 * @access public */ public function ip_access( $ip_list ) { if ( ! $ip_list ) { return false; } if ( ! isset( self::$_ip ) ) { self::$_ip = self::get_ip(); } // $uip = explode('.', $_ip); // if(empty($uip) || count($uip) != 4) Return false; // foreach($ip_list as $key => $ip) $ip_list[$key] = explode('.', trim($ip)); // foreach($ip_list as $key => $ip) { // if(count($ip) != 4) continue; // for($i = 0; $i <= 3; $i++) if($ip[$i] == '*') $ip_list[$key][$i] = $uip[$i]; // } return in_array( self::$_ip, $ip_list ); } /** * Get client ip * * @since 1.1.0 * @since 1.6.5 changed to public * @access public * @return string */ public static function get_ip() { $_ip = ''; if ( function_exists( 'apache_request_headers' ) ) { $apache_headers = apache_request_headers(); $_ip = ! empty( $apache_headers['True-Client-IP'] ) ? $apache_headers['True-Client-IP'] : false; if ( ! $_ip ) { $_ip = ! empty( $apache_headers['X-Forwarded-For'] ) ? $apache_headers['X-Forwarded-For'] : false; $_ip = explode( ',', $_ip ); $_ip = $_ip[ 0 ]; } } if ( ! $_ip ) { $_ip = ! empty( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : false; } return $_ip; } /** * Check if opcode cache is enabled * * @since 1.8.2 * @access public */ public static function opcache_enabled() { return function_exists( 'opcache_reset' ) && ini_get( 'opcache.enable' ); } /** * Handle static files * * @since 3.0 */ public function serve_static() { if ( ! empty( $_SERVER[ 'SCRIPT_URI' ] ) ) { if ( strpos( $_SERVER[ 'SCRIPT_URI' ], LITESPEED_STATIC_URL . '/' ) !== 0 ) { return; } $path = substr( $_SERVER[ 'SCRIPT_URI' ], strlen( LITESPEED_STATIC_URL . '/' ) ); } elseif ( ! empty( $_SERVER[ 'REQUEST_URI' ] ) ) { $static_path = parse_url( LITESPEED_STATIC_URL, PHP_URL_PATH ) . '/'; if ( strpos( $_SERVER[ 'REQUEST_URI' ], $static_path ) !== 0 ) { return; } $path = substr( parse_url( $_SERVER[ 'REQUEST_URI' ], PHP_URL_PATH ), strlen( $static_path ) ); } else { return; } $path = explode( '/', $path, 2 ); if ( empty( $path[ 0 ] ) || empty( $path[ 1 ] ) ) { return; } switch ( $path[ 0 ] ) { case 'avatar': $this->cls( 'Avatar' )->serve_static( $path[ 1 ] ); break; default : break; } } /** * Handle all request actions from main cls * * This is different than other handlers * * @since 3.0 * @access public */ public function handler( $cls ) { if ( ! in_array( $cls, self::$_HANDLERS ) ) { return; } return $this->cls( $cls )->handler(); } }