PluginProbe
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript / 4.1.20
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript v4.1.20
4.1.20 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 All 174 releases
← All changes | inc/helper-functions.php +213 -46 4.0.18 → 4.1.20 View file →
@@ -82,9 +82,8 @@
82 82 }
83 83
84 84 function berqwp_activate_single_site() {
85 85 if (empty(berqwp_get_license_key())) {
86 - set_transient('bqwp_hide_feedback_notice', true, 60 * 60);
87 86 set_transient('berqwp_redirect', true, 1);
88 87 }
89 88 update_option('berqwp_sync_addons', true);
90 89 do_action('berqwp_activate_plugin');
@@ -225,8 +224,9 @@
225 224 "/embed",
226 225 "/view-order/",
227 226 "/redirect/",
228 227 "/elementskit-content/",
228 + "/checkout/",
229 229 ];
230 230
231 231 $exclude_items = apply_filters('berqwp_exclude_slug_match', $exclude_items);
232 232
@@ -238,8 +238,52 @@
238 238
239 239 return false;
240 240 }
241 241
242 +
243 +function berqwp_home_url() {
244 + return untrailingslashit(apply_filters('berqwp_site_url', home_url()));
245 +}
246 +
247 +function bwp_canonicalize_page_url($url) {
248 + $permalink_structure = get_option('permalink_structure');
249 +
250 + if (!$permalink_structure) {
251 + return $url;
252 + }
253 +
254 + $path = parse_url($url, PHP_URL_PATH) ?? '/';
255 +
256 + if ($path === '/') {
257 + return $url;
258 + }
259 +
260 + $uses_trailing_slash = substr(rtrim($permalink_structure), -1) === '/';
261 + $has_trailing_slash = substr($path, -1) === '/';
262 +
263 + if ($uses_trailing_slash && !$has_trailing_slash) {
264 + return trailingslashit($url);
265 + }
266 +
267 + if (!$uses_trailing_slash && $has_trailing_slash) {
268 + return untrailingslashit($url);
269 + }
270 +
271 + return $url;
272 +}
273 +
274 +function bwp_sync_permalink_config() {
275 + $permalink_structure = get_option('permalink_structure');
276 + $trailing_slash = empty($permalink_structure) ? null : (substr(rtrim($permalink_structure), -1) === '/');
277 +
278 + $berqconfigs = berqConfigs::getInstance();
279 + $current = $berqconfigs->get_configs();
280 +
281 + if ($current === false || !array_key_exists('permalink_trailing_slash', $current) || $current['permalink_trailing_slash'] !== $trailing_slash) {
282 + $berqconfigs->update_configs(['permalink_trailing_slash' => $trailing_slash]);
283 + }
284 +}
285 +
242 286 function berqwp_get_page_params($page_url, $is_forced = false)
243 287 {
244 288
245 289 if (empty($page_url)) {
@@ -262,8 +306,10 @@
262 306 } elseif ($optimization_mode == 1) {
263 307 $optimization_mode = 'basic';
264 308 }
265 309
310 + $home_url = berqwp_home_url();
311 +
266 312 // Data to send as POST parameters
267 313 $post_data = array(
268 314 'site_id' => $berqwp_configs['site_id'],
269 315 'license_key' => berqwp_get_license_key(),
@@ -268,13 +314,14 @@
268 314 'site_id' => $berqwp_configs['site_id'],
269 315 'license_key' => berqwp_get_license_key(),
270 316 'page_url' => $page_url,
271 317 'page_slug' => $page_slug,
272 - 'site_url' => home_url(),
318 + 'site_url' => $home_url,
273 319 'webp_max_width' => (int) get_option('berqwp_webp_max_width'),
274 320 'webp_quality' => (int) get_option('berqwp_webp_quality'),
275 321 'fluid_images' => get_option('berqwp_fluid_images'),
276 322 'enable_critical_css' => get_option('berqwp_enable_critical_css'),
323 + 'enable_used_css' => get_option('berqwp_enable_used_css'),
277 324 'force_include_critical_css'=> get_option('berqwp_force_include_critical_css', []),
278 325 'exclude_css' => get_option('berqwp_exclude_css', []),
279 326 'exclude_js' => get_option('berqwp_exclude_js', []),
280 327 'exclude_third_party_js' => get_option('berqwp_exclude_third_party_js', []),
@@ -1301,9 +1348,9 @@
1301 1348
1302 1349 function bwp_sluguri_into_path($slug_uri)
1303 1350 {
1304 1351 $is_multisite = function_exists('is_multisite') && is_multisite();
1305 - $home_path = parse_url(home_url(), PHP_URL_PATH);
1352 + $home_path = parse_url(berqwp_home_url(), PHP_URL_PATH);
1306 1353
1307 1354 // if (berqwp_is_sub_dir_wp() && !$is_multisite) {
1308 1355 if (!$is_multisite && $home_path !== null) {
1309 1356 // Parse strings to extract paths
@@ -1324,9 +1371,9 @@
1324 1371 {
1325 1372 $parsed_url = parse_url($url);
1326 1373 $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
1327 1374 $query = isset($parsed_url['query']) ? $parsed_url['query'] : '';
1328 - $homeurl = home_url();
1375 + $homeurl = berqwp_home_url();
1329 1376
1330 1377 if (!empty($query)) {
1331 1378 $path = $path . '?' . $query;
1332 1379 }
@@ -1450,9 +1497,9 @@
1450 1497 // Set the number of posts per batch to handle
1451 1498 $posts_per_page = 10000; // Adjust this based on server capacity
1452 1499
1453 1500 // Get current page from query string (for pagination)
1454 - $paged = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
1501 + $paged = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
1455 1502
1456 1503 // Build the query arguments with pagination
1457 1504 $args = array(
1458 1505 'post_type' => $post_types,
@@ -1480,8 +1527,9 @@
1480 1527
1481 1528 $berqconfigs = berqConfigs::getInstance();
1482 1529 $configs = $berqconfigs->get_configs();
1483 1530 $post_params['cache_lifespan'] = $configs['cache_lifespan'];
1531 + $post_params['sandbox'] = get_option('berqwp_enable_sandbox');
1484 1532
1485 1533 if ($query->have_posts()) {
1486 1534 $sitemap_urls = [];
1487 1535
@@ -1639,21 +1687,21 @@
1639 1687
1640 1688 if (!empty($_GET['tab_id'])) {
1641 1689 if (sanitize_text_field($_GET['tab_id']) == $tab_id) {
1642 1690 // echo ' style="display:block" ';
1643 - echo ' style="visibility:visible;opacity:1;height:auto;" ';
1691 + echo ' style="visibility:visible;opacity:1;height:auto;display:block;" ';
1644 1692 } else {
1645 1693 // echo ' style="display:none" ';
1646 - echo ' style="visibility:hidden;opacity:0;height:0;overflow:hidden;" ';
1694 + echo ' style="visibility:hidden;opacity:0;height:0;overflow:hidden;display:none;" ';
1647 1695 }
1648 1696 } else {
1649 1697
1650 1698 if ($tab_id == $default_tab) {
1651 1699 // echo ' style="display:block" ';
1652 - echo ' style="visibility:visible;opacity:1;height:auto;" ';
1700 + echo ' style="visibility:visible;opacity:1;height:auto;display:block;" ';
1653 1701 } else {
1654 1702 // echo ' style="display:none" ';
1655 - echo ' style="visibility:hidden;opacity:0;height:0;overflow:hidden;" ';
1703 + echo ' style="visibility:hidden;opacity:0;height:0;overflow:hidden;display:none;" ';
1656 1704 }
1657 1705 }
1658 1706 }
1659 1707
@@ -1691,15 +1739,15 @@
1691 1739 d="M6.43896 0H17.561C21.1172 0 24 2.88287 24 6.43903V17.561C24 21.1171 21.1172 24 17.561 24H6.43896C2.88281 24 0 21.1171 0 17.561V6.43903C0 2.88287 2.88281 0 6.43896 0ZM15.7888 4.09753L8.59961 12.7534H12.3517L7.02441 20.4878L16.3903 11.0222L12.7814 10.3799L15.7888 4.09753Z"
1692 1740 fill="#1f72ff" />
1693 1741 </svg></div>
1694 1742 <div class="content">
1695 - <div class="status-tag"><?php esc_html_e($status, 'searchpro'); ?></div>
1743 + <div class="status-tag"><?php echo esc_html($status); ?></div>
1696 1744 <?php if (!empty($title)) { ?>
1697 - <h5><?php echo wp_kses_post(__($title, 'searchpro')); ?></h5>
1745 + <h5><?php echo wp_kses_post($title); ?></h5>
1698 1746 <?php } ?>
1699 1747
1700 1748 <?php if (!empty($message)) { ?>
1701 - <?php echo wp_kses_post(__($message, 'searchpro')); ?>
1749 + <?php echo wp_kses_post($message); ?>
1702 1750 <?php } ?>
1703 1751
1704 1752 <?php if (!empty($btn) && is_array($btn)) { ?>
1705 1753 <div class="bwp-notice-btn">
@@ -1723,9 +1771,9 @@
1723 1771 ?>
1724 1772 <a target="<?php echo esc_attr($bwp_btn['target']) ?? ''; ?>"
1725 1773 href="<?php echo esc_attr($bwp_btn['href']) ?? ''; ?>"
1726 1774 class="bwp-btn <?php echo esc_attr($bwp_btn['classes']) ?? ''; ?>">
1727 - <?php echo esc_html__($bwp_btn['text'], 'searchpro') ?? ''; ?>
1775 + <?php echo esc_html($bwp_btn['text']); ?>
1728 1776 </a>
1729 1777 <?php
1730 1778 }
1731 1779 ?>
@@ -1810,9 +1858,9 @@
1810 1858 if (isset($_GET['berqwp_logs'])) {
1811 1859
1812 1860 // Check if the current user is logged in and has admin privileges
1813 1861 if (!is_user_logged_in() || !current_user_can('administrator')) {
1814 - wp_die(__('You are not allowed to access this page.', 'berqwp'));
1862 + wp_die(__('You are not allowed to access this page.', 'searchpro'));
1815 1863 }
1816 1864
1817 1865 // Define the path to the BerqWP logs file
1818 1866 $log_file_path = optifer_cache . '/logs/berqwp.log'; // Adjust path if needed
@@ -1880,8 +1928,22 @@
1880 1928 if (!file_exists($cache_dir)) {
1881 1929 wp_mkdir_p($cache_dir);
1882 1930 }
1883 1931
1932 + if (!function_exists('got_mod_rewrite')) {
1933 + require_once ABSPATH . 'wp-admin/includes/misc.php';
1934 + }
1935 +
1936 + if (!got_mod_rewrite()) {
1937 + return;
1938 + }
1939 +
1940 + $htaccess_path = $cache_dir . '.htaccess';
1941 +
1942 + if (!is_writable($htaccess_path)) {
1943 + return;
1944 + }
1945 +
1884 1946 $rules = <<<HTACCESS
1885 1947 Order allow,deny
1886 1948 Deny from all
1887 1949
@@ -1888,13 +1950,50 @@
1888 1950 <FilesMatch "index\.html\.gz$">
1889 1951 Order allow,deny
1890 1952 Allow from all
1891 1953 </FilesMatch>
1954 +
1955 +# Block PHP execution and dot-files to prevent webshell deployment
1956 +<FilesMatch "\.php\d*$|\.phtml$|\.phar$">
1957 + Order allow,deny
1958 + Deny from all
1959 +</FilesMatch>
1960 +<FilesMatch "^\.">
1961 + Order allow,deny
1962 + Deny from all
1963 +</FilesMatch>
1892 1964 HTACCESS;
1893 1965
1894 - file_put_contents($cache_dir . '.htaccess', $rules);
1966 + file_put_contents($htaccess_path, $rules);
1967 +
1968 + // Suppress directory listing
1969 + $index_stub = $cache_dir . 'index.php';
1970 + if (!file_exists($index_stub)) {
1971 + file_put_contents($index_stub, '<?php // Silence is golden');
1972 + }
1973 +
1895 1974 }
1896 1975
1976 +function bwp_delete_php_files_in_cache()
1977 +{
1978 + $cache_dir = optifer_cache;
1979 + if (!is_dir($cache_dir)) {
1980 + return;
1981 + }
1982 +
1983 + $php_extensions = ['php', 'php3', 'php4', 'php5', 'php7', 'php8', 'phtml', 'phar'];
1984 +
1985 + $iterator = new RecursiveIteratorIterator(
1986 + new RecursiveDirectoryIterator($cache_dir, RecursiveDirectoryIterator::SKIP_DOTS)
1987 + );
1988 +
1989 + foreach ($iterator as $file) {
1990 + if ($file->isFile() && in_array(strtolower($file->getExtension()), $php_extensions, true)) {
1991 + @unlink($file->getRealPath());
1992 + }
1993 + }
1994 +}
1995 +
1897 1996 function bwp_write_htaccess_rules($ignore_sandbox = false)
1898 1997 {
1899 1998 if (!got_mod_rewrite() || bwp_is_openlitespeed_server()) {
1900 1999 return;
@@ -1904,14 +2003,31 @@
1904 2003 return;
1905 2004 }
1906 2005
1907 2006 $htaccess = get_home_path() . '.htaccess';
1908 - $rules = [
2007 + $cache_tag_host = parse_url(home_url(), PHP_URL_HOST);
2008 +
2009 + if (!is_writable($htaccess)) {
2010 + return;
2011 + }
2012 +
2013 + // Match the cache-serving RewriteCond to the site's actual permalink convention,
2014 + // so caching works whether the site uses trailing slashes or not.
2015 + $permalink_structure = get_option('permalink_structure');
2016 + $uses_trailing_slash = empty($permalink_structure) || substr(rtrim($permalink_structure), -1) === '/';
2017 +
2018 + $slash_conds = $uses_trailing_slash
2019 + ? [' RewriteCond %{REQUEST_URI} /$']
2020 + : [' RewriteCond %{REQUEST_URI} ^/$ [OR]', ' RewriteCond %{REQUEST_URI} !/$'];
2021 +
2022 + $rules = array_merge([
1909 2023 '<IfModule mod_rewrite.c>',
1910 2024 ' RewriteEngine On',
1911 2025 ' RewriteCond %{REQUEST_METHOD} !POST',
1912 2026 ' RewriteCond %{QUERY_STRING} ^$',
1913 2027 ' RewriteCond %{HTTP_COOKIE} !(wp\-postpass|wordpress_logged_in|comment_author|woocommerce_cart_hash|edd_items_in_cart) [NC]',
2028 + ' RewriteCond %{HTTP_USER_AGENT} !(Googlebot|Google-InspectionTool|Bingbot|Slurp|DuckDuckBot|Baiduspider|YandexBot|Sogou|Exabot|facebookexternalhit|Twitterbot|LinkedInBot|WhatsApp|TelegramBot|Applebot|AhrefsBot|SemrushBot|MJ12bot|DotBot|PetalBot|BLEXBot|archive\.org_bot|UptimeRobot|Pingdom|ChatGPT-User|GPTBot|ClaudeBot|Bytespider) [NC]',
2029 + ], $slash_conds, [
1914 2030 ' RewriteCond %{DOCUMENT_ROOT}/wp-content/cache/berqwp/html/%{HTTP_HOST}%{REQUEST_URI}/index.html.gz -f',
1915 2031 ' RewriteRule .* /wp-content/cache/berqwp/html/%{HTTP_HOST}%{REQUEST_URI}/index.html.gz [L]',
1916 2032 '</IfModule>',
1917 2033 '<IfModule mod_mime.c>',
@@ -1917,16 +2033,55 @@
1917 2033 '<IfModule mod_mime.c>',
1918 2034 ' <FilesMatch "index\.html\.gz$">',
1919 2035 ' ForceType text/html',
1920 2036 ' AddEncoding gzip .gz',
2037 + ' AddDefaultCharset utf-8',
1921 2038 ' </FilesMatch>',
1922 2039 '</IfModule>',
1923 2040 '<IfModule mod_headers.c>',
1924 2041 ' <FilesMatch "index\.html\.gz$">',
2042 + ' Header set X-BerqWP-Cache "HIT"',
1925 2043 ' Header set X-Served "server"',
2044 + ' Header set Content-Encoding "gzip"',
2045 + ' Header set Vary "Accept-Encoding, Cookie"',
2046 + ' Header set CDN-Cache-Control "max-age=2592000"',
2047 + ' Header set Cache-Control "public, max-age=600, s-maxage=2592000, stale-while-revalidate=86400"',
2048 + ' Header set Cache-Tag "' . $cache_tag_host . '"',
2049 + ' Header set X-Content-Type-Options "nosniff"',
1926 2050 ' </FilesMatch>',
1927 2051 '</IfModule>',
1928 - ];
2052 + '<IfModule mod_expires.c>',
2053 + ' ExpiresActive On',
2054 + ' ExpiresByType text/css "access plus 1 year"',
2055 + ' ExpiresByType application/javascript "access plus 1 year"',
2056 + ' ExpiresByType text/javascript "access plus 1 year"',
2057 + ' ExpiresByType image/jpeg "access plus 1 year"',
2058 + ' ExpiresByType image/png "access plus 1 year"',
2059 + ' ExpiresByType image/gif "access plus 1 year"',
2060 + ' ExpiresByType image/webp "access plus 1 year"',
2061 + ' ExpiresByType image/avif "access plus 1 year"',
2062 + ' ExpiresByType image/svg+xml "access plus 1 year"',
2063 + ' ExpiresByType image/x-icon "access plus 1 year"',
2064 + ' ExpiresByType font/woff "access plus 1 year"',
2065 + ' ExpiresByType font/woff2 "access plus 1 year"',
2066 + ' ExpiresByType application/font-woff "access plus 1 year"',
2067 + ' ExpiresByType application/font-woff2 "access plus 1 year"',
2068 + ' ExpiresByType application/x-font-ttf "access plus 1 year"',
2069 + ' ExpiresByType application/x-font-opentype "access plus 1 year"',
2070 + '</IfModule>',
2071 + '<IfModule mod_headers.c>',
2072 + ' <FilesMatch "\.(css|js)$">',
2073 + ' Header set Cache-Control "public, max-age=31536000, immutable"',
2074 + ' </FilesMatch>',
2075 + ' <FilesMatch "\.(jpg|jpeg|png|gif|webp|avif|svg|ico)$">',
2076 + ' Header set Cache-Control "public, max-age=31536000, immutable"',
2077 + ' </FilesMatch>',
2078 + ' <FilesMatch "\.(woff|woff2|ttf|otf|eot)$">',
2079 + ' Header set Cache-Control "public, max-age=31536000, immutable"',
2080 + ' Header set Access-Control-Allow-Origin "*"',
2081 + ' </FilesMatch>',
2082 + '</IfModule>',
2083 + ]);
1929 2084
1930 2085 // Must appear before the WordPress block so Apache processes it first
1931 2086 $marker = 'BerqWP Cache';
1932 2087 $start = "# BEGIN $marker";
@@ -2102,8 +2257,40 @@
2102 2257 // Fallback: no <head> tag found, return unchanged
2103 2258 return $buffer;
2104 2259 }
2105 2260
2261 +function berqwp_earlyHeadHtml($buffer, $htmlToInsert)
2262 +{
2263 + // Locate <head> opening tag
2264 + if (!preg_match('/<head(\s[^>]*)?>/i', $buffer, $headMatch, PREG_OFFSET_CAPTURE)) {
2265 + return berqwp_prependHtmlToHead($buffer, $htmlToInsert);
2266 + }
2267 +
2268 + $headStart = $headMatch[0][1] + strlen($headMatch[0][0]);
2269 +
2270 + // Bound the search to content inside <head>...</head>
2271 + $headEndPos = stripos($buffer, '</head>', $headStart);
2272 + if ($headEndPos === false) {
2273 + return berqwp_prependHtmlToHead($buffer, $htmlToInsert);
2274 + }
2275 +
2276 + $headContent = substr($buffer, $headStart, $headEndPos - $headStart);
2277 +
2278 + // Find first <script, <link, or <style in the head
2279 + // if (preg_match('/<(script|link|style)[\s>\/]/i', $headContent, $tagMatch, PREG_OFFSET_CAPTURE)) {
2280 +
2281 + $regex = "/<(script|link[^>]+rel=['\"]+(modulepreload|stylesheet|preload)['\"]|style)[\s>\/]/i";
2282 +
2283 + if (preg_match($regex, $headContent, $tagMatch, PREG_OFFSET_CAPTURE)) {
2284 + $insertPos = $headStart + $tagMatch[0][1];
2285 + return substr_replace($buffer, $htmlToInsert . PHP_EOL, $insertPos, 0);
2286 + }
2287 +
2288 + // Fallback: no matching tag in head
2289 + return berqwp_prependHtmlToHead($buffer, $htmlToInsert);
2290 +}
2291 +
2292 +
2106 2293 function berqwp_setup_dropin()
2107 2294 {
2108 2295 if (defined('BERQWP_ADVANCED_CACHE_PATH')) {
2109 2296 $adv_cache_path = BERQWP_ADVANCED_CACHE_PATH;
@@ -2216,9 +2403,8 @@
2216 2403
2217 2404 function berqwp_validate_url_array($urls)
2218 2405 {
2219 2406 $home_host = parse_url(home_url(), PHP_URL_HOST);
2220 - $home_scheme = parse_url(home_url(), PHP_URL_SCHEME);
2221 2407
2222 2408 $urls = array_filter($urls, function ($url) use ($home_host) {
2223 2409 $url_host = parse_url($url, PHP_URL_HOST);
2224 2410
@@ -2229,35 +2415,9 @@
2229 2415
2230 2416 return $url_host === $home_host;
2231 2417 });
2232 2418
2233 - $urls = array_map(function ($url) use ($home_scheme) {
2234 - // Skip invalid URLs
2235 - if (!is_string($url) || $url === '') {
2236 - return $url;
2237 - }
2238 -
2239 - $parts = parse_url($url);
2240 -
2241 - // Relative URL → leave as-is
2242 - if (empty($parts['scheme'])) {
2243 - return $url;
2244 - }
2245 -
2246 - // Rebuild URL with home scheme
2247 - $parts['scheme'] = $home_scheme;
2248 -
2249 - $new_url = $parts['scheme'] . '://';
2250 - $new_url .= $parts['host'] ?? '';
2251 - $new_url .= isset($parts['port']) ? ':' . $parts['port'] : '';
2252 - $new_url .= $parts['path'] ?? '';
2253 - $new_url .= isset($parts['query']) ? '?' . $parts['query'] : '';
2254 - $new_url .= isset($parts['fragment']) ? '#' . $parts['fragment'] : '';
2255 -
2256 - return $new_url;
2257 - }, $urls);
2258 -
2259 - return $urls;
2419 + return array_values($urls);
2260 2420 }
2261 2421
2262 2422 function berqwp_render_toggle($name, $checked) {
2263 2423 ?>
@@ -2302,9 +2462,9 @@
2302 2462 }
2303 2463
2304 2464 function bwp_remove_recently_optimized_entry($page_url)
2305 2465 {
2306 - if (empty($page_url)) return;
2466 + if (empty($page_url)) return;
2307 2467
2308 2468 $log = json_decode(get_option('berqwp_recently_optimized', '[]'), true);
2309 2469 if (!is_array($log)) return;
2310 2470
@@ -2317,5 +2477,12 @@
2317 2477 $configs = $berqconfigs->get_configs();
2318 2478 $license_key = berqwp_get_license_key();
2319 2479
2320 2480 return !empty($configs['site_id']) && !empty($configs['secret']) && !empty($configs['optimization_method']) && $configs['optimization_method'] == 'cloud' && !empty($license_key);
2481 +}
2482 +
2483 +function berqwp_generate_site_id() {
2484 + $blog_id = get_current_blog_id();
2485 + $network_id = function_exists('get_current_network_id') ? get_current_network_id() : 1;
2486 + $siteurl = get_option('siteurl');
2487 + return md5("berqwp|$network_id|$blog_id|$siteurl");
2321 2488 }