PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.0.2
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.0.2
1.3.3 1.3.2 1.3.1 1.3.0 1.2.4 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 All 29 releases
xspeed / includes / advanced-cache.php

advanced-cache.php in xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN 1.0.2, at includes/advanced-cache.php

91 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * XSPEED_DROPIN
4 * Drop-in cache loader. Serves cached HTML before WordPress fully boots.
5 *
6 * IMPORTANT: This file is included by wp-settings.php BEFORE
7 * wp-includes/formatting.php and wp-includes/load.php are loaded, so NO
8 * WordPress functions (sanitize_text_field, wp_unslash, is_admin,
9 * HOUR_IN_SECONDS, etc.) are available here. Use raw PHP only.
10 *
11 * @package XSpeed
12 */
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 // Only handle plain GET requests.
19 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Drop-in runs before wp-includes/formatting.php loads, so wp_unslash() and sanitize_text_field() are unavailable. Value is upper-cased and matched against the literal string 'GET'; never echoed, never executed.
20 $xspeed_method = isset( $_SERVER['REQUEST_METHOD'] ) ? strtoupper( (string) $_SERVER['REQUEST_METHOD'] ) : '';
21 if ( 'GET' !== $xspeed_method ) {
22 return;
23 }
24
25 // Skip cached query-string requests (search, pagination via ?, etc.).
26 if ( ! empty( $_SERVER['QUERY_STRING'] ) ) {
27 return;
28 }
29
30 // Honor explicit bypass header. xSpeed's own benchmark REST endpoint
31 // sends `X-XSpeed-Bypass: 1` so we can measure uncached TTFB for the
32 // before/after comparison on the dashboard. Harmless if a third party
33 // sends it — they just get an uncached response.
34 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Drop-in runs before WP loads. Value is only used as an isset() check + literal string comparison, never echoed.
35 if ( ! empty( $_SERVER['HTTP_X_XSPEED_BYPASS'] ) ) {
36 return;
37 }
38
39 if ( ! isset( $_SERVER['REQUEST_URI'] ) ) {
40 return;
41 }
42
43 // Raw-PHP sanitization: strip null bytes only. This value is used for
44 // substring comparisons and as input to md5() — never echoed, never
45 // executed, never written to disk as data. Magic quotes was removed in
46 // PHP 5.4 and the plugin requires PHP 7.4+, so no unslashing is needed.
47 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Drop-in runs before wp_unslash()/sanitize_text_field() are loaded; null-byte strip is the strongest sanitizer available pre-WP-bootstrap. Value is only used for substring comparison and as md5() input.
48 $xspeed_request_uri = str_replace( "\0", '', (string) $_SERVER['REQUEST_URI'] );
49
50 // Skip admin / login requests.
51 if ( false !== strpos( $xspeed_request_uri, '/wp-admin' ) || false !== strpos( $xspeed_request_uri, '/wp-login' ) ) {
52 return;
53 }
54
55 // Skip logged-in users and comment authors — never serve a cached page to
56 // someone who has a session cookie. Reading raw cookies; we only inspect
57 // names, not values.
58 if ( ! empty( $_COOKIE ) ) {
59 foreach ( $_COOKIE as $xspeed_cookie_name => $xspeed_cookie_value ) {
60 unset( $xspeed_cookie_value );
61 $xspeed_cookie_name = (string) $xspeed_cookie_name;
62 if ( 0 === strpos( $xspeed_cookie_name, 'wordpress_logged_in' )
63 || 0 === strpos( $xspeed_cookie_name, 'comment_author_' )
64 || 0 === strpos( $xspeed_cookie_name, 'wp-postpass_' ) ) {
65 return;
66 }
67 }
68 }
69
70 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Drop-in runs before wp_unslash()/sanitize_text_field() are loaded. Value is filtered through a strict allowlist regex below (letters, digits, dot, hyphen, colon) and only used as md5() input for the cache key.
71 $xspeed_host = isset( $_SERVER['HTTP_HOST'] ) ? (string) $_SERVER['HTTP_HOST'] : 'default';
72 $xspeed_host = str_replace( "\0", '', $xspeed_host );
73 // Restrict host to a safe charset (letters, digits, dot, hyphen, colon for port).
74 $xspeed_host = preg_replace( '/[^a-zA-Z0-9.\-:]/', '', $xspeed_host );
75
76 $xspeed_path_only = strtok( $xspeed_request_uri, '?' );
77 $xspeed_cache_key = md5( $xspeed_host . $xspeed_path_only );
78 $xspeed_cache_file = WP_CONTENT_DIR . '/cache/xspeed/' . $xspeed_cache_key . '.html';
79
80 if ( file_exists( $xspeed_cache_file ) ) {
81 // 24h TTL in seconds. HOUR_IN_SECONDS is a WordPress constant defined
82 // after this drop-in loads, so use a literal here.
83 $xspeed_age = time() - filemtime( $xspeed_cache_file );
84 if ( $xspeed_age < 86400 ) {
85 header( 'X-XSpeed-Cache: HIT' );
86 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile -- Drop-in runs before WP_Filesystem is available; readfile is optimal for streaming a static cache file to the visitor.
87 readfile( $xspeed_cache_file );
88 exit;
89 }
90 }
91