PluginProbe
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript / 4.1.18
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript v4.1.18
4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.14 4.1.13 4.1.12 4.1.11 4.1.10 4.0.30 4.0.29 4.0.28 4.0.27 4.0.26 4.0.24 4.0.25 4.0.23 4.0.22 4.0.21 4.0.19 4.0.18 4.0.17 4.0.16 1.9.3 All 173 releases
searchpro / inc / common-functions.php

common-functions.php in BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript 4.1.18, at inc/common-functions.php

272 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 function bwp_pass_cookie_requirement() {
4 $berqconfigs = berqConfigs::getInstance();
5 $configs = $berqconfigs->get_configs();
6 $default = ['berqwpnocache', 'wp-postpass', 'comment_author', 'woocommerce_cart_hash', 'edd_items_in_cart'];
7 $excluded_cookies = array_merge($configs['exclude_cookies'], $default);
8
9 if (!empty($excluded_cookies)) {
10 foreach ($excluded_cookies as $cookie_id) {
11
12 // Skip if empty
13 if (empty($cookie_id)) {
14 continue;
15 }
16
17 foreach ($_COOKIE as $key => $value) {
18 if (strpos($key, $cookie_id) === 0) {
19 return false;
20 }
21 }
22 }
23 }
24
25 return true;
26 }
27
28 function bwp_request_is_https() {
29 if (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
30 return true;
31 }
32
33 // Reverse proxy / load balancer terminating TLS upstream
34 if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
35 // may be a comma-separated chain: "https,http" — first hop is the client
36 $proto = strtolower(trim(explode(',', $_SERVER['HTTP_X_FORWARDED_PROTO'])[0]));
37 if ($proto === 'https') {
38 return true;
39 }
40 }
41
42 if (!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && strtolower($_SERVER['HTTP_X_FORWARDED_SSL']) === 'on') {
43 return true;
44 }
45
46 if (!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) === 'on') {
47 return true;
48 }
49
50 if (!empty($_SERVER['SERVER_PORT']) && (int) $_SERVER['SERVER_PORT'] === 443) {
51 return true;
52 }
53
54 return false;
55 }
56
57 function bwp_get_request_url() {
58
59 $scheme = 'http://';
60
61 if (bwp_request_is_https()) {
62 $scheme = 'https://';
63 } elseif (function_exists('wp_parse_url') && function_exists('get_option')) {
64 $scheme = (wp_parse_url(get_option('home'), PHP_URL_SCHEME) === 'https') ? 'https://' : 'http://';
65 }
66
67 $host = isset($_SERVER['HTTP_HOST']) ? strip_tags(stripslashes($_SERVER['HTTP_HOST'])) : 'localhost';
68 $uri = isset($_SERVER['REQUEST_URI']) ? strip_tags(stripslashes($_SERVER['REQUEST_URI'])) : '/';
69 $url = $scheme . $host . $uri;
70 return strtolower($url);
71 }
72
73 // function bwp_build_cache_path($url) {
74 // $parts = parse_url($url);
75
76 // $host = $parts['host'] ?? '';
77 // $path = $parts['path'] ?? '/';
78
79 // // normalize
80 // $path = '/' . ltrim($path, '/');
81 // $path = rtrim($path, '/');
82
83 // if ($path === '') {
84 // $path = '/';
85 // }
86
87 // // sanitize
88 // $host = preg_replace('#[^a-zA-Z0-9\.\-]#', '', $host);
89 // $path = preg_replace('#[^a-zA-Z0-9/_-]#', '', $path);
90
91 // return $host . $path;
92 // }
93
94 function bwp_build_cache_path($url) {
95 $parts = parse_url($url);
96 $host = $parts['host'] ?? '';
97 $path = $parts['path'] ?? '/';
98 $query = $parts['query'] ?? '';
99
100 // normalize path
101 $path = '/' . ltrim($path, '/');
102 $path = rtrim($path, '/');
103 if ($path === '') {
104 $path = '/';
105 }
106
107 // sanitize host
108 $host = preg_replace('#[^a-zA-Z0-9\.\-]#', '', $host);
109
110 // Normalize percent-encoded chars to raw UTF-8, then strip only chars that
111 // are unsafe on filesystems (null bytes, path traversal sequences).
112 $path = urldecode($path);
113 $path = str_replace("\0", '', $path);
114 $path = preg_replace('#\.\.+#', '', $path);
115 $path = preg_replace('#[<>:"\\\\|?*]#', '', $path);
116
117 if ($query === '') {
118 return $path === '/' ? $host : $host . $path;
119 }
120
121 // normalize query param order so ?b=2&a=1 and ?a=1&b=2 hit the same cache
122 parse_str($query, $params);
123 ksort($params);
124 $normalized_query = http_build_query($params);
125
126 // hash it — query strings can contain anything and be very long
127 $query_hash = substr(md5($normalized_query), 0, 12);
128
129 return $host . $path . '/q-' . $query_hash;
130 }
131
132 /**
133 * Redirect a mismatched-trailing-slash request to its canonical form, the same
134 * way WordPress's redirect_canonical() would — but without needing WordPress
135 * to boot first. Used by the advanced-cache.php dropin, which runs before the
136 * DB connection is available.
137 */
138 function bwp_redirect_to_canonical_slash($wants_trailing_slash) {
139 $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';
140 $parts = explode('?', $uri, 2);
141 $path = $parts[0];
142 $query = isset($parts[1]) ? '?' . $parts[1] : '';
143
144 if ($wants_trailing_slash) {
145 $path = rtrim($path, '/') . '/';
146 } else {
147 $path = rtrim($path, '/');
148 if ($path === '') {
149 $path = '/';
150 }
151 }
152
153 $scheme = bwp_request_is_https() ? 'https://' : 'http://';
154 $host = isset($_SERVER['HTTP_HOST']) ? strip_tags(stripslashes($_SERVER['HTTP_HOST'])) : '';
155
156 header('Location: ' . $scheme . $host . $path . $query, true, 301);
157 exit();
158 }
159
160 function bwp_serve_advanced_cache($serve_from = 'plugin') {
161
162 if (php_sapi_name() === 'cli' || (defined('WP_CLI') && WP_CLI)) {
163 return;
164 }
165
166 if ( strpos( $_SERVER["REQUEST_URI"], "berqwp-ping" ) !== false ) {
167 echo "PONG";
168 exit();
169 }
170
171 if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'GET' && !bwp_is_user_logged_in() && !bwp_is_ajax() && !berqDetectCrawler::is_crawler() && bwp_pass_cookie_requirement()) {
172
173 $berqconfigs = berqConfigs::getInstance();
174 $configs = $berqconfigs->get_configs();
175 $url = bwp_get_request_url();
176 $url = @dropin_remove_ignore_params($url);
177 $cache_key = md5($url);
178 $cache_directory = WP_CONTENT_DIR . '/cache/berqwp/html/';
179 if (defined('MULTISITE') && MULTISITE) {
180 $blog_id = berqConfigs::detect_blog_id_from_request();
181 $cache_directory .= 'site-' . $blog_id . '/';
182 }
183 $cache_file = $cache_directory . $cache_key . '.html';
184 $cache_file_gz = $cache_directory . $cache_key . '.gz';
185 $cache_file_gz = $cache_directory . bwp_build_cache_path($url) . '/index.html.gz';
186 $cache_file = $cache_file_gz;
187 $cache_max_life = file_exists($cache_file) ? @filemtime($cache_file) + $configs['cache_lifespan'] : null;
188 // $compression_enabled = $configs['page_compression'] === true;
189 $compression_enabled = true;
190 $accept_encoding = $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '';
191 $supports_gzip = strpos($accept_encoding, 'gzip') !== false;
192 $domain = isset($_SERVER['HTTP_HOST']) ? strip_tags(stripslashes($_SERVER['HTTP_HOST'])) : '';
193
194 if (berqwp_dropin_is_page_url_excluded($url)) {
195 return;
196 }
197
198 $request_path = parse_url($url, PHP_URL_PATH) ?? '/';
199 if ($request_path !== '/' && isset($configs['permalink_trailing_slash']) && $configs['permalink_trailing_slash'] !== null) {
200 $has_trailing_slash = substr($request_path, -1) === '/';
201 if ($configs['permalink_trailing_slash'] !== $has_trailing_slash) {
202 bwp_redirect_to_canonical_slash($configs['permalink_trailing_slash']);
203 }
204 }
205
206 if (file_exists($cache_file) && $cache_max_life > time()) {
207 $file_content = @file_get_contents($cache_file);
208
209 if (!isset($_GET['creating_cache']) && file_exists($cache_file)) {
210
211 if (strpos($file_content, "Optimized with BerqWP's instant cache") !== false && (filemtime($cache_file) + DAY_IN_SECONDS) < time()) {
212 return;
213 }
214
215 // Prepare gzip cache file
216 if ($compression_enabled && file_exists($cache_file_gz)) {
217 $cache_file = $cache_file_gz;
218 // header('Content-Encoding: gzip');
219 header_remove('Content-Encoding');
220 }
221
222 $lastModified = filemtime($cache_file);
223 $etag = md5_file($cache_file);
224 header('ETag: ' . $etag);
225 header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
226 header('X-File-Size: ' . filesize($cache_file), true);
227 header('Content-Type: text/html; charset=utf-8');
228 header("X-served: $serve_from");
229 header("X-BerqWP-Cache: HIT");
230 // header('Vary: Cookie');
231
232 // Check if the client has a cached copy and if it's still valid using Last-Modified
233 if ((isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified) || (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $etag)) {
234 // The client's cache is still valid based on Last-Modified, respond with a 304 Not Modified
235 header('HTTP/1.1 304 Not Modified');
236 // header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
237 // header("Expires: 0");
238 // header('Cache-Control: no-cache, must-revalidate');
239 header('Cache-Control: public, max-age=600, s-maxage=2592000, stale-while-revalidate=86400', true);
240 header('cdn-cache-control: max-age=2592000');
241 header("Cache-Tag: $domain");
242 exit();
243
244 }
245
246 // Prevent PHP/Apache from re-compressing the already-gzipped cache file
247 if (ini_get('zlib.output_compression')) {
248 ini_set('zlib.output_compression', 'Off');
249 }
250
251 while (ob_get_level()) {
252 ob_end_clean();
253 }
254
255 // header('Cache-Control: public, max-age=0, s-maxage=3600, must-revalidate', true);
256 // header('Cache-Control: public, max-age=60, s-maxage=3600, stale-while-revalidate=60, must-revalidate', true);
257 header('Cache-Control: public, max-age=600, s-maxage=2592000, stale-while-revalidate=86400', true);
258 header('cdn-cache-control: max-age=2592000');
259 header("Cache-Tag: $domain");
260 // header("Content-Security-Policy: script-src 'self' blob: 'unsafe-inline'");
261 header('Vary: Accept-Encoding, Cookie');
262 header('Content-Encoding: gzip', true);
263 header('Content-Length: ' . filesize($cache_file), true);
264 readfile($cache_file);
265 exit();
266 }
267
268 }
269
270 }
271 }
272