<?php defined('ABSPATH') || exit; function flush_rocket_htaccess($remove_rules = false) { global $is_apache; if (!$is_apache || apply_filters('rocket_disable_htaccess', false) && !$remove_rules) { return false; } if (!function_exists('get_home_path')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } $htaccess_file = get_home_path() . '.htaccess'; if (!rocket_direct_filesystem()->is_writable($htaccess_file)) { return false; } $ftmp = rocket_direct_filesystem()->get_contents($htaccess_file); if (false === $ftmp) { return false; } $has_wp_rules = rocket_has_wp_htaccess_rules($ftmp); $ftmp = preg_replace('/\\s*# BEGIN WP Rocket.*# END WP Rocket\\s*?/isU', PHP_EOL . PHP_EOL, $ftmp); $ftmp = ltrim($ftmp); if (!$remove_rules) { $ftmp = get_rocket_htaccess_marker() . PHP_EOL . $ftmp; } if ($has_wp_rules && !rocket_has_wp_htaccess_rules($ftmp)) { return false; } return rocket_put_content($htaccess_file, $ftmp); } function rocket_htaccess_rules_test($rules_name) { $request_args = apply_filters('rocket_htaccess_rules_test_args', ['redirection' => 0, 'timeout' => 5, 'sslverify' => apply_filters('https_local_ssl_verify', false), 'user-agent' => 'wprocketbot', 'cookies' => $_COOKIE]); $response = wp_remote_get(site_url(WP_ROCKET_URL . 'tests/' . $rules_name . '/index.html'), $request_args); if (is_wp_error($response)) { return $response; } return 500 !== wp_remote_retrieve_response_code($response); } function get_rocket_htaccess_marker() { $marker = '# BEGIN WP Rocket v' . WP_ROCKET_VERSION . PHP_EOL; $marker .= apply_filters('before_rocket_htaccess_rules', ''); $marker .= get_rocket_htaccess_charset(); $marker .= get_rocket_htaccess_etag(); $marker .= get_rocket_htaccess_web_fonts_access(); $marker .= get_rocket_htaccess_files_match(); $marker .= get_rocket_htaccess_mod_expires(); $marker .= get_rocket_htaccess_mod_deflate(); if (\WP_Rocket\Buffer\Cache::can_generate_caching_files() && !is_rocket_generate_caching_mobile_files()) { $marker .= get_rocket_htaccess_mod_rewrite(); } $marker .= apply_filters('after_rocket_htaccess_rules', ''); $marker .= '# END WP Rocket' . PHP_EOL; $marker = apply_filters('rocket_htaccess_marker', $marker); return $marker; } function get_rocket_htaccess_mod_rewrite() { if (is_multisite()) { return; } if (defined('WPLANG') && 'ko_KR' === WPLANG || 'ko_KR' === get_locale()) { return; } $home_root = rocket_extract_url_component(home_url(), PHP_URL_PATH); $home_root = isset($home_root) ? trailingslashit($home_root) : '/'; $site_root = rocket_extract_url_component(site_url(), PHP_URL_PATH); $site_root = isset($site_root) ? trailingslashit($site_root) : ''; if (strpos(WP_ROCKET_CACHE_PATH, ABSPATH) === false && isset($_SERVER['DOCUMENT_ROOT'])) { $cache_root = '/' . ltrim(str_replace(sanitize_text_field(wp_unslash($_SERVER['DOCUMENT_ROOT'])), '', WP_ROCKET_CACHE_PATH), '/'); } else { $cache_root = '/' . ltrim($site_root . str_replace(ABSPATH, '', WP_ROCKET_CACHE_PATH), '/'); } $http_host = apply_filters('rocket_url_no_dots', false) ? rocket_remove_url_protocol(home_url()) : '%{HTTP_HOST}'; $is_1and1_or_force = apply_filters('rocket_force_full_path', strpos(sanitize_text_field(wp_unslash($_SERVER['DOCUMENT_ROOT'])), '/kunden/') === 0); $rules = ''; $gzip_rules = ''; $enc = ''; if ($is_1and1_or_force) { $cache_dir_path = str_replace('/kunden/', '/', WP_ROCKET_CACHE_PATH) . $http_host . '%{REQUEST_URI}'; } else { $cache_dir_path = '%{DOCUMENT_ROOT}/' . ltrim($cache_root, '/') . $http_host . '%{REQUEST_URI}'; } if (function_exists('gzencode') && apply_filters('rocket_force_gzip_htaccess_rules', true)) { $rules = '<IfModule mod_mime.c>' . PHP_EOL; $rules .= 'AddType text/html .html_gzip' . PHP_EOL; $rules .= 'AddEncoding gzip .html_gzip' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; $rules .= '<IfModule mod_setenvif.c>' . PHP_EOL; $rules .= 'SetEnvIfNoCase Request_URI \\.html_gzip$ no-gzip' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL . PHP_EOL; $gzip_rules .= 'RewriteCond %{HTTP:Accept-Encoding} gzip' . PHP_EOL; $gzip_rules .= 'RewriteRule .* - [E=WPR_ENC:_gzip]' . PHP_EOL; $enc = '%{ENV:WPR_ENC}'; } $rules .= '<IfModule mod_rewrite.c>' . PHP_EOL; $rules .= 'RewriteEngine On' . PHP_EOL; $rules .= 'RewriteBase ' . $home_root . PHP_EOL; $rules .= get_rocket_htaccess_ssl_rewritecond(); $rules .= rocket_get_webp_rewritecond($cache_dir_path); $rules .= $gzip_rules; $rules .= 'RewriteCond %{REQUEST_METHOD} GET' . PHP_EOL; $rules .= 'RewriteCond %{QUERY_STRING} =""' . PHP_EOL; $cookies = get_rocket_cache_reject_cookies(); if ($cookies) { $rules .= 'RewriteCond %{HTTP:Cookie} !(' . $cookies . ') [NC]' . PHP_EOL; } $uri = get_rocket_cache_reject_uri(); if ($uri) { $rules .= 'RewriteCond %{REQUEST_URI} !^(' . $uri . ')$ [NC]' . PHP_EOL; } $rules .= !is_rocket_cache_mobile() ? get_rocket_htaccess_mobile_rewritecond() : ''; $ua = get_rocket_cache_reject_ua(); if ($ua) { $rules .= 'RewriteCond %{HTTP_USER_AGENT} !^(' . $ua . ').* [NC]' . PHP_EOL; } $rules .= 'RewriteCond "' . $cache_dir_path . '/index%{ENV:WPR_SSL}%{ENV:WPR_WEBP}.html' . $enc . '" -f' . PHP_EOL; $rules .= 'RewriteRule .* "' . $cache_root . $http_host . '%{REQUEST_URI}/index%{ENV:WPR_SSL}%{ENV:WPR_WEBP}.html' . $enc . '" [L]' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; $rules = apply_filters('rocket_htaccess_mod_rewrite', $rules); return $rules; } function get_rocket_htaccess_mobile_rewritecond() { if (is_multisite()) { return; } $rules = 'RewriteCond %{HTTP:X-Wap-Profile} !^[a-z0-9\\"]+ [NC]' . PHP_EOL; $rules .= 'RewriteCond %{HTTP:Profile} !^[a-z0-9\\"]+ [NC]' . PHP_EOL; $rules .= 'RewriteCond %{HTTP_USER_AGENT} !^.*(2.0\\ MMP|240x320|400X240|AvantGo|BlackBerry|Blazer|Cellphone|Danger|DoCoMo|Elaine/3.0|EudoraWeb|Googlebot-Mobile|hiptop|IEMobile|KYOCERA/WX310K|LG/U990|MIDP-2.|MMEF20|MOT-V|NetFront|Newt|Nintendo\\ Wii|Nitro|Nokia|Opera\\ Mini|Palm|PlayStation\\ Portable|portalmmm|Proxinet|ProxiNet|SHARP-TQ-GX10|SHG-i900|Small|SonyEricsson|Symbian\\ OS|SymbianOS|TS21i-10|UP.Browser|UP.Link|webOS|Windows\\ CE|WinWAP|YahooSeeker/M1A1-R2D2|iPhone|iPod|Android|BlackBerry9530|LG-TU915\\ Obigo|LGE\\ VX|webOS|Nokia5800).* [NC]' . PHP_EOL; $rules .= 'RewriteCond %{HTTP_USER_AGENT} !^(w3c\\ |w3c-|acs-|alav|alca|amoi|audi|avan|benq|bird|blac|blaz|brew|cell|cldc|cmd-|dang|doco|eric|hipt|htc_|inno|ipaq|ipod|jigs|kddi|keji|leno|lg-c|lg-d|lg-g|lge-|lg/u|maui|maxo|midp|mits|mmef|mobi|mot-|moto|mwbp|nec-|newt|noki|palm|pana|pant|phil|play|port|prox|qwap|sage|sams|sany|sch-|sec-|send|seri|sgh-|shar|sie-|siem|smal|smar|sony|sph-|symb|t-mo|teli|tim-|tosh|tsm-|upg1|upsi|vk-v|voda|wap-|wapa|wapi|wapp|wapr|webc|winw|winw|xda\\ |xda-).* [NC]' . PHP_EOL; $rules = apply_filters('rocket_htaccess_mobile_rewritecond', $rules); return $rules; } function get_rocket_htaccess_ssl_rewritecond() { $rules = 'RewriteCond %{HTTPS} on [OR]' . PHP_EOL; $rules .= 'RewriteCond %{SERVER_PORT} ^443$ [OR]' . PHP_EOL; $rules .= 'RewriteCond %{HTTP:X-Forwarded-Proto} https' . PHP_EOL; $rules .= 'RewriteRule .* - [E=WPR_SSL:-https]' . PHP_EOL; $rules = apply_filters('rocket_htaccess_ssl_rewritecond', $rules); return $rules; } function rocket_get_webp_rewritecond($cache_dir_path) { if (!get_rocket_option('cache_webp')) { return ''; } $rules = 'RewriteCond %{HTTP_ACCEPT} image/webp' . PHP_EOL; $rules .= 'RewriteCond "' . $cache_dir_path . '/.no-webp" !-f' . PHP_EOL; $rules .= 'RewriteRule .* - [E=WPR_WEBP:-webp]' . PHP_EOL; return apply_filters('rocket_webp_rewritecond', $rules); } function get_rocket_htaccess_mod_deflate() { $rules = '# Gzip compression' . PHP_EOL; $rules .= '<IfModule mod_deflate.c>' . PHP_EOL; $rules .= '# Active compression' . PHP_EOL; $rules .= 'SetOutputFilter DEFLATE' . PHP_EOL; $rules .= '# Force deflate for mangled headers' . PHP_EOL; $rules .= '<IfModule mod_setenvif.c>' . PHP_EOL; $rules .= '<IfModule mod_headers.c>' . PHP_EOL; $rules .= 'SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\\s*,?\\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding' . PHP_EOL; $rules .= 'RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding' . PHP_EOL; $rules .= '# Don’t compress images and other uncompressible content' . PHP_EOL; $rules .= 'SetEnvIfNoCase Request_URI \\' . PHP_EOL; $rules .= '\\.(?:gif|jpe?g|png|rar|zip|exe|flv|mov|wma|mp3|avi|swf|mp?g|mp4|webm|webp|pdf)$ no-gzip dont-vary' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL . PHP_EOL; $rules .= '# Compress all output labeled with one of the following MIME-types' . PHP_EOL; $rules .= '<IfModule mod_filter.c>' . PHP_EOL; $rules .= 'AddOutputFilterByType DEFLATE application/atom+xml \\ application/javascript \\ application/json \\ application/rss+xml \\ application/vnd.ms-fontobject \\ application/x-font-ttf \\ application/xhtml+xml \\ application/xml \\ font/opentype \\ image/svg+xml \\ image/x-icon \\ text/css \\ text/html \\ text/plain \\ text/x-component \\ text/xml' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; $rules .= '<IfModule mod_headers.c>' . PHP_EOL; $rules .= 'Header append Vary: Accept-Encoding' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL . PHP_EOL; $rules = apply_filters('rocket_htaccess_mod_deflate', $rules); return $rules; } function get_rocket_htaccess_mod_expires() { $rules = <<<HTACCESS # Expires headers (for better cache control) <IfModule mod_expires.c> \tExpiresActive on \tExpiresDefault "access plus 1 month" \t# cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5) \tExpiresByType text/cache-manifest "access plus 0 seconds" \t# Your document html \tExpiresByType text/html "access plus 0 seconds" \t# Data \tExpiresByType text/xml "access plus 0 seconds" \tExpiresByType application/xml "access plus 0 seconds" \tExpiresByType application/json "access plus 0 seconds" \t# Feed \tExpiresByType application/rss+xml "access plus 1 hour" \tExpiresByType application/atom+xml "access plus 1 hour" \t# Favicon (cannot be renamed) \tExpiresByType image/x-icon "access plus 1 week" \t# Media: images, video, audio \tExpiresByType image/gif "access plus 4 months" \tExpiresByType image/png "access plus 4 months" \tExpiresByType image/jpeg "access plus 4 months" \tExpiresByType image/webp "access plus 4 months" \tExpiresByType video/ogg "access plus 4 months" \tExpiresByType audio/ogg "access plus 4 months" \tExpiresByType video/mp4 "access plus 4 months" \tExpiresByType video/webm "access plus 4 months" \t# HTC files (css3pie) \tExpiresByType text/x-component "access plus 1 month" \t# Webfonts \tExpiresByType font/ttf "access plus 4 months" \tExpiresByType font/otf "access plus 4 months" \tExpiresByType font/woff "access plus 4 months" \tExpiresByType font/woff2 "access plus 4 months" \tExpiresByType image/svg+xml "access plus 1 month" \tExpiresByType application/vnd.ms-fontobject "access plus 1 month" \t# CSS and JavaScript \tExpiresByType text/css "access plus 1 year" \tExpiresByType application/javascript "access plus 1 year" </IfModule> HTACCESS; $rules = apply_filters('rocket_htaccess_mod_expires', $rules); return $rules; } function get_rocket_htaccess_charset() { $charset = preg_replace('/[^a-zA-Z0-9_\\-\\.:]+/', '', get_bloginfo('charset', 'display')); $rules = "# Use {$charset} encoding for anything served text/plain or text/html" . PHP_EOL; $rules .= "AddDefaultCharset {$charset}" . PHP_EOL; $rules .= "# Force {$charset} for a number of file formats" . PHP_EOL; $rules .= '<IfModule mod_mime.c>' . PHP_EOL; $rules .= "AddCharset {$charset} .atom .css .js .json .rss .vtt .xml" . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL . PHP_EOL; $rules = apply_filters('rocket_htaccess_charset', $rules); return $rules; } function get_rocket_htaccess_files_match() { $rules = '<IfModule mod_alias.c>' . PHP_EOL; $rules .= '<FilesMatch "\\.(html|htm|rtf|rtx|txt|xsd|xsl|xml)$">' . PHP_EOL; $rules .= '<IfModule mod_headers.c>' . PHP_EOL; $rules .= 'Header set X-Powered-By "WP Rocket/' . WP_ROCKET_VERSION . '"' . PHP_EOL; $rules .= 'Header unset Pragma' . PHP_EOL; $rules .= 'Header append Cache-Control "public"' . PHP_EOL; $rules .= 'Header unset Last-Modified' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; $rules .= '</FilesMatch>' . PHP_EOL . PHP_EOL; $rules .= '<FilesMatch "\\.(css|htc|js|asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|json|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|otf|odb|odc|odf|odg|odp|ods|odt|ogg|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|tif|tiff|ttf|ttc|wav|wma|wri|xla|xls|xlsx|xlt|xlw|zip)$">' . PHP_EOL; $rules .= '<IfModule mod_headers.c>' . PHP_EOL; $rules .= 'Header unset Pragma' . PHP_EOL; $rules .= 'Header append Cache-Control "public"' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; $rules .= '</FilesMatch>' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL . PHP_EOL; $rules = apply_filters('rocket_htaccess_files_match', $rules); return $rules; } function get_rocket_htaccess_etag() { $rules = '# FileETag None is not enough for every server.' . PHP_EOL; $rules .= '<IfModule mod_headers.c>' . PHP_EOL; $rules .= 'Header unset ETag' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL . PHP_EOL; $rules .= '# Since we’re sending far-future expires, we don’t need ETags for static content.' . PHP_EOL; $rules .= '# developer.yahoo.com/performance/rules.html#etags' . PHP_EOL; $rules .= 'FileETag None' . PHP_EOL . PHP_EOL; $rules = apply_filters('rocket_htaccess_etag', $rules); return $rules; } function get_rocket_htaccess_web_fonts_access() { if (!get_rocket_option('cdn', false)) { return; } $rules = '# Send CORS headers if browsers request them; enabled by default for images.' . PHP_EOL; $rules .= '<IfModule mod_setenvif.c>' . PHP_EOL; $rules .= '<IfModule mod_headers.c>' . PHP_EOL; $rules .= '# mod_headers, y u no match by Content-Type?!' . PHP_EOL; $rules .= '<FilesMatch "\\.(cur|gif|png|jpe?g|svgz?|ico|webp)$">' . PHP_EOL; $rules .= 'SetEnvIf Origin ":" IS_CORS' . PHP_EOL; $rules .= 'Header set Access-Control-Allow-Origin "*" env=IS_CORS' . PHP_EOL; $rules .= '</FilesMatch>' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL . PHP_EOL; $rules .= '# Allow access to web fonts from all domains.' . PHP_EOL; $rules .= '<FilesMatch "\\.(eot|otf|tt[cf]|woff2?)$">' . PHP_EOL; $rules .= '<IfModule mod_headers.c>' . PHP_EOL; $rules .= 'Header set Access-Control-Allow-Origin "*"' . PHP_EOL; $rules .= '</IfModule>' . PHP_EOL; $rules .= '</FilesMatch>' . PHP_EOL . PHP_EOL; $rules = apply_filters('rocket_htaccess_web_fonts_access', $rules); return $rules; } function rocket_has_wp_htaccess_rules($content) { if (is_multisite()) { $has_wp_rules = strpos($content, '# add a trailing slash to /wp-admin') !== false; } else { $has_wp_rules = strpos($content, '# BEGIN WordPress') !== false; } return apply_filters('rocket_has_wp_htaccess_rules', $has_wp_rules, $content); } function rocket_check_htaccess_rules() { if (!function_exists('get_home_path')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } $htaccess_file = get_home_path() . '.htaccess'; if (!rocket_direct_filesystem()->is_readable($htaccess_file)) { return false; } $htaccess = rocket_direct_filesystem()->get_contents($htaccess_file); if (preg_match('/\\s*# BEGIN WP Rocket.*# END WP Rocket\\s*?/isU', $htaccess)) { return true; } return false; }