Skip to content

On Windows, DOCUMENT_ROOT use backslashes, but WP_ROCKET_CACHE_PATH uses forward slashes, causing str_replace() to fail #8523

Description

@suzoutlet

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions