Describe the bug
In a Windows environment that uses backslashes for the path, str_replace() will fail to replace the path correctly because ABSPATH and $_SERVER['DOCUMENT_ROOT'] uses backslashes, but we're using forward slashes, so the strings won't match, and the path won't be replaced.
- When
str_replace() fails, this causes $cache_root to be incorrect.
- In the
.htaccess, the rules written to it will contain an incorrect absolute path, and Apache cannot interpret that and every cache hit will fall through PHP.
The root cause is from inc/functions/htaccess.php:283-284 here:
// Get cache 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 ), '/' );
}
and here inc/functions/htaccess.php: 305 & 313:
$is_1and1_or_force = apply_filters( 'rocket_force_full_path', strpos( sanitize_text_field( wp_unslash( $_SERVER['DOCUMENT_ROOT'] ) ), '/kunden/' ) === 0 );
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}';
}
Suggestion
We have a similar normalizing method for filesystem path here, we could also apply a similar method for this case, using the wp_normalize_path to normalize both WP_ROCKET_CACHE_PATH and $_SERVER['DOCUMENT_ROOT'].
Customer suggested this fix:
Normalize separators with WordPress's own wp_normalize_path() and drop the destructive wp_unslash():
// Get cache root.
$document_root = isset( $_SERVER['DOCUMENT_ROOT'] )
? wp_normalize_path( sanitize_text_field( $_SERVER['DOCUMENT_ROOT'] ) )
: '';
$cache_path = wp_normalize_path( WP_ROCKET_CACHE_PATH );
$abspath = wp_normalize_path( ABSPATH );
if ( strpos( $cache_path, $abspath ) === false && '' !== $document_root ) {
$cache_root = '/' . ltrim( str_replace( $document_root, '', $cache_path ), '/' );
} else {
$cache_root = '/' . ltrim( $site_root . str_replace( $abspath, '', $cache_path ), '/' );
}
Additional context
Describe the bug
In a Windows environment that uses backslashes for the path,
str_replace()will fail to replace the path correctly becauseABSPATHand$_SERVER['DOCUMENT_ROOT']uses backslashes, but we're using forward slashes, so the strings won't match, and the path won't be replaced.str_replace()fails, this causes $cache_root to be incorrect..htaccess, the rules written to it will contain an incorrect absolute path, and Apache cannot interpret that and every cache hit will fall through PHP.The root cause is from
inc/functions/htaccess.php:283-284here:and here
inc/functions/htaccess.php:305&313:$is_1and1_or_force = apply_filters( 'rocket_force_full_path', strpos( sanitize_text_field( wp_unslash( $_SERVER['DOCUMENT_ROOT'] ) ), '/kunden/' ) === 0 );Suggestion
We have a similar normalizing method for filesystem path here, we could also apply a similar method for this case, using the wp_normalize_path to normalize both
WP_ROCKET_CACHE_PATHand$_SERVER['DOCUMENT_ROOT'].Customer suggested this fix:
Normalize separators with WordPress's own
wp_normalize_path()and drop the destructivewp_unslash():Additional context