PATH:
home
/
nappmpmd
/
bestyment.online
/
wp-content
/
plugins
/
tenweb-speed-optimizer
/
includes
/
WebPageCache
<?php namespace TenWebOptimizer\WebPageCache; use TenWebOptimizer\OptimizerUtils; /* * Base class other (more-specific) classes inherit from. */ if (!defined('ABSPATH')) { exit; } /** * This class will work with wp hooks/filter. Will decide when to clear cache, enable/disable web caching, etc. * * */ class OptimizerWebPageCacheWP { protected static $instance = null; public $wp_config_file_path = ABSPATH . '/wp-config.php'; public $page_cache_config_dir = WP_CONTENT_DIR . '/10web-page-cache-config'; public $wp_cache_define = "define( 'WP_CACHE', true );\ndefine( 'TWO_PLUGIN_DIR_CACHE', '" . TENWEB_SO_PLUGIN_DIR . "' );"; public $advanced_cache_path = WP_CONTENT_DIR . '/advanced-cache.php'; public function __construct() { if (isset($_GET['action']) && $_GET['action'] === 'two_clear_page_cache') { // phpcs:ignore add_action('admin_init', [ $this, 'maybe_clear_page_cache' ]); } global $TwoSettings; if ($TwoSettings->get_settings('two_page_cache') === 'on' && get_option('show_on_front') === 'posts') { add_action('transition_post_status', [$this, 'transition_post_status'], 10, 3); } if ((!isset($_GET['action']) || $_GET['action'] != 'deactivate') // phpcs:ignore && (!isset($_GET['rest_route']) || $_GET['rest_route'] != '/tenweb_so/v1/set_modes')) { // phpcs:ignore add_action('update_option_two_settings', [ $this, 'enable_disable_page_cache' ], 10, 3); } add_filter('page_row_actions', [$this, 'post_row_actions'], 10, 2); add_filter('post_row_actions', [$this, 'post_row_actions'], 10, 2); if ($TwoSettings->get_settings('two_page_cache') === 'on' && $TwoSettings->get_settings('two_page_cache_user') === 'on') { if (is_user_logged_in()) { // phpcs:ignore WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___COOKIE, WordPress.Security.ValidatedSanitizedInput.InputNotValidated $logged_in_cookie = sanitize_text_field($_COOKIE[LOGGED_IN_COOKIE]); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.cookies_setcookie setcookie('tenweb_so_page_cache_hash', md5($logged_in_cookie), time() + (int) $TwoSettings->get_settings('two_page_cache_life_time'), COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true); } else { if (isset($_COOKIE['tenweb_so_page_cache_hash'])) { // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.cookies_setcookie setcookie('tenweb_so_page_cache_hash', '', time() + (int) $TwoSettings->get_settings('two_page_cache_life_time'), COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true); } } } } public function delete_all_cache() { OptimizerWebPageCache::delete_all_cached_pages(); } public function post_updated($post_id, $post_after, $post_before) { OptimizerWebPageCache::delete_cache_by_post_id($post_id); } public function enable_disable_page_cache($old_value, $value, $option) { $value = json_decode($value, true); $value = (isset($value[ 'two_page_cache' ])) ? $value['two_page_cache'] : ''; if ($value === 'on') { $this->store_page_cache_configs(); if (!file_exists(WP_CONTENT_DIR . '/advanced-cache.php')) { $this->enable_page_cache(); } else { $file_content = file_get_contents(WP_CONTENT_DIR . '/advanced-cache.php'); if (strpos($file_content, 'TENWEB_SO_ADVANCED_CACHE') === false) { $this->enable_page_cache(); } elseif (!defined('WP_CACHE') || !WP_CACHE || !defined('TWO_PLUGIN_DIR_CACHE')) { $this->add_wp_cache_constant(); } } } else { $this->disable_page_cache(); } } public function enable_page_cache() { if ($this->add_wp_cache_constant() === false) { return false; } return copy(TENWEB_SO_PLUGIN_DIR . 'includes/WebPageCache/advanced-cache.php', $this->advanced_cache_path); } public function disable_page_cache() { if ($this->remove_wp_cache_constant() === false) { return false; } if ($this->delete_page_cache_configs() === false) { return false; } if (!file_exists($this->advanced_cache_path)) { return true; } return unlink($this->advanced_cache_path); // phpcs:ignore } public function add_wp_cache_constant() { // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_is_writable if (!is_writable($this->wp_config_file_path) || !is_readable($this->wp_config_file_path)) { return false; } // Save untouched version of the file $original_file_content = file_get_contents($this->wp_config_file_path); // phpcs:ignore if ($original_file_content === false) { error_log('10Web Speed Optimizer: Failed to read original wp-config.php file'); // phpcs:ignore return false; } $file_content = $original_file_content; // Remove our constants to clear the file in case if somebody removed the WP_CACHE define $file_content = preg_replace('/# BEGIN WP Cache by 10Web[\s\S]*# END WP Cache by 10Web/', '', $file_content); if ($file_content === null) { error_log('10Web Speed Optimizer: Failed to remove existing WP Cache constants'); // phpcs:ignore return false; } // Remove WP_CACHE defined by others $file_content = OptimizerUtils::delete_define('WP_CACHE', $file_content); if (strpos($file_content, '<?php') === false) { // Restore original file content file_put_contents($this->wp_config_file_path, $original_file_content); // phpcs:ignore error_log('10Web Speed Optimizer: Failed to remove existing WP_CACHE define'); // phpcs:ignore return false; } // Add new defines $replacement = "<?php\n# BEGIN WP Cache by 10Web\n" . $this->wp_cache_define . "\n# END WP Cache by 10Web\n"; $file_content = preg_replace('@<\?php\s*@i', $replacement, $file_content, 1); if ($file_content === null) { // Restore original file content file_put_contents($this->wp_config_file_path, $original_file_content); // phpcs:ignore error_log('10Web Speed Optimizer: Failed to add new WP Cache constants'); // phpcs:ignore return false; } // Ensure essential WordPress constants are still present if (strpos($file_content, 'require_once') === false || strpos($file_content, 'ABSPATH') === false) { file_put_contents($this->wp_config_file_path, $original_file_content); // phpcs:ignore error_log('10Web Speed Optimizer: Essential WordPress constants missing after modification'); // phpcs:ignore return false; } // Write to temporary file first for atomic operation $temp_file = $this->wp_config_file_path . '.tmp.' . uniqid(); $write_result = file_put_contents($temp_file, $file_content); // phpcs:ignore if ($write_result === false) { // Clean up temp file and restore original content if (file_exists($temp_file)) { unlink($temp_file); // phpcs:ignore } file_put_contents($this->wp_config_file_path, $original_file_content); // phpcs:ignore error_log('10Web Speed Optimizer: Failed to write modified content to temporary file'); // phpcs:ignore return false; } // Atomic rename operation $rename_result = rename($temp_file, $this->wp_config_file_path); // phpcs:ignore if (!$rename_result) { // Clean up temp file and restore original content unlink($temp_file); // phpcs:ignore file_put_contents($this->wp_config_file_path, $original_file_content); // phpcs:ignore error_log('10Web Speed Optimizer: Failed to rename temporary file to wp-config.php'); // phpcs:ignore return false; } return true; } public function remove_wp_cache_constant() { // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.file_ops_is_writable if (!is_writable($this->wp_config_file_path) || !is_readable($this->wp_config_file_path)) { return false; } // Save untouched version of the file $original_file_content = file_get_contents($this->wp_config_file_path); // phpcs:ignore if ($original_file_content === false) { error_log('10Web Speed Optimizer: Failed to read original wp-config.php file'); // phpcs:ignore return false; } $file_content = $original_file_content; $file_content = preg_replace('/# BEGIN WP Cache by 10Web[\s\S]*# END WP Cache by 10Web/', '', $file_content); if ($file_content === null) { error_log('10Web Speed Optimizer: Failed to remove WP Cache constants'); // phpcs:ignore return false; } // Write to temporary file first for atomic operation $temp_file = $this->wp_config_file_path . '.tmp.' . uniqid(); $write_result = file_put_contents($temp_file, $file_content); // phpcs:ignore if ($write_result === false) { // Clean up temp file and restore original content if (file_exists($temp_file)) { unlink($temp_file); // phpcs:ignore } file_put_contents($this->wp_config_file_path, $original_file_content); // phpcs:ignore error_log('10Web Speed Optimizer: Failed to write modified content to temporary file'); // phpcs:ignore return false; } // Atomic rename operation $rename_result = rename($temp_file, $this->wp_config_file_path); // phpcs:ignore if (!$rename_result) { // Clean up temp file and restore original content unlink($temp_file); // phpcs:ignore file_put_contents($this->wp_config_file_path, $original_file_content); // phpcs:ignore error_log('10Web Speed Optimizer: Failed to rename temporary file to wp-config.php'); // phpcs:ignore return false; } return true; } public function store_page_cache_configs() { if (!is_dir($this->page_cache_config_dir) && !mkdir($concurrentDirectory = $this->page_cache_config_dir, 0777) && !is_dir($concurrentDirectory)) { // phpcs:ignore return false; } $configs = []; $TwoSettings = new \TenWebOptimizer\OptimizerSettings(); $configs['two_settings'] = json_encode($TwoSettings->get_settings()); // phpcs:ignore return (bool) file_put_contents($this->page_cache_config_dir . '/config.json', json_encode($configs)); // phpcs:ignore } public function delete_page_cache_configs() { if (file_exists($this->page_cache_config_dir . '/config.json')) { return unlink($this->page_cache_config_dir . '/config.json'); // phpcs:ignore } return true; } public function maybe_clear_page_cache() { // Check user capabilities if (!current_user_can('manage_options')) { wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'tenweb-speed-optimizer'), 403); } // Verify nonce $nonce = isset($_GET['_wpnonce']) ? sanitize_text_field($_GET['_wpnonce']) : ''; if (!wp_verify_nonce($nonce, 'two_clear_page_cache')) { wp_die(esc_html__('Security check failed. Please try again.', 'tenweb-speed-optimizer'), 403); } if (!empty($_GET['permalink'])) { $permalink = sanitize_url($_GET['permalink']); // phpcs:ignore // Validate URL - reject if contains dangerous characters instead of trying to fix it if (!self::is_url_safe_for_cache_clear($permalink)) { status_header(400); wp_die(esc_html__('Invalid URL: contains dangerous characters.', 'tenweb-speed-optimizer'), 400); } // Validate that the cache directory path stays within allowed boundaries $cache_dir = OptimizerWebPageCache::get_cache_dir_for_page_from_url($permalink); $cache_dir = self::validate_cache_path($cache_dir); if ($cache_dir === false) { wp_die(esc_html__('Invalid cache path detected.', 'tenweb-speed-optimizer'), 403); } OptimizerUtils::clear_cloudflare_cache([$permalink]); OptimizerWebPageCache::delete_cache_by_url($permalink); } $redirect_to = (!empty($_SERVER['HTTP_REFERER'])) ? sanitize_text_field($_SERVER['HTTP_REFERER']) : '/wp-admin/edit.php'; wp_safe_redirect($redirect_to); die; } /** * Validate URL for cache clearing - reject URLs with dangerous characters * Instead of trying to fix the URL, we reject it to prevent path traversal attacks * * @param string $url The URL to validate * * @return bool True if URL is safe, false if it contains dangerous characters */ private static function is_url_safe_for_cache_clear($url) { if (empty($url)) { return false; } $parsed_url = wp_parse_url($url); // Must have host and path if (!isset($parsed_url['host']) || !isset($parsed_url['path'])) { return false; } $path = $parsed_url['path']; // Reject if contains directory traversal sequences if (strpos($path, '../') !== false || strpos($path, '..\\') !== false) { return false; } // Reject if contains null bytes if (strpos($path, "\0") !== false) { return false; } // Reject if path contains encoded directory traversal if (strpos($path, '%2e%2e%2f') !== false || strpos($path, '%2e%2e\\') !== false) { return false; } // URL is safe return true; } /** * Validate that cache path stays within TENWEB_SO_PAGE_CACHE_DIR * * @param string $cache_dir The cache directory path to validate * * @return string|false Returns normalized path if valid, false otherwise */ private static function validate_cache_path($cache_dir) { if (empty($cache_dir)) { return false; } // Normalize paths for comparison $cache_dir = rtrim($cache_dir, '/') . '/'; $allowed_dir = rtrim(TENWEB_SO_PAGE_CACHE_DIR, '/') . '/'; // First check: ensure the path starts with the allowed directory (string comparison) // This works even if directories don't exist yet if (strpos($cache_dir, $allowed_dir) !== 0) { return false; } // Second check: use realpath if directory exists to resolve symlinks and normalize $real_cache_dir = realpath($cache_dir); $real_allowed_dir = realpath($allowed_dir); // If both paths exist, verify the resolved path is still within allowed directory if ($real_cache_dir !== false && $real_allowed_dir !== false) { if (strpos($real_cache_dir, $real_allowed_dir) !== 0) { return false; } return $real_cache_dir; } // If directory doesn't exist yet, return the normalized path if it passed string check // This allows validation of paths that will be created return $cache_dir; } public function post_row_actions($actions, $post) { global $TwoSettings; if ($TwoSettings->get_settings('two_page_cache') !== 'on') { return $actions; } $url = wp_nonce_url(admin_url('admin-post.php?action=two_clear_page_cache&permalink=' . get_permalink($post)), 'two_clear_page_cache'); $actions['two_clear_page_cache'] = sprintf('<a href="%s">%s</a>', $url, __('Clear page cache', 'tenweb-speed-optimizer')); return $actions; } public function transition_post_status($new_status, $old_status, $post) { if ($post->post_type !== 'post') { return; } if ($new_status === $old_status) { return; } // if status changed from publish (e.g. to trash) or to publish (e.g. from draft to publish) clear page cache if ($new_status === 'publish' || $old_status === 'publish') { OptimizerUtils::clear_cloudflare_cache([get_home_url()]); OptimizerWebPageCache::delete_cache_by_url(get_home_url()); } } public static function get_instance() { if (null == self::$instance) { self::$instance = new self(); } return self::$instance; } }
[-] OptimizerWebPageValidations.php
[edit]
[-] OptimizerWebPageCache.php
[edit]
[+]
..
[-] advanced-cache.php
[edit]
[-] OptimizerWebPageCacheWP.php
[edit]