PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / 3.6
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score v3.6
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, at includes/dropins/page-cache.php

684 lines 20.7 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 \PoweredCache\Utils\log( sprintf( 'DONOTCACHEPAGE DEFINED on %s', $_SERVER['REQUEST_URI'] ) );
228 powered_cache_add_cache_miss_header( "DONOTCACHEPAGE defined" );
229
230 return $buffer;
231 }
232
233 if ( ! empty( $GLOBALS['powered_cache_options']['dev_mode'] ) ) {
234 powered_cache_add_cache_miss_header( "Dev mode is enabled" );
235
236 return $buffer;
237 }
238
239 // Don't cache password protected posts
240 if ( ! empty( $post->post_password ) ) {
241 powered_cache_add_cache_miss_header( "Password protected posts are not cached" );
242
243 return $buffer;
244 }
245
246 // Don't cache 404 results
247 if ( function_exists( 'is_404' ) && is_404() ) {
248 powered_cache_add_cache_miss_header( "404 pages are not cached" );
249
250 return $buffer;
251 }
252
253 // Don't cache search results
254 if ( function_exists( 'is_search' ) && is_search() ) {
255 powered_cache_add_cache_miss_header( "Search result page is not cached" );
256
257 return $buffer;
258 }
259
260 /**
261 * Filter whether to enable page cache for this request
262 *
263 * @hook powered_cache_page_cache_enable
264 *
265 * @param {boolean} $enable true for caching
266 *
267 * @since 1.0
268 */
269 if ( true !== apply_filters( 'powered_cache_page_cache_enable', true ) ) {
270 powered_cache_add_cache_miss_header( "Page Cache not enabled for this post" );
271
272 return $buffer;
273 }
274
275 // only cache when http ok
276 if ( 200 !== http_response_code() ) {
277 powered_cache_add_cache_miss_header( "Response code is not 200" );
278
279 return $buffer;
280 }
281
282 if ( ! function_exists( '\PoweredCache\Utils\get_cache_dir' ) ) {
283 return $buffer;
284 }
285
286 // Make sure we can read/write files and that proper folders exist
287 if ( ! file_exists( untrailingslashit( \PoweredCache\Utils\get_cache_dir() ) ) ) {
288 if ( ! @mkdir( untrailingslashit( \PoweredCache\Utils\get_cache_dir() ) ) ) {
289 // Can not cache!
290 powered_cache_add_cache_miss_header( "The cache directory does not exist for storing cached output" );
291
292 return $buffer;
293 }
294 }
295
296 if ( ! file_exists( \PoweredCache\Utils\get_page_cache_dir() ) ) {
297 if ( ! @mkdir( \PoweredCache\Utils\get_page_cache_dir() ) ) {
298 // Can not cache!
299 powered_cache_add_cache_miss_header( "The page cache directory does not exist for storing cached output" );
300
301 return $buffer;
302 }
303 }
304
305 /**
306 * Filters HTML buffer
307 *
308 * @hook powered_cache_page_caching_buffer
309 *
310 * @param {string} $buffer Output buffer.
311 *
312 * @return {string} New value.
313 * @since 1.0
314 */
315 $buffer = apply_filters( 'powered_cache_page_caching_buffer', $buffer );
316
317 $url_path = powered_cache_get_url_path();
318
319 $dirs = explode( '/', $url_path );
320
321 $path = untrailingslashit( \PoweredCache\Utils\get_page_cache_dir() );
322
323 foreach ( $dirs as $dir ) {
324 if ( ! empty( $dir ) ) {
325 $path .= '/' . $dir;
326
327 if ( ! file_exists( $path ) ) {
328 if ( ! @mkdir( $path ) ) {
329 // Can not cache!
330 return $buffer;
331 }
332 }
333 }
334 }
335
336 $modified_time = time(); // Make sure modified time is consistent
337 $generation_time = number_format( microtime( true ) - $powered_cache_start_time, 3 );
338
339 $home_url = get_home_url();
340 // prevent mixed content
341 if ( ! is_ssl() && 'https' === strtolower( parse_url( $home_url, PHP_URL_SCHEME ) ) ) {
342 $https_home_url = $home_url;
343 $http_home_url = str_replace( 'https://', 'http://', $https_home_url );
344 $buffer = str_replace( esc_url( $http_home_url ), esc_url( $https_home_url ), $buffer );
345 }
346
347 if ( array_key_exists( 'cache_footprint', $GLOBALS['powered_cache_options'] ) && true === $GLOBALS['powered_cache_options']['cache_footprint'] ) {
348 if ( preg_match( '#</html>#i', $buffer ) ) {
349 $buffer .= PHP_EOL;
350 $buffer .= "<!-- Cache served by Powered Cache -->";
351 $buffer .= PHP_EOL;
352 $buffer .= "<!-- If you like fast websites like this, visit: https://poweredcache.com -->";
353 $buffer .= PHP_EOL;
354 $buffer .= "<!-- Last modified: " . gmdate( 'D, d M Y H:i:s', $modified_time ) . " GMT -->";
355 $buffer .= PHP_EOL;
356 $buffer .= "<!-- Dynamic page generated in $generation_time -->";
357 $buffer .= PHP_EOL;
358 if ( false !== stripos( $_SERVER['HTTP_USER_AGENT'], 'Powered Cache Preloader' ) ) {
359 $buffer .= "<!-- This page is preloaded by Powered Cache Preloader -->";
360 $buffer .= PHP_EOL;
361 }
362 }
363 }
364
365
366 $meta_file_name = 'meta.php';
367 $meta_file = '<?php exit; ?>' . PHP_EOL;
368
369 $meta_params = array(); // holds to metadata for cached file
370
371 $response_headers = \PoweredCache\Utils\get_response_headers();
372
373 foreach ( (array) $response_headers as $key => $value ) {
374 $meta_params['headers'][ $key ] = "$key: $value";
375 }
376
377 /**
378 * Filters meta parameters.
379 *
380 * @hook powered_cache_page_cache_meta_params
381 *
382 * @param {array} $meta_params Meta parameters.
383 * @param {array} $response_headers Supported response header list.
384 *
385 * @return {array} New value.
386 * @since 1.2
387 */
388 $meta_params = apply_filters( 'powered_cache_page_cache_meta_params', $meta_params, $response_headers );
389 $meta_file_contents = $meta_file . json_encode( $meta_params );
390
391 /**
392 * Filters meta file contents.
393 *
394 * @hook powered_cache_page_cache_meta_info
395 *
396 * @param {string} $meta_file_contents The content of the meta file.*
397 *
398 * @return {array} New value.
399 * @since 1.2
400 */
401 $meta_file_contents = apply_filters( 'powered_cache_page_cache_meta_info', $meta_file_contents );
402
403 file_put_contents( $path . '/' . $meta_file_name, $meta_file_contents );
404 touch( $path . '/' . $meta_file_name, $modified_time );
405
406 if ( ! empty( $meta_params['headers']['Content-Type'] ) ) {
407 $index_name = powered_cache_index_file( $meta_params['headers']['Content-Type'] );
408 } else {
409 $index_name = powered_cache_index_file();
410 }
411
412 if ( $GLOBALS['powered_cache_options']['gzip_compression'] && function_exists( 'gzencode' ) ) {
413 file_put_contents( $path . '/' . $index_name, gzencode( $buffer, 3 ) );
414 touch( $path . '/' . $index_name, $modified_time );
415 } else {
416 file_put_contents( $path . '/' . $index_name, $buffer );
417 touch( $path . '/' . $index_name, $modified_time );
418 }
419
420 /**
421 * Fires after caching a page.
422 *
423 * @hook powered_cache_page_cached
424 *
425 * @param {string} $buffer HTML Output.
426 *
427 * @since 1.0
428 */
429 do_action( 'powered_cache_page_cached', $buffer );
430
431 header( 'Cache-Control: no-cache' ); // Check back every time to see if re-download is necessary
432
433 header( 'X-Powered-Cache: MISS' );
434
435 header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $modified_time ) . ' GMT' );
436
437 if ( function_exists( 'ob_gzhandler' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
438 return ob_gzhandler( $buffer, $flags );
439 } else {
440 return $buffer;
441 }
442 }
443
444
445 /**
446 * Optionally serve cache and exit
447 *
448 * @since 1.0
449 */
450 function powered_cache_serve_cache() {
451 global $powered_cache_slash_check;
452
453 $path = rtrim( $GLOBALS['powered_cache_options']['cache_location'], '/' ) . '/powered-cache/' . rtrim( powered_cache_get_url_path(), '/' ) . '/';
454
455 $meta_file = $path . '/meta.php';
456
457 $header_params = [];
458 $content_type = 'text/html';
459
460 if ( @file_exists( $meta_file ) ) {
461 $meta_contents = trim( file_get_contents( $meta_file ) );
462 $meta_contents = str_replace( '<?php exit; ?>', '', $meta_contents );
463 $meta_params = json_decode( trim( $meta_contents ), true );
464 $header_params = $meta_params['headers'];
465 }
466
467 if ( ! empty( $header_params['Content-Type'] ) ) {
468 $content_type = $header_params['Content-Type'];
469 }
470
471
472 $file_name = powered_cache_index_file( $content_type );
473 $file_path = $path . $file_name;
474
475 // check file exists?
476 if ( ! file_exists( $file_path ) ) {
477 return;
478 }
479
480 $modified_time = (int) @filemtime( $file_path );
481
482 header( 'Cache-Control: no-cache' ); // Check back in an hour
483
484 if ( ! empty( $modified_time ) && ! empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) && strtotime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) === $modified_time ) {
485 header( $_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304 );
486 exit;
487 }
488
489 // trailingslash check
490 if ( isset( $powered_cache_slash_check ) && $powered_cache_slash_check ) {
491 $current_path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
492 if ( ! empty( $current_path ) && '/' !== substr( $current_path, - 1 ) ) {
493 header( 'X-Powered-Cache: Passing to WordPress' );
494
495 return;
496 }
497 }
498
499 if ( @file_exists( $file_path ) && @is_readable( $file_path ) ) {
500
501 if ( ! empty( $header_params ) ) {
502 foreach ( $header_params as $key => $response_header ) {
503 header( $response_header );
504 }
505 }
506
507 header( 'X-Powered-Cache: PHP' );
508 header( 'X-Cache-Enabled: true' );
509 header( sprintf( "age: %d", time() - filemtime( $file_path ) ) );
510
511 if ( function_exists( 'gzencode' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
512 header( 'Content-Encoding: gzip' );
513 }
514
515 @readfile( $file_path );
516
517 exit;
518 }
519 }
520
521 /**
522 * Get URL path for caching
523 *
524 * @return string
525 * @since 1.0
526 * @since 2.0 $request_uri without query string
527 */
528 function powered_cache_get_url_path() {
529 $host = ( isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '' );
530 $request_uri = explode( '?', $_SERVER['REQUEST_URI'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
531 $request_uri = reset( $request_uri );
532 $request_uri = preg_replace( '/(\/+)/', '/', $request_uri );
533 $request_uri = str_replace( '..', '', preg_replace( '/[ <>\'\"\r\n\t\(\)]/', '', $request_uri ) );
534
535 return rtrim( $host, '/' ) . $request_uri;
536 }
537
538 function powered_cache_get_user_cookie() {
539 if ( empty( $_COOKIE ) ) {
540 return false;
541 }
542
543 foreach ( $_COOKIE as $c_key => $val ) {
544 if ( false !== strpos( $c_key, 'wordpress_logged_in_' ) ) {
545 return $val;
546 }
547 }
548
549 return false;
550 }
551
552
553 /**
554 * Determines cache file names
555 *
556 * @param string $content_type
557 *
558 * @return string
559 * @since 1.2 `$content_type`
560 * @since 1.0
561 */
562 function powered_cache_index_file( $content_type = 'text/html' ) {
563 global $powered_cache_mobile_browsers, $powered_cache_mobile_prefixes, $powered_cache_vary_cookies, $powered_cache_cache_query_strings;
564
565 $file_name = 'index';
566
567 if ( is_ssl() ) {
568 $file_name .= '-https';
569 }
570
571 // separate file for mobile cache
572 if ( ! empty( $GLOBALS['powered_cache_options']['cache_mobile'] ) && ! empty( $GLOBALS['powered_cache_options']['cache_mobile_separate_file'] ) ) {
573 $mobile_browsers = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_browsers ) ), ' ' );
574 $mobile_prefixes = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_prefixes ) ), ' ' );
575
576 // Don't cache if mobile detection is activated
577 if ( ( preg_match( '#^.*(' . $mobile_browsers . ').*#i', $_SERVER['HTTP_USER_AGENT'] ) || preg_match( '#^(' . $mobile_prefixes . ').*#i', substr( $_SERVER['HTTP_USER_AGENT'], 0, 4 ) ) ) ) {
578 $file_name .= '-mobile';
579 }
580 }
581
582 if ( ! empty( $GLOBALS['powered_cache_options']['loggedin_user_cache'] ) ) {
583 $usr_cookie = powered_cache_get_user_cookie();
584 if ( false !== $usr_cookie ) {
585 $cookie_info = explode( '|', $usr_cookie );
586
587 // user specific cache index
588 $file_name .= '-user_' . $cookie_info[0] . '-' . substr( sha1( $cookie_info[0] ), 0, 6 );
589 }
590 }
591
592 // change filename based on vary cookies
593 if ( ! empty( $powered_cache_vary_cookies ) ) {
594 $cookie_file_name = '';
595 foreach ( $powered_cache_vary_cookies as $key => $vary_cookie ) {
596 if ( is_array( $vary_cookie ) ) {
597 if ( ! empty( $_COOKIE[ $key ] ) ) {
598 foreach ( $vary_cookie as $vary_sub_cookie ) {
599 if ( isset( $_COOKIE[ $key ][ $vary_sub_cookie ] ) ) {
600 $cookie_value = preg_replace( '/[^A-Za-z0-9. -]/', '', $_COOKIE[ $key ][ $vary_sub_cookie ] );
601 $cookie_file_name .= strtolower( $key . $vary_sub_cookie . $cookie_value );
602 }
603 }
604 }
605
606 continue;
607 }
608
609 if ( isset( $_COOKIE[ $vary_cookie ] ) && ! empty( $_COOKIE[ $vary_cookie ] ) ) {
610 $cookie_value = preg_replace( '/[^A-Za-z0-9. -]/', '', $_COOKIE[ $vary_cookie ] );
611 $cookie_file_name .= strtolower( $vary_cookie . $cookie_value );
612 }
613 }
614
615 if ( ! empty( $cookie_file_name ) ) {
616 /**
617 * Hashing for no particular reason
618 * preg_replace( '/[^a-z0-9_\-]/', '', strtolower( $cookie_file_name ) )
619 * can create a messy filename
620 */
621 $file_name .= '-' . sha1( $cookie_file_name );
622 }
623
624 }
625
626 // change filename for provided cache query string
627 if ( ! empty( $_SERVER['QUERY_STRING'] ) ) {
628 parse_str( $_SERVER['QUERY_STRING'], $query_string );
629 $qs_variable = '';
630 sort( $powered_cache_cache_query_strings );
631 foreach ( $powered_cache_cache_query_strings as $query_parameter ) {
632 if ( isset( $query_string[ $query_parameter ] ) ) {
633 $qs_variable .= '_' . $query_parameter;
634 $qs_variable .= is_array( $query_string[ $query_parameter ] ) ? implode( '|', $query_string[ $query_parameter ] ) : $query_string[ $query_parameter ];
635 }
636 }
637
638 if ( ! empty( $qs_variable ) ) {
639 $qs_variable = 'query_' . $qs_variable;
640 $file_name .= '_' . sha1( $qs_variable );
641 }
642 }
643
644
645 /**
646 * Content-Type is not always text/html (like feed, wp-json etc..)
647 * Adding hash by simply escaping from rewrite matches in htaccess or nginx
648 * Different types of content should be serve via PHP, in order to restore header info
649 */
650 if ( false === strpos( $content_type, 'text/html' ) ) {
651 $file_name .= '-' . substr( sha1( $content_type ), 0, 6 );
652 }
653
654
655 $file_name .= '.html';
656
657 if ( function_exists( 'gzencode' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
658 $file_name .= '.gz';
659 }
660
661 return $file_name;
662 }
663
664 /**
665 * Add cache miss header and reason
666 *
667 * @param string $reason Cache Miss info
668 *
669 * @since 2.2
670 */
671 function powered_cache_add_cache_miss_header( $reason ) {
672 if ( headers_sent() ) {
673 return;
674 }
675
676 header( 'X-Powered-Cache: MISS' );
677
678 if ( ( defined( 'POWERED_CACHE_ENABLE_LOG' ) && POWERED_CACHE_ENABLE_LOG )
679 || ( defined( 'POWERED_CACHE_MISS_REASON' ) && POWERED_CACHE_MISS_REASON )
680 ) {
681 header( "X-Powered-Cache-Miss-Reason: $reason" );
682 }
683 }
684