WordPress.org

Make WordPress Core

Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#14904 closed defect (bug) (duplicate)

Install page not redirecting to wp-admin/ on IIS6

Reported by: knutsp Owned by:
Milestone: Priority: normal
Severity: normal Version: 3.0.1
Component: Upgrade/Install Keywords:
Focuses: Cc:

Description

Steps to reproduce:

  1. Download and extract to Windows Server 2003 with IIS6 (fast-cgi, PHP 5.3.3)
  2. Create a wp-config.php file pointing to an empty database or any database with no tables matching the selected prefix.
  3. Create a new virtual directory on IIS site example.com named myblog, pointing to the newly created wordpress directory, hence accessible as URL http://example.com/myblog/[[BR]]
  4. Point your browser to this (root) URL (you will not be redirected), and the WordPress install page (step 1) will appear
  5. Fill out the form and hit Install WordPress
  6. Tthe browser will show URL http://example.com/myblog/install.php?step=2 and status 404 Not found is shown.

I think that the error is in step 4. You should be redirected to http://example.com/myblog/wp-admin/install.php

If you in step 4 direct yout browser to http://example.com/myblog/wp-admin/ the installation will go on without this error.

Tested with Firefox and Chrome. Works fine on IIS7.

Attachments (1)

server-dump.txt (9.3 KB) - added by knutsp 4 years ago.

Download all attachments as: .zip

Change History (11)

comment:2 follow-up: dd324 years ago

can you post a dump of $_SERVER for the install.php page?

this sounds to me like WordPress can't determine the folder correctly.. You may want to dump $_SERVER in both wp-config.php and in install.php as $_SERVER may be modified between them. (see wp_fix_server_vars() in wp-includes/load.php - I'm not sure if that's run for Installation however)

comment:3 in reply to: ↑ 2 knutsp4 years ago

Replying to dd32:

can you post a dump of $_SERVER for the install.php page?

Dump for both wp-config.php and install.php. Both dumps are made while the browser address bar shows http://sparhell.no/kari/

knutsp4 years ago

comment:4 follow-up: dd324 years ago

  • Keywords reporter-feedback added
  1. Point your browser to this (root) URL (you will not be redirected), and the WordPress install page (step 1) will appear

That is indeed your problem.

i've just installed 2003 R2, Enabled IIS6, Installed the latest FastCGI extension from iis.net, Run the PHP 5.3.3 installer, etc

Extracted wordpress files to C:\inetpub\wwwroot\wordpress Created a Virtual Directory 'blog' to point to that folder as well

Loaded http://localhost/blog/ and was redirected to the folder as expected. My $_SERVER contents looks the same as your's for the most part..

Have you configured something else related to redirects, or Rewrites, or something? I have a feeling something in your server stack is intercepting the redirection and not passing it to the browser, but making the request itself..

comment:5 in reply to: ↑ 4 knutsp4 years ago

Replying to dd32:

Have you configured something else related to redirects, or Rewrites, or something? I have a feeling something in your server stack is intercepting the redirection and not passing it to the browser, but making the request itself..

There is no redirects and no URL rewrite module on this server. The virtual dir is showing as pointing directly to the physical directory.

The IIS on this server has no knowledge of wp-admin\install.php. Only WP has. If I remove install.php there is a 404.

I will try to investigate further and get back.

comment:6 knutsp4 years ago

  • Keywords reporter-feedback removed

Now I think I can explain this issue a bit deeper. On my system the server software is Microsoft-IIS/6.0.

In pluggable.php I find this:

function wp_redirect($location, $status = 302) {
	global $is_IIS;
	$is_IIS = TRUE;
	$location = apply_filters('wp_redirect', $location, $status);
	$status = apply_filters('wp_redirect_status', $status, $location);

	if ( !$location ) // allows the wp_redirect filter to cancel a redirect
		return false;

	$location = wp_sanitize_redirect($location);

	if ( $is_IIS ) {
		header("Refresh: 0;url=$location");
	} else {
		if ( php_sapi_name() != 'cgi-fcgi' )
			status_header($status); // This causes problems on IIS and some FastCGI setups
		header("Location: $location", true, $status);
	}
}

The first thing is that his means that in case the server is IIS the redirect method should be the "Refresh" header. Othwerwise the redirect method should be the "Location" header. This is strange, because the Location header also works on IIS.

The second thing is that the $is_IIS variable is not initialized inside wp-includes/load.php, as this is required from wp-settings.php before the vars.php is requierd. In case the blog is not installed yet, but a wp-config.php is present, the redirection to wp-admin/install.php is done from wp-includes/load.php. This means that the redirect method used for any server is the Location header.

The third thing is that, on my system, when a redirect is done with a relative URL, the redirect is done "internally". This means that the browser will not know that actual resource served to it. But, strangely, the IIS log file shows the actual wp-admin/install.php as being requested. This is very, very strange to me, and I have no explaination. I have no other IIS6 systems to etst this on.

The fourth thing, and this is the main reason (and bug?), is that WP_SITEURL is not defined in wp-includes/load.php, as long as it's not defined in wp-config.php. This means that the redirection location will miss the site part and be relative. Combined with the undefined $is_IIS the redirect will fail. From load.php:

function wp_not_installed() {
	if ( is_multisite() ) {
		if ( ! is_blog_installed() && ! defined( 'WP_INSTALLING' ) )
			wp_die( __( 'The site you have requested is not installed properly. Please contact the system administrator.' ) );
	} elseif ( ! is_blog_installed() && false === strpos( $_SERVER['PHP_SELF'], 'install.php' ) && !defined( 'WP_INSTALLING' ) ) {
		if ( defined( 'WP_SITEURL' ) )
			$link = WP_SITEURL . '/wp-admin/install.php';
		elseif ( false !== strpos( $_SERVER['PHP_SELF'], 'wp-admin' ) )
			$link = preg_replace( '|/wp-admin/?.*?$|', '/', $_SERVER['PHP_SELF'] ) . 'wp-admin/install.php';
		else
			$link = preg_replace( '|/[^/]+?$|', '/', $_SERVER['PHP_SELF'] ) . 'wp-admin/install.php';
		require( ABSPATH . WPINC . '/kses.php' );
		require( ABSPATH . WPINC . '/pluggable.php' );
		require( ABSPATH . WPINC . '/formatting.php' );
		wp_redirect( $link );
		die();
	}
}

I suggest:

  1. Remove the "Refresh" redirection method from wp_redirect, as I cannot see the need for this, and it's not a standard header. I qoute from http://php.net/manual/en/function.header.php: «frank farmer 04-Aug-2010 02:10 in response to marcel dot glacki at stud dot fh-swf dot de

The "refresh" header in your example is not part of the HTTP standard, it was a proprietary extension invented by Netscape. It's use is discouraged by the W3C.»

Then we can remove the $is_IIS test from wp-redirect and it doesn't need to be defined there.

  1. Rearrange the loading or constant definition sequence, or move the wp_not_installed function declaration, so that WP_SITEURL is defined at the time of declaration of wp_not_installed(). This will ensure that a redirection location never is a relative URL. A "Location" header should always have an "absoluteURI".

I have also investigated this on IIS7 (Windows Server 2008) and there is no problem with relative URLs in a Location header. This is why this problem seems only to affect IIS6.

comment:7 dd324 years ago

The first thing is that his means that in case the server is IIS the redirect method should be the "Refresh" header. Othwerwise the redirect method should be the "Location" header. This is strange, because the Location header also works on IIS.

Thats an IIS5 thing, IIRC, It doesn't support the Location header, or does, but due to other bugs, you're required to use the Refresh header. There's another ticket discussing this, and ultimately, I feel IIS5 support should be dropped entirely.

The third thing is that, on my system, when a redirect is done with a relative URL, the redirect is done "internally". This means that the browser will not know that actual resource served to it. But, strangely, the IIS log file shows the actual wp-admin/install.php as being requested. This is very, very strange to me, and I have no explaination. I have no other IIS6 systems to etst this on.

Sounds strange, but that confirms what I was thinking, The redirect wasn't happening to the browser, so the form wasn't getting a correct URL.

WP_SITEURL is never defined by WordPress, This is a constant which can be defined in wp-config.php to override WordPress's database option site_url.

I think there are 2 things that need to be done here, And both are covered by other tickets:

  • Force all redirects to be absolute (whether that be by removing the relative calls and fixing them, or handling it internally in wp_redirect) - #14062
  • Remove the Refresh header entirely, and leave it for a Plugin to support if required? - #10187

I think we can close this ticket as a duplicate of those if fixing those will resolve the problems here.

comment:8 knutsp4 years ago

  • Resolution set to duplicate
  • Status changed from new to closed

I just found out that WP_SITEURL will never be defined by WordPress. An absolute URL for the redirect to install.php may be constructed from $_SERVER.

I suggest this change for pluggable.php:

function wp_redirect($location, $status = 302) {

	$location = apply_filters('wp_redirect', $location, $status);
	$status = apply_filters('wp_redirect_status', $status, $location);

	if ( !$location ) // allows the wp_redirect filter to cancel a redirect
		return false;

	$location = wp_sanitize_redirect($location);

	if ( php_sapi_name() != 'cgi-fcgi' )
		status_header($status); // This causes problems on IIS and some FastCGI setups
	header("Location: $location", true, $status);
}
endif;

and this change for load.php:

function wp_not_installed() {
	if ( is_multisite() ) {
		if ( ! is_blog_installed() && ! defined( 'WP_INSTALLING' ) )
			wp_die( __( 'The site you have requested is not installed properly. Please contact the system administrator.' ) );
	} elseif ( ! is_blog_installed() && false === strpos( $_SERVER['PHP_SELF'], 'install.php' ) && !defined( 'WP_INSTALLING' ) ) {
		if ( defined( 'WP_SITEURL' ) )
			$link = WP_SITEURL . '/wp-admin/install.php';
		elseif ( false !== strpos( $_SERVER['PHP_SELF'], 'wp-admin' ) )
			$link = is_ssl() ? 'https://' : 'http://'.$_SERVER['HTTP_HOST'] . preg_replace( '|/wp-admin/?.*?$|', '/', $_SERVER['PHP_SELF'] ) . 'wp-admin/install.php';
		else
			$link = is_ssl() ? 'https://' : 'http://'.$_SERVER['HTTP_HOST'] . preg_replace( '|/[^/]+?$|', '/', $_SERVER['PHP_SELF'] ) . 'wp-admin/install.php';
		require( ABSPATH . WPINC . '/kses.php' );
		require( ABSPATH . WPINC . '/pluggable.php' );
		require( ABSPATH . WPINC . '/formatting.php' );
		wp_redirect( $link );
		die();
	}
}

After writing the above I see your last comment, and agree that this issue is really a duplicate.

comment:9 dd324 years ago

(In [15680]) utilise wp_guess_url() in installation redirection to provide an Absolute URL. See #14062. See #14904

comment:10 nacin4 years ago

  • Milestone Awaiting Review deleted
Note: See TracTickets for help on using tickets.