PluginProbe
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript / 4.1.19
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript v4.1.19
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.19, at inc/common-functions.php

279 lines 10.4 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 $extension = strtolower(pathinfo($request_path, PATHINFO_EXTENSION));
200 $allowed_extension = ['html', 'htm'];
201
202 if (!empty($extension) && !in_array($extension, $allowed_extension)) {
203 return;
204 }
205
206 if ($request_path !== '/' && isset($configs['permalink_trailing_slash']) && $configs['permalink_trailing_slash'] !== null) {
207 $has_trailing_slash = substr($request_path, -1) === '/';
208 if ($configs['permalink_trailing_slash'] !== $has_trailing_slash) {
209 bwp_redirect_to_canonical_slash($configs['permalink_trailing_slash']);
210 }
211 }
212
213 if (file_exists($cache_file) && $cache_max_life > time()) {
214 $file_content = @file_get_contents($cache_file);
215
216 if (!isset($_GET['creating_cache']) && file_exists($cache_file)) {
217
218 if (strpos($file_content, "Optimized with BerqWP's instant cache") !== false && (filemtime($cache_file) + DAY_IN_SECONDS) < time()) {
219 return;
220 }
221
222 // Prepare gzip cache file
223 if ($compression_enabled && file_exists($cache_file_gz)) {
224 $cache_file = $cache_file_gz;
225 // header('Content-Encoding: gzip');
226 header_remove('Content-Encoding');
227 }
228
229 $lastModified = filemtime($cache_file);
230 $etag = md5_file($cache_file);
231 header('ETag: ' . $etag);
232 header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
233 header('X-File-Size: ' . filesize($cache_file), true);
234 header('Content-Type: text/html; charset=utf-8');
235 header("X-served: $serve_from");
236 header("X-BerqWP-Cache: HIT");
237 // header('Vary: Cookie');
238
239 // Check if the client has a cached copy and if it's still valid using Last-Modified
240 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)) {
241 // The client's cache is still valid based on Last-Modified, respond with a 304 Not Modified
242 header('HTTP/1.1 304 Not Modified');
243 // header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
244 // header("Expires: 0");
245 // header('Cache-Control: no-cache, must-revalidate');
246 header('Cache-Control: public, max-age=600, s-maxage=2592000, stale-while-revalidate=86400', true);
247 header('cdn-cache-control: max-age=2592000');
248 header("Cache-Tag: $domain");
249 exit();
250
251 }
252
253 // Prevent PHP/Apache from re-compressing the already-gzipped cache file
254 if (ini_get('zlib.output_compression')) {
255 ini_set('zlib.output_compression', 'Off');
256 }
257
258 while (ob_get_level()) {
259 ob_end_clean();
260 }
261
262 // header('Cache-Control: public, max-age=0, s-maxage=3600, must-revalidate', true);
263 // header('Cache-Control: public, max-age=60, s-maxage=3600, stale-while-revalidate=60, must-revalidate', true);
264 header('Cache-Control: public, max-age=600, s-maxage=2592000, stale-while-revalidate=86400', true);
265 header('cdn-cache-control: max-age=2592000');
266 header("Cache-Tag: $domain");
267 // header("Content-Security-Policy: script-src 'self' blob: 'unsafe-inline'");
268 header('Vary: Accept-Encoding, Cookie');
269 header('Content-Encoding: gzip', true);
270 header('Content-Length: ' . filesize($cache_file), true);
271 readfile($cache_file);
272 exit();
273 }
274
275 }
276
277 }
278 }
279