• Resolved reviewmylife

    (@reviewmylife)


    Hi, here’s what I’ve had to change to get mod_rewrite mode working on 1and1. They seem to have something weird in their configuration that means the document_root values aren’t consistent between PHP and the .htaccess file. The comment in the code should explain what is going on.

    function wpsc_get_htaccess_info() {
    	global $wp_cache_mobile_enabled, $wp_cache_mobile_prefixes, $wp_cache_mobile_browsers;
    	if ( isset( $_SERVER[ "PHP_DOCUMENT_ROOT" ] ) ) {
    		$document_root = $_SERVER[ "PHP_DOCUMENT_ROOT" ];
    		$apache_root = $_SERVER[ "PHP_DOCUMENT_ROOT" ];
    	} else {
    		$document_root = $_SERVER[ "DOCUMENT_ROOT" ];
    		$apache_root = '%{DOCUMENT_ROOT}';
    	}
    
    	$home_path = get_home_path();
    
    	$content_dir_root = $document_root;
    	if ( strpos( $home_path, '/kunden/' ) === 0 ){
    		// When WordPress is running on 1and1 shared hosting the home_path
    		// starts with /kunden/, however the WP_CONTENT_DIR does not.
    		// Neither does the .htaccess %{DOCUMENT_ROOT} variable.
    		// This prevents the $inst_root from being calculated correctly and
    		// means that the $apache_root is wrong.
    		//
    		// e.g. This is an example of what these values look like on 1and1:
    		// $home_path: /kunden/homepages/xx/dxxxxxxxx/htdocs/site1/
    		// WP_CONTENT_DIR:    /homepages/xx/dxxxxxxxx/htdocs/site1/blog/wp-content
    		// Here we fix up the paths to make mode_rewrite work on 1and1 shared hosting.
    		$content_dir_root = preg_replace( '/\/kunden\//', '/', $content_dir_root, 1 );
    		$apache_root = $document_root;
    	}
    
    	$inst_root = str_replace( '//', '/', '/' . trailingslashit( str_replace( $content_dir_root, '', str_replace( '\\', '/', WP_CONTENT_DIR ) ) ) );
    
    	$home_root = parse_url(get_bloginfo('url'));
    	$home_root = isset( $home_root['path'] ) ? trailingslashit( $home_root['path'] ) : '/';
    
    	$wprules = implode( "\n", extract_from_markers( $home_path.'.htaccess', 'WordPress' ) );
    	$wprules = str_replace( "RewriteEngine On\n", '', $wprules );

    Someone did previously report this issue – https://www.ads-software.com/support/topic/wp-super-cache-10381-doesnt-deliver-cached-pages

    As 1and1 is one of the largest hosting companies out there I think it is worth making the fastest rules work on it.

Viewing 7 replies - 1 through 7 (of 7 total)
  • Thanks for the patch. Is there any reason why you didn’t just use $document_root instead of creating $content_dir_root? The $document_root will be incorrect when passed back from that function as it will still hold the /kunden/ part of the path.

    I checked this into trunk. You can grab an updated wp-cache.php and drop into your wp-super-cache directory.

    Thread Starter reviewmylife

    (@reviewmylife)

    Hi Donncha, I’ve tested your modification to this patch and it is working on my 1and1 account. The correct mod_rewrite rules are now being created in mod_rewrite mode and the supercached pages are being served directly from the supercache directory.

    The reason I added $content_dir_root was to reduce any knock on effects – in case other parts of the plugin relied on the old $document_root value. If it is safe to do so you could just remove the /kunden/ from the $document_root directly.

    Just thinking to myself: If these hosting companies had any sense they’d pay people to check that caching plugins like yours are compatible with their configurations. That way they could squeeze more accounts onto each server. I’m sure the percentage of customers who use WordPress must be significant so it could be well worth their money.

    Also for anyone who is wondering – ‘kunden’ is German for ‘customer’. 1and1 being based in Germany.

    Thread Starter reviewmylife

    (@reviewmylife)

    Hi Donncha, Maybe a bit more work is needed on this. I’ve just had a look at two of my live WordPress sites which are using WP Super Cache. Both are stored in the same 1and1 account.

    I’m getting inconsistent values from get_home_path(). One site starts with ‘/kunden/’ (as did my test site) but the other one doesn’t! And yet both sites are stored in the same directory. Very weird. Which means that this patch would work for one live site but not the other.

    live site1
    #home_path – /homepages/xx/dxxxxxxxx/htdocs/site1/
    #document_root – /kunden/homepages/xx/dxxxxxxxx/htdocs/site1
    #WP_CONTENT_DIR – /homepages/xx/dxxxxxxxx/htdocs/site1/wp-content

    live site2
    #home_path – /kunden/homepages/xx/dxxxxxxxx/htdocs/site2/
    #document_root – /kunden/homepages/xx/dxxxxxxxx/htdocs/site2
    #WP_CONTENT_DIR – /homepages/xx/dxxxxxxxx/htdocs/site2/blog/wp-content

    Maybe the 1and1 check/substr should be done with document_root instead of home_path as this seems to be consistent (at least across my sample of 3 sites (test, live1, and live2). I’ll look into this more and report back.

    BTW – I don’t think the current patch will do any harm. It’s just that it won’t work on all 1and1 sites.

    Thread Starter reviewmylife

    (@reviewmylife)

    I think I now have the explanation for all this path inconsistency.

    On 1and1 they have set Apache and PHP to have different roots. The Apache root starts with /kunden, the PHP root starts with /homepages.

    So in PHP a path like /homepages/xx/dxxxxxxxx/htdocs/site1/index.html would be /kunden/homepages/xx/dxxxxxxxx/htdocs/site1/index.html in Apache.

    Also %{DOCUMENT_ROOT} is not supported in .htaccess files and $_SERVER[ “PHP_DOCUMENT_ROOT” ] is not set.

    Problem1 in original code: This code causes the $apache_root to be set to a value that 1and1 does not support.

    if ( isset( $_SERVER[ "PHP_DOCUMENT_ROOT" ] ) ) {
    		$document_root = $_SERVER[ "PHP_DOCUMENT_ROOT" ];
    		$apache_root = $_SERVER[ "PHP_DOCUMENT_ROOT" ];
    	} else {
    		$document_root = $_SERVER[ "DOCUMENT_ROOT" ];
    		$apache_root = '%{DOCUMENT_ROOT}';
    	}

    Problem2 in original code: This code is trying to remove the Apache path from a PHP path. As Apache sees an extra ‘/kunden’ folder at its base this won’t remove anything from the WP_CONTENT_DIR on 1and1.

    $inst_root = str_replace( '//', '/', '/' . trailingslashit( str_replace( $document_root, '', str_replace( '\\', '/', WP_CONTENT_DIR ) ) ) );

    Problem with the original patch: get_home_path() which is an internal WordPress function returns different values depending on whether the ‘WordPress address’ and the ‘Site address’ (both set in Settings->General) are the same or different. You can see from the get_home_path() code that if the WordPress/Site address values are the same you will get the PHP path. If the values are different you will get the Apache path.

    function get_home_path() {
    	$home = get_option( 'home' );
    	$siteurl = get_option( 'siteurl' );
    	if ( $home != '' && $home != $siteurl ) {
    	        $wp_path_rel_to_home = str_replace($home, '', $siteurl); /* $siteurl - $home */
    	        $pos = strpos($_SERVER["SCRIPT_FILENAME"], $wp_path_rel_to_home);
    	        $home_path = substr($_SERVER["SCRIPT_FILENAME"], 0, $pos);
    		$home_path = trailingslashit( $home_path );
    	} else {
    		$home_path = ABSPATH;
    	}
    
    	return $home_path;
    }

    On most hosts the Apache and PHP path structures are probably the same. But not on 1and1 because of the extra ‘/kunden’ in the Apache path.

    Therefore depending on how your WordPress install is configured the original patch may or may not work. I spotted this problem because some of my WordPress installs are configures with the same blog/site address, and others with a different one.

    Therefore we need to use $document_root instead of get_home_path().

    Updated patch: This updated patch now uses $document_root instead of get_home_path(). The comment has also been updated.

    function wpsc_get_htaccess_info() {
    	global $wp_cache_mobile_enabled, $wp_cache_mobile_prefixes, $wp_cache_mobile_browsers;
    	if ( isset( $_SERVER[ "PHP_DOCUMENT_ROOT" ] ) ) {
    		$document_root = $_SERVER[ "PHP_DOCUMENT_ROOT" ];
    		$apache_root = $_SERVER[ "PHP_DOCUMENT_ROOT" ];
    	} else {
    		$document_root = $_SERVER[ "DOCUMENT_ROOT" ];
    		$apache_root = '%{DOCUMENT_ROOT}';
    	}
    	$content_dir_root = $document_root;
    	if ( strpos( $document_root, '/kunden/' ) === 0 ) {
    		// https://www.ads-software.com/support/topic/plugin-wp-super-cache-how-to-get-mod_rewrite-working-on-1and1-shared-hosting?replies=1
    		// On 1and1, PHP's directory structure starts with '/homepages'. The
    		// Apache directory structure has an extra '/kunden' before it.
    		// Also 1and1 does not support the %{DOCUMENT_ROOT} variable in
    		// .htaccess files.
    		// This prevents the $inst_root from being calculated correctly and
    		// means that the $apache_root is wrong.
    		//
    		// e.g. This is an example of how Apache and PHP see the directory
    		// structure on	1and1:
    		// Apache: /kunden/homepages/xx/dxxxxxxxx/htdocs/site1/index.html
    		// PHP:           /homepages/xx/dxxxxxxxx/htdocs/site1/index.html
    		// Here we fix up the paths to make mode_rewrite work on 1and1 shared hosting.
    		$content_dir_root = substr( $content_dir_root, 7 );
    		$apache_root = $document_root;
    	}
    	$home_path = get_home_path();
    	$home_root = parse_url(get_bloginfo('url'));
    	$home_root = isset( $home_root['path'] ) ? trailingslashit( $home_root['path'] ) : '/';
    	$inst_root = str_replace( '//', '/', '/' . trailingslashit( str_replace( $content_dir_root, '', str_replace( '\\', '/', WP_CONTENT_DIR ) ) ) );
    	$wprules = implode( "\n", extract_from_markers( $home_path.'.htaccess', 'WordPress' ) );

    Thanks for the updated patch, I’ve just checked it into trunk if you want to give that a go! Appreciate the time you’ve taken to work on this! ??

    Thread Starter reviewmylife

    (@reviewmylife)

    Hi, the updated patch works ??

    And I’ve raised this ticket on WordPress in case they fancy fixing the inconsistent get_home_path() behaviour.

Viewing 7 replies - 1 through 7 (of 7 total)
  • The topic ‘[Plugin: WP Super Cache] How to get mod_rewrite working on 1and1 shared hosting’ is closed to new replies.