Skip to content

Commit

Permalink
handle .htaccess without WordPress markers and no end-of-line at EOF …
Browse files Browse the repository at this point in the history
…correctly

When custom .htaccess is used with no trailing line, the configuration injected by W3TC didn't insert line break before adding own rules causing a corrupt .htaccess generation
  • Loading branch information
maxicus committed Dec 11, 2019
1 parent 90ad342 commit 20429ed
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 117 deletions.
102 changes: 12 additions & 90 deletions PgCache_Environment.php
Original file line number Diff line number Diff line change
Expand Up @@ -397,102 +397,24 @@ private function wp_config_remove_from_content( $config_data ) {
* returns true if modifications has been made
*/
private function rules_core_add( $config, $exs ) {
$path = Util_Rule::get_pgcache_rules_core_path();
if ( $path === false )
return;

$original_data = @file_get_contents( $path );
if ( $original_data === false )
$original_data = '';

$data = $original_data;

if ( $has_wpsc = Util_Rule::has_rules( $data, W3TC_MARKER_BEGIN_PGCACHE_WPSC, W3TC_MARKER_END_PGCACHE_WPSC ) )
$data = Util_Rule::erase_rules( $data, W3TC_MARKER_BEGIN_PGCACHE_WPSC, W3TC_MARKER_END_PGCACHE_WPSC );

$rules = $this->rules_core_generate( $config );
$rules_missing = ( strstr( Util_Rule::clean_rules( $data ), Util_Rule::clean_rules( $rules ) ) === false );


if ( !$has_wpsc && !$rules_missing )
return; // modification of file not required


$replace_start = strpos( $data, W3TC_MARKER_BEGIN_PGCACHE_CORE );
$replace_end = strpos( $data, W3TC_MARKER_END_PGCACHE_CORE );

if ( $replace_start !== false && $replace_end !== false && $replace_start < $replace_end ) {
$replace_length = $replace_end - $replace_start +
strlen( W3TC_MARKER_END_PGCACHE_CORE ) + 1;
} else {
$replace_start = false;
$replace_length = 0;

$search = array(
Util_Rule::add_rules( $exs, Util_Rule::get_pgcache_rules_core_path(),
$this->rules_core_generate( $config ),
W3TC_MARKER_BEGIN_PGCACHE_CORE,
W3TC_MARKER_END_PGCACHE_CORE,
array(
W3TC_MARKER_BEGIN_BROWSERCACHE_NO404WP => 0,
W3TC_MARKER_BEGIN_WORDPRESS => 0,
W3TC_MARKER_END_MINIFY_CORE =>
strlen( W3TC_MARKER_END_MINIFY_CORE ) + 1,
strlen( W3TC_MARKER_END_MINIFY_CORE ) + 1,
W3TC_MARKER_END_BROWSERCACHE_CACHE =>
strlen( W3TC_MARKER_END_BROWSERCACHE_CACHE ) + 1,
strlen( W3TC_MARKER_END_BROWSERCACHE_CACHE ) + 1,
W3TC_MARKER_END_PGCACHE_CACHE =>
strlen( W3TC_MARKER_END_PGCACHE_CACHE ) + 1,
strlen( W3TC_MARKER_END_PGCACHE_CACHE ) + 1,
W3TC_MARKER_END_MINIFY_CACHE =>
strlen( W3TC_MARKER_END_MINIFY_CACHE ) + 1
);

foreach ( $search as $string => $length ) {
$replace_start = strpos( $data, $string );

if ( $replace_start !== false ) {
$replace_start += $length;
break;
}
}
}

if ( $replace_start !== false ) {
$data = Util_Rule::trim_rules( substr_replace( $data, $rules,
$replace_start, $replace_length ) );
} else {
$data = Util_Rule::trim_rules( $data . $rules );
}

try {
Util_WpFile::write_to_file( $path, $data );
} catch ( Util_WpFile_FilesystemOperationException $ex ) {
if ( $has_wpsc )
$exs->push( new Util_WpFile_FilesystemModifyException(
$ex->getMessage(), $ex->credentials_form(),
sprintf( __( 'Edit file <strong>%s</strong> and remove all lines between and including
<strong>%s</strong> and <strong>%s</strong> markers.', 'w3-total-cache' )
, $path
, W3TC_MARKER_BEGIN_PGCACHE_WPSC
, W3TC_MARKER_END_PGCACHE_WPSC
), $path ) );

if ( $rules_missing ) {
if ( strpos( $data, W3TC_MARKER_BEGIN_PGCACHE_CORE ) !== false )
$exs->push( new Util_WpFile_FilesystemModifyException(
$ex->getMessage(), $ex->credentials_form(),
sprintf( __( 'Edit file <strong>%s</strong> and replace all lines between and including
<strong>%s</strong> and <strong>%s</strong> markers with:', 'w3-total-cache' )
, $path
, W3TC_MARKER_BEGIN_PGCACHE_CORE
, W3TC_MARKER_END_PGCACHE_CORE
), $path, $rules ) );
else
$exs->push( new Util_WpFile_FilesystemModifyException(
$ex->getMessage(), $ex->credentials_form(),
sprintf( __( 'Edit file <strong>%s</strong> and add the following rules above the WordPress
directives:' )
, $path
), $path, $rules ) );
}
return;
}

Util_Rule::after_rules_modified();
strlen( W3TC_MARKER_END_MINIFY_CACHE ) + 1
),
true
);
}

/**
Expand Down
80 changes: 53 additions & 27 deletions Util_Rule.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,36 +224,59 @@ static public function has_rules( $rules, $start, $end ) {
/**
*
*
* @param Util_Environment_Exceptions $exs
* @param string $path
* @param string $rules
* @param string $start
* @param string $end
* @param array $order
* @param Util_Environment_Exceptions $exs exceptions to fill on error
* @param string $path filename of rules file to modify
* @param string $rules rules to add
* @param string $start start marker
* @param string $end end marker
* @param array $order order where to place if some marker exists
* @param boolean $remove_wpsc if WPSC rules should be removed to avoid
* inconsistent rules generation
*/
static public function add_rules( $exs, $path, $rules, $start, $end, $order ) {
if ( empty( $path ) )
static public function add_rules( $exs, $path, $rules, $start, $end, $order,
$remove_wpsc = false ) {
if ( empty( $path ) ) {
return;
}

$data = @file_get_contents( $path );

if ( $data === false )
if ( empty( $data ) ) {
$data = '';
}

$modified = false;
if ( $remove_wpsc ) {
if ( Util_Rule::has_rules(
$data,
W3TC_MARKER_BEGIN_PGCACHE_WPSC,
W3TC_MARKER_END_PGCACHE_WPSC ) ) {
$data = Util_Rule::erase_rules(
$data,
W3TC_MARKER_BEGIN_PGCACHE_WPSC,
W3TC_MARKER_END_PGCACHE_WPSC );
$modified = true;
}
}

if ( empty( $rules ) ) {
$rules_present = ( strpos( $data, $start ) !== false );
if ( !$rules_present )
// rules removal mode
$rules_present = ( strpos( $data, $start ) !== false );
if ( !$modified && !$rules_present ) {
return;
}
} else {
// rules creation mode
$rules_missing = ( strstr( Util_Rule::clean_rules( $data ), Util_Rule::clean_rules( $rules ) ) === false );
if ( !$rules_missing )
if ( !$modified && !$rules_missing ) {
return;
}
}

$replace_start = strpos( $data, $start );
$replace_end = strpos( $data, $end );

if ( $replace_start !== false && $replace_end !== false && $replace_start < $replace_end ) {
// old rules exists, replace mode
$replace_length = $replace_end - $replace_start + strlen( $end ) + 1;
} else {
$replace_start = false;
Expand All @@ -274,28 +297,31 @@ static public function add_rules( $exs, $path, $rules, $start, $end, $order ) {
if ( $replace_start !== false ) {
$data = Util_Rule::trim_rules( substr_replace( $data, $rules, $replace_start, $replace_length ) );
} else {
$data = Util_Rule::trim_rules( $data . $rules );
$data = Util_Rule::trim_rules( rtrim( $data ) . "\n" . $rules );
}

if ( strpos( $path, W3TC_CACHE_DIR ) === false || Util_Environment::is_nginx() ) {
// writing to system rules file, may be potentially write-protected
try {
Util_WpFile::write_to_file( $path, $data );
} catch ( Util_WpFile_FilesystemOperationException $ex ) {
if ( $replace_start !== false )
$exs->push( new Util_WpFile_FilesystemModifyException(
$ex->getMessage(), $ex->credentials_form(),
sprintf( __( 'Edit file <strong>%s
</strong> and replace all lines between and including <strong>%s</strong> and
<strong>%s</strong> markers with:', 'w3-total-caceh' ), $path, $start, $end ), $path, $rules ) );
else
$exs->push( new Util_WpFile_FilesystemModifyException(
$ex->getMessage(), $ex->credentials_form(),
sprintf( __( 'Edit file <strong>%s</strong> and add the following rules
above the WordPress directives:', 'w3-total-cache' ),
$path ), $path, $rules ) );
if ( $replace_start !== false ) {
$message = sprintf( __( 'Edit file <strong>%s</strong> and replace all lines between and including <strong>%s</strong> and <strong>%s</strong> markers with:',
'w3-total-caceh' ), $path, $start, $end );
} else {
$message = sprintf( __( 'Edit file <strong>%s</strong> and add the following rules above the WordPress directives:',
'w3-total-cache' ), $path );
}

$ex = new Util_WpFile_FilesystemModifyException(
$ex->getMessage(), $ex->credentials_form(),
$message, $path, $rules );

$exs->push( $ex );
return;
}
} else {
// writing to own rules file in cache folder
if ( !@file_exists( dirname( $path ) ) ) {
Util_File::mkdir_from( dirname( $path ), W3TC_CACHE_DIR );
}
Expand Down Expand Up @@ -351,7 +377,7 @@ static public function remove_rules( $exs, $path, $start, $end ) {
$exs->push( new Util_WpFile_FilesystemModifyException(
$ex->getMessage(), $ex->credentials_form(),
sprintf( __( 'Edit file <strong>%s</strong> and remove all lines between and including <strong>%s</strong>
and <strong>%s</strong> markers.', 'w3-total-cache' ), $path, $start, $end ), $path ) );
and <strong>%s</strong> markers.', 'w3-total-cache' ), $path, $start, $end ), $path ) );
}
}

Expand Down

0 comments on commit 20429ed

Please sign in to comment.