PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / 3.6.3
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score v3.6.3
trunk 1.0 1.0.1 1.1 1.1.1 1.1.2 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1 2.1.1 2.1.2 2.2 2.2.1 All 69 releases
powered-cache / includes / dropins / page-cache.php

page-cache.php in Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score 3.6.3, at includes/dropins/page-cache.php

683 lines 20.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Forked from https://github.com/tlovett1/simple-cache/
4 */
5
6 defined( 'ABSPATH' ) || exit;
7
8 $powered_cache_start_time = microtime( true );
9
10 // Don't cache robots.txt or htacesss
11 if ( strpos( $_SERVER['REQUEST_URI'], 'robots.txt' ) !== false || strpos( $_SERVER['REQUEST_URI'], '.htaccess' ) !== false ) {
12 powered_cache_add_cache_miss_header( "Uncacheable file" );
13
14 return;
15 }
16
17 // Don't cache non-GET requests
18 if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || 'GET' !== $_SERVER['REQUEST_METHOD'] ) {
19 powered_cache_add_cache_miss_header( "Invalid request method" );
20
21 return;
22 }
23
24 if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
25 $_SERVER['HTTP_USER_AGENT'] = '';
26 }
27
28 // Don't cache wp-admin
29 if ( is_admin() ) {
30 return;
31 }
32
33 $file_extension = $_SERVER['REQUEST_URI'];
34 $file_extension = preg_replace( '#^(.*?)\?.*$#', '$1', $file_extension );
35 $file_extension = trim( preg_replace( '#^.*\.(.*)$#', '$1', $file_extension ) );
36
37 // Don't cache disallowed extensions. Prevents wp-cron.php, xmlrpc.php, etc.
38 if ( ! preg_match( '#index\.php$#i', $_SERVER['REQUEST_URI'] ) && in_array( $file_extension, array( 'php', 'xml', 'xsl' ), true ) ) {
39 powered_cache_add_cache_miss_header( "Disallowed file extension" );
40
41 return;
42 }
43
44 if ( ! $GLOBALS['powered_cache_options']['enable_page_cache'] ) {
45 powered_cache_add_cache_miss_header( "Page Caching is not enabled" );
46
47 return;
48 }
49
50 if ( ! empty( $GLOBALS['powered_cache_options']['dev_mode'] ) ) {
51 powered_cache_add_cache_miss_header( "Dev mode is enabled" );
52
53 return;
54 }
55
56 if ( isset( $_GET['nopoweredcache'] ) && $_GET['nopoweredcache'] ) {
57 powered_cache_add_cache_miss_header( "Passing nopoweredcache with the query" );
58
59 return;
60 }
61
62 // Don't cache page with these user agents
63 if ( isset( $powered_cache_rejected_user_agents ) && ! empty( $powered_cache_rejected_user_agents ) ) {
64 $rejected_user_agents = implode( '|', $powered_cache_rejected_user_agents );
65 if ( ! empty( $rejected_user_agents ) && isset( $_SERVER['HTTP_USER_AGENT'] ) && preg_match( '#(' . $rejected_user_agents . ')#', $_SERVER['HTTP_USER_AGENT'] ) ) {
66 powered_cache_add_cache_miss_header( "Rejected user agent" );
67
68 return;
69 }
70 }
71
72 // dont cache mobile
73 if ( empty( $GLOBALS['powered_cache_options']['cache_mobile'] ) ) {
74 global $powered_cache_mobile_browsers, $powered_cache_mobile_prefixes;
75
76 $mobile_browsers = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_browsers ) ), ' ' );
77 $mobile_prefixes = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_prefixes ) ), ' ' );
78 // Don't cache if mobile detection is activated
79 if ( ( preg_match( '#^.*(' . $mobile_browsers . ').*#i', $_SERVER['HTTP_USER_AGENT'] ) || preg_match( '#^(' . $mobile_prefixes . ').*#i', substr( $_SERVER['HTTP_USER_AGENT'], 0, 4 ) ) ) ) {
80 powered_cache_add_cache_miss_header( "Mobile request" );
81
82 return;
83 }
84 }
85
86 // Exclude caching based on HTTP_REFERER
87 if ( ! empty( $powered_cache_rejected_referrers ) && isset( $_SERVER['HTTP_REFERER'] ) && $_SERVER['HTTP_REFERER'] ) {
88 foreach ( $powered_cache_rejected_referrers as $referrer_rule ) {
89 $referrer_rule = trim( $referrer_rule );
90 if ( $referrer_rule === '' ) {
91 continue;
92 }
93 // If rule starts with ^ or contains regex special chars, treat as regex
94 if ( preg_match( '/[\\^$.|?*+()\[\]]/', $referrer_rule ) ) {
95 if ( @preg_match( '#' . $referrer_rule . '#i', $_SERVER['HTTP_REFERER'] ) ) {
96 if ( preg_match( '#' . $referrer_rule . '#i', $_SERVER['HTTP_REFERER'] ) ) {
97 powered_cache_add_cache_miss_header( "Rejected referer: $referrer_rule" );
98
99 return;
100 }
101 }
102 } else {
103 // Plain string match
104 if ( strpos( $_SERVER['HTTP_REFERER'], $referrer_rule ) !== false ) {
105 powered_cache_add_cache_miss_header( "Rejected referer: $referrer_rule" );
106
107 return;
108 }
109 }
110 }
111 }
112
113 if ( ! empty( $_COOKIE ) ) {
114 $wp_cookies = [ 'wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_' ];
115 $comment_cookies = [ 'comment_author_', 'comment_author_email_', 'comment_author_url_' ];
116
117 // Check if logged-in caching is disabled or the user is not logged in
118 if ( empty( $GLOBALS['powered_cache_options']['loggedin_user_cache'] ) || false === powered_cache_get_user_cookie() ) {
119 // Standard check for logged-in status
120 foreach ( $_COOKIE as $key => $value ) {
121 foreach ( $wp_cookies as $cookie ) {
122 if ( strpos( $key, $cookie ) !== false ) {
123 powered_cache_add_cache_miss_header( "User logged-in" );
124 return;
125 }
126 }
127
128 // Check if the user has commented on the site
129 foreach ( $comment_cookies as $cookie ) {
130 if ( strpos( $key, $cookie ) !== false ) {
131 powered_cache_add_cache_miss_header( "User left a comment" );
132 return;
133 }
134 }
135 }
136
137 // Avoid caching pages with specific post comments from users
138 // it's a bit different from $comment_cookies since we are checking the post path
139 if ( ! empty( $_COOKIE['powered_cache_commented_posts'] ) ) {
140 foreach ( $_COOKIE['powered_cache_commented_posts'] as $path ) {
141 if ( rtrim( $path, '/' ) === rtrim( $_SERVER['REQUEST_URI'], '/' ) ) {
142 powered_cache_add_cache_miss_header( "User commented" );
143 return;
144 }
145 }
146 }
147 }
148
149 // Skip caching if there are specific rejected cookies, regardless of logged-in status
150 if ( ! empty( $powered_cache_rejected_cookies ) ) {
151 $rejected_cookies = array_diff( $powered_cache_rejected_cookies, $wp_cookies, $comment_cookies, ['powered_cache_commented_posts'] );
152 $rejected_cookies = implode( '|', $rejected_cookies );
153 if ( preg_match( '#(' . $rejected_cookies . ')#', var_export( $_COOKIE, true ) ) ) {
154 powered_cache_add_cache_miss_header( "Rejected cookie" );
155 return;
156 }
157 }
158 }
159
160 // Don't cache rejected pages
161 if ( ! empty( $powered_cache_rejected_uri ) ) {
162 foreach ( (array) $powered_cache_rejected_uri as $exception ) {
163 if ( preg_match( '#^[\s]*$#', $exception ) ) {
164 continue;
165 }
166
167 // full url exception
168 if ( preg_match( '#^https?://#', $exception ) ) {
169 $exception = parse_url( $exception, PHP_URL_PATH );
170 }
171
172 if ( empty( $exception ) ) {
173 continue;
174 }
175
176 if ( preg_match( '#^(' . $exception . ')$#', $_SERVER['REQUEST_URI'] ) ) {
177 powered_cache_add_cache_miss_header( "Rejected page" );
178
179 return;
180 }
181 }
182 }
183
184
185 if ( ! empty( $_GET ) ) {
186 if ( ! isset( $powered_cache_ignored_query_strings ) ) {
187 $powered_cache_ignored_query_strings = [];
188 }
189
190 $query_params = array_diff_key( $_GET, array_flip( $powered_cache_ignored_query_strings ) );
191
192 if ( ! isset( $powered_cache_cache_query_strings ) ) {
193 $powered_cache_cache_query_strings = [];
194 }
195
196 // don't cache when there is not allowed query parameter exists
197 if ( ! empty( $query_params ) && ! array_intersect_key( $_GET, array_flip( $powered_cache_cache_query_strings ) ) ) {
198 powered_cache_add_cache_miss_header( "Disallowed query parameter exists" );
199
200 return;
201 }
202 }
203
204 powered_cache_serve_cache();
205
206 ob_start( 'powered_cache_page_buffer' );
207
208 /**
209 * Cache output before it goes to the browser
210 *
211 * @param string $buffer
212 * @param int $flags
213 *
214 * @return string
215 * @since 1.0
216 */
217 function powered_cache_page_buffer( $buffer, $flags ) {
218 global $powered_cache_start_time, $post;
219
220 if ( strlen( $buffer ) < 255 ) {
221 return $buffer;
222 }
223
224 // maybe we shouldn't cache template file has this constant
225 // dont check DONOTCACHEPAGE strictly some plugins define string instead bool flag
226 if ( defined( 'DONOTCACHEPAGE' ) && DONOTCACHEPAGE ) {
227 powered_cache_add_cache_miss_header( "DONOTCACHEPAGE defined" );
228
229 return $buffer;
230 }
231
232 if ( ! empty( $GLOBALS['powered_cache_options']['dev_mode'] ) ) {
233 powered_cache_add_cache_miss_header( "Dev mode is enabled" );
234
235 return $buffer;
236 }
237
238 // Don't cache password protected posts
239 if ( ! empty( $post->post_password ) ) {
240 powered_cache_add_cache_miss_header( "Password protected posts are not cached" );
241
242 return $buffer;
243 }
244
245 // Don't cache 404 results
246 if ( function_exists( 'is_404' ) && is_404() ) {
247 powered_cache_add_cache_miss_header( "404 pages are not cached" );
248
249 return $buffer;
250 }
251
252 // Don't cache search results
253 if ( function_exists( 'is_search' ) && is_search() ) {
254 powered_cache_add_cache_miss_header( "Search result page is not cached" );
255
256 return $buffer;
257 }
258
259 /**
260 * Filter whether to enable page cache for this request
261 *
262 * @hook powered_cache_page_cache_enable
263 *
264 * @param {boolean} $enable true for caching
265 *
266 * @since 1.0
267 */
268 if ( true !== apply_filters( 'powered_cache_page_cache_enable', true ) ) {
269 powered_cache_add_cache_miss_header( "Page Cache not enabled for this post" );
270
271 return $buffer;
272 }
273
274 // only cache when http ok
275 if ( 200 !== http_response_code() ) {
276 powered_cache_add_cache_miss_header( "Response code is not 200" );
277
278 return $buffer;
279 }
280
281 if ( ! function_exists( '\PoweredCache\Utils\get_cache_dir' ) ) {
282 return $buffer;
283 }
284
285 // Make sure we can read/write files and that proper folders exist
286 if ( ! file_exists( untrailingslashit( \PoweredCache\Utils\get_cache_dir() ) ) ) {
287 if ( ! @mkdir( untrailingslashit( \PoweredCache\Utils\get_cache_dir() ) ) ) {
288 // Can not cache!
289 powered_cache_add_cache_miss_header( "The cache directory does not exist for storing cached output" );
290
291 return $buffer;
292 }
293 }
294
295 if ( ! file_exists( \PoweredCache\Utils\get_page_cache_dir() ) ) {
296 if ( ! @mkdir( \PoweredCache\Utils\get_page_cache_dir() ) ) {
297 // Can not cache!
298 powered_cache_add_cache_miss_header( "The page cache directory does not exist for storing cached output" );
299
300 return $buffer;
301 }
302 }
303
304 /**
305 * Filters HTML buffer
306 *
307 * @hook powered_cache_page_caching_buffer
308 *
309 * @param {string} $buffer Output buffer.
310 *
311 * @return {string} New value.
312 * @since 1.0
313 */
314 $buffer = apply_filters( 'powered_cache_page_caching_buffer', $buffer );
315
316 $url_path = powered_cache_get_url_path();
317
318 $dirs = explode( '/', $url_path );
319
320 $path = untrailingslashit( \PoweredCache\Utils\get_page_cache_dir() );
321
322 foreach ( $dirs as $dir ) {
323 if ( ! empty( $dir ) ) {
324 $path .= '/' . $dir;
325
326 if ( ! file_exists( $path ) ) {
327 if ( ! @mkdir( $path ) ) {
328 // Can not cache!
329 return $buffer;
330 }
331 }
332 }
333 }
334
335 $modified_time = time(); // Make sure modified time is consistent
336 $generation_time = number_format( microtime( true ) - $powered_cache_start_time, 3 );
337
338 $home_url = get_home_url();
339 // prevent mixed content
340 if ( ! is_ssl() && 'https' === strtolower( parse_url( $home_url, PHP_URL_SCHEME ) ) ) {
341 $https_home_url = $home_url;
342 $http_home_url = str_replace( 'https://', 'http://', $https_home_url );
343 $buffer = str_replace( esc_url( $http_home_url ), esc_url( $https_home_url ), $buffer );
344 }
345
346 if ( array_key_exists( 'cache_footprint', $GLOBALS['powered_cache_options'] ) && true === $GLOBALS['powered_cache_options']['cache_footprint'] ) {
347 if ( preg_match( '#</html>#i', $buffer ) ) {
348 $buffer .= PHP_EOL;
349 $buffer .= "<!-- Cache served by Powered Cache -->";
350 $buffer .= PHP_EOL;
351 $buffer .= "<!-- If you like fast websites like this, visit: https://poweredcache.com -->";
352 $buffer .= PHP_EOL;
353 $buffer .= "<!-- Last modified: " . gmdate( 'D, d M Y H:i:s', $modified_time ) . " GMT -->";
354 $buffer .= PHP_EOL;
355 $buffer .= "<!-- Dynamic page generated in $generation_time -->";
356 $buffer .= PHP_EOL;
357 if ( false !== stripos( $_SERVER['HTTP_USER_AGENT'], 'Powered Cache Preloader' ) ) {
358 $buffer .= "<!-- This page is preloaded by Powered Cache Preloader -->";
359 $buffer .= PHP_EOL;
360 }
361 }
362 }
363
364
365 $meta_file_name = 'meta.php';
366 $meta_file = '<?php exit; ?>' . PHP_EOL;
367
368 $meta_params = array(); // holds to metadata for cached file
369
370 $response_headers = \PoweredCache\Utils\get_response_headers();
371
372 foreach ( (array) $response_headers as $key => $value ) {
373 $meta_params['headers'][ $key ] = "$key: $value";
374 }
375
376 /**
377 * Filters meta parameters.
378 *
379 * @hook powered_cache_page_cache_meta_params
380 *
381 * @param {array} $meta_params Meta parameters.
382 * @param {array} $response_headers Supported response header list.
383 *
384 * @return {array} New value.
385 * @since 1.2
386 */
387 $meta_params = apply_filters( 'powered_cache_page_cache_meta_params', $meta_params, $response_headers );
388 $meta_file_contents = $meta_file . json_encode( $meta_params );
389
390 /**
391 * Filters meta file contents.
392 *
393 * @hook powered_cache_page_cache_meta_info
394 *
395 * @param {string} $meta_file_contents The content of the meta file.*
396 *
397 * @return {array} New value.
398 * @since 1.2
399 */
400 $meta_file_contents = apply_filters( 'powered_cache_page_cache_meta_info', $meta_file_contents );
401
402 file_put_contents( $path . '/' . $meta_file_name, $meta_file_contents );
403 touch( $path . '/' . $meta_file_name, $modified_time );
404
405 if ( ! empty( $meta_params['headers']['Content-Type'] ) ) {
406 $index_name = powered_cache_index_file( $meta_params['headers']['Content-Type'] );
407 } else {
408 $index_name = powered_cache_index_file();
409 }
410
411 if ( $GLOBALS['powered_cache_options']['gzip_compression'] && function_exists( 'gzencode' ) ) {
412 file_put_contents( $path . '/' . $index_name, gzencode( $buffer, 3 ) );
413 touch( $path . '/' . $index_name, $modified_time );
414 } else {
415 file_put_contents( $path . '/' . $index_name, $buffer );
416 touch( $path . '/' . $index_name, $modified_time );
417 }
418
419 /**
420 * Fires after caching a page.
421 *
422 * @hook powered_cache_page_cached
423 *
424 * @param {string} $buffer HTML Output.
425 *
426 * @since 1.0
427 */
428 do_action( 'powered_cache_page_cached', $buffer );
429
430 header( 'Cache-Control: no-cache' ); // Check back every time to see if re-download is necessary
431
432 header( 'X-Powered-Cache: MISS' );
433
434 header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $modified_time ) . ' GMT' );
435
436 if ( function_exists( 'ob_gzhandler' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
437 return ob_gzhandler( $buffer, $flags );
438 } else {
439 return $buffer;
440 }
441 }
442
443
444 /**
445 * Optionally serve cache and exit
446 *
447 * @since 1.0
448 */
449 function powered_cache_serve_cache() {
450 global $powered_cache_slash_check;
451
452 $path = rtrim( $GLOBALS['powered_cache_options']['cache_location'], '/' ) . '/powered-cache/' . rtrim( powered_cache_get_url_path(), '/' ) . '/';
453
454 $meta_file = $path . '/meta.php';
455
456 $header_params = [];
457 $content_type = 'text/html';
458
459 if ( @file_exists( $meta_file ) ) {
460 $meta_contents = trim( file_get_contents( $meta_file ) );
461 $meta_contents = str_replace( '<?php exit; ?>', '', $meta_contents );
462 $meta_params = json_decode( trim( $meta_contents ), true );
463 $header_params = $meta_params['headers'];
464 }
465
466 if ( ! empty( $header_params['Content-Type'] ) ) {
467 $content_type = $header_params['Content-Type'];
468 }
469
470
471 $file_name = powered_cache_index_file( $content_type );
472 $file_path = $path . $file_name;
473
474 // check file exists?
475 if ( ! file_exists( $file_path ) ) {
476 return;
477 }
478
479 $modified_time = (int) @filemtime( $file_path );
480
481 header( 'Cache-Control: no-cache' ); // Check back in an hour
482
483 if ( ! empty( $modified_time ) && ! empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) && strtotime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) === $modified_time ) {
484 header( $_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304 );
485 exit;
486 }
487
488 // trailingslash check
489 if ( isset( $powered_cache_slash_check ) && $powered_cache_slash_check ) {
490 $current_path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
491 if ( ! empty( $current_path ) && '/' !== substr( $current_path, - 1 ) ) {
492 header( 'X-Powered-Cache: Passing to WordPress' );
493
494 return;
495 }
496 }
497
498 if ( @file_exists( $file_path ) && @is_readable( $file_path ) ) {
499
500 if ( ! empty( $header_params ) ) {
501 foreach ( $header_params as $key => $response_header ) {
502 header( $response_header );
503 }
504 }
505
506 header( 'X-Powered-Cache: PHP' );
507 header( 'X-Cache-Enabled: true' );
508 header( sprintf( "age: %d", time() - filemtime( $file_path ) ) );
509
510 if ( function_exists( 'gzencode' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
511 header( 'Content-Encoding: gzip' );
512 }
513
514 @readfile( $file_path );
515
516 exit;
517 }
518 }
519
520 /**
521 * Get URL path for caching
522 *
523 * @return string
524 * @since 1.0
525 * @since 2.0 $request_uri without query string
526 */
527 function powered_cache_get_url_path() {
528 $host = ( isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '' );
529 $request_uri = explode( '?', $_SERVER['REQUEST_URI'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
530 $request_uri = reset( $request_uri );
531 $request_uri = preg_replace( '/(\/+)/', '/', $request_uri );
532 $request_uri = str_replace( '..', '', preg_replace( '/[ <>\'\"\r\n\t\(\)]/', '', $request_uri ) );
533
534 return rtrim( $host, '/' ) . $request_uri;
535 }
536
537 function powered_cache_get_user_cookie() {
538 if ( empty( $_COOKIE ) ) {
539 return false;
540 }
541
542 foreach ( $_COOKIE as $c_key => $val ) {
543 if ( false !== strpos( $c_key, 'wordpress_logged_in_' ) ) {
544 return $val;
545 }
546 }
547
548 return false;
549 }
550
551
552 /**
553 * Determines cache file names
554 *
555 * @param string $content_type
556 *
557 * @return string
558 * @since 1.2 `$content_type`
559 * @since 1.0
560 */
561 function powered_cache_index_file( $content_type = 'text/html' ) {
562 global $powered_cache_mobile_browsers, $powered_cache_mobile_prefixes, $powered_cache_vary_cookies, $powered_cache_cache_query_strings;
563
564 $file_name = 'index';
565
566 if ( is_ssl() ) {
567 $file_name .= '-https';
568 }
569
570 // separate file for mobile cache
571 if ( ! empty( $GLOBALS['powered_cache_options']['cache_mobile'] ) && ! empty( $GLOBALS['powered_cache_options']['cache_mobile_separate_file'] ) ) {
572 $mobile_browsers = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_browsers ) ), ' ' );
573 $mobile_prefixes = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_prefixes ) ), ' ' );
574
575 // Don't cache if mobile detection is activated
576 if ( ( preg_match( '#^.*(' . $mobile_browsers . ').*#i', $_SERVER['HTTP_USER_AGENT'] ) || preg_match( '#^(' . $mobile_prefixes . ').*#i', substr( $_SERVER['HTTP_USER_AGENT'], 0, 4 ) ) ) ) {
577 $file_name .= '-mobile';
578 }
579 }
580
581 if ( ! empty( $GLOBALS['powered_cache_options']['loggedin_user_cache'] ) ) {
582 $usr_cookie = powered_cache_get_user_cookie();
583 if ( false !== $usr_cookie ) {
584 $cookie_info = explode( '|', $usr_cookie );
585
586 // user specific cache index
587 $file_name .= '-user_' . $cookie_info[0] . '-' . substr( sha1( $cookie_info[0] ), 0, 6 );
588 }
589 }
590
591 // change filename based on vary cookies
592 if ( ! empty( $powered_cache_vary_cookies ) ) {
593 $cookie_file_name = '';
594 foreach ( $powered_cache_vary_cookies as $key => $vary_cookie ) {
595 if ( is_array( $vary_cookie ) ) {
596 if ( ! empty( $_COOKIE[ $key ] ) ) {
597 foreach ( $vary_cookie as $vary_sub_cookie ) {
598 if ( isset( $_COOKIE[ $key ][ $vary_sub_cookie ] ) ) {
599 $cookie_value = preg_replace( '/[^A-Za-z0-9. -]/', '', $_COOKIE[ $key ][ $vary_sub_cookie ] );
600 $cookie_file_name .= strtolower( $key . $vary_sub_cookie . $cookie_value );
601 }
602 }
603 }
604
605 continue;
606 }
607
608 if ( isset( $_COOKIE[ $vary_cookie ] ) && ! empty( $_COOKIE[ $vary_cookie ] ) ) {
609 $cookie_value = preg_replace( '/[^A-Za-z0-9. -]/', '', $_COOKIE[ $vary_cookie ] );
610 $cookie_file_name .= strtolower( $vary_cookie . $cookie_value );
611 }
612 }
613
614 if ( ! empty( $cookie_file_name ) ) {
615 /**
616 * Hashing for no particular reason
617 * preg_replace( '/[^a-z0-9_\-]/', '', strtolower( $cookie_file_name ) )
618 * can create a messy filename
619 */
620 $file_name .= '-' . sha1( $cookie_file_name );
621 }
622
623 }
624
625 // change filename for provided cache query string
626 if ( ! empty( $_SERVER['QUERY_STRING'] ) ) {
627 parse_str( $_SERVER['QUERY_STRING'], $query_string );
628 $qs_variable = '';
629 sort( $powered_cache_cache_query_strings );
630 foreach ( $powered_cache_cache_query_strings as $query_parameter ) {
631 if ( isset( $query_string[ $query_parameter ] ) ) {
632 $qs_variable .= '_' . $query_parameter;
633 $qs_variable .= is_array( $query_string[ $query_parameter ] ) ? implode( '|', $query_string[ $query_parameter ] ) : $query_string[ $query_parameter ];
634 }
635 }
636
637 if ( ! empty( $qs_variable ) ) {
638 $qs_variable = 'query_' . $qs_variable;
639 $file_name .= '_' . sha1( $qs_variable );
640 }
641 }
642
643
644 /**
645 * Content-Type is not always text/html (like feed, wp-json etc..)
646 * Adding hash by simply escaping from rewrite matches in htaccess or nginx
647 * Different types of content should be serve via PHP, in order to restore header info
648 */
649 if ( false === strpos( $content_type, 'text/html' ) ) {
650 $file_name .= '-' . substr( sha1( $content_type ), 0, 6 );
651 }
652
653
654 $file_name .= '.html';
655
656 if ( function_exists( 'gzencode' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
657 $file_name .= '.gz';
658 }
659
660 return $file_name;
661 }
662
663 /**
664 * Add cache miss header and reason
665 *
666 * @param string $reason Cache Miss info
667 *
668 * @since 2.2
669 */
670 function powered_cache_add_cache_miss_header( $reason ) {
671 if ( headers_sent() ) {
672 return;
673 }
674
675 header( 'X-Powered-Cache: MISS' );
676
677 if ( ( defined( 'POWERED_CACHE_ENABLE_LOG' ) && POWERED_CACHE_ENABLE_LOG )
678 || ( defined( 'POWERED_CACHE_MISS_REASON' ) && POWERED_CACHE_MISS_REASON )
679 ) {
680 header( "X-Powered-Cache-Miss-Reason: $reason" );
681 }
682 }
683