setup-config.php ➔ setup_config_display_header()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 15
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 22
rs 9.2
1
<?php
2
/**
3
 * Retrieves and creates the wp-config.php file.
4
 *
5
 * The permissions for the base directory must allow for writing files in order
6
 * for the wp-config.php to be created using this page.
7
 *
8
 * @internal This file must be parsable by PHP4.
9
 *
10
 * @package WordPress
11
 * @subpackage Administration
12
 */
13
14
/**
15
 * We are installing.
16
 */
17
define('WP_INSTALLING', true);
18
19
/**
20
 * We are blissfully unaware of anything.
21
 */
22
define('WP_SETUP_CONFIG', true);
23
24
/**
25
 * Disable error reporting
26
 *
27
 * Set this to error_reporting( -1 ) for debugging
28
 */
29
error_reporting(0);
30
31
if ( ! defined( 'ABSPATH' ) ) {
32
	define( 'ABSPATH', dirname( dirname( __FILE__ ) ) . '/' );
33
}
34
35
require( ABSPATH . 'wp-settings.php' );
36
37
/** Load WordPress Administration Upgrade API */
38
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
39
40
/** Load WordPress Translation Install API */
41
require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
42
43
nocache_headers();
44
45
// Support wp-config-sample.php one level up, for the develop repo.
46
if ( file_exists( ABSPATH . 'wp-config-sample.php' ) )
47
	$config_file = file( ABSPATH . 'wp-config-sample.php' );
48
elseif ( file_exists( dirname( ABSPATH ) . '/wp-config-sample.php' ) )
49
	$config_file = file( dirname( ABSPATH ) . '/wp-config-sample.php' );
50
else
51
	wp_die( __( 'Sorry, I need a wp-config-sample.php file to work from. Please re-upload this file to your WordPress installation.' ) );
52
53
// Check if wp-config.php has been created
54
if ( file_exists( ABSPATH . 'wp-config.php' ) )
55
	wp_die( '<p>' . sprintf(
56
			/* translators: %s: install.php */
57
			__( "The file 'wp-config.php' already exists. If you need to reset any of the configuration items in this file, please delete it first. You may try <a href='%s'>installing now</a>." ),
58
			'install.php'
59
		) . '</p>'
60
	);
61
62
// Check if wp-config.php exists above the root directory but is not part of another install
63
if ( @file_exists( ABSPATH . '../wp-config.php' ) && ! @file_exists( ABSPATH . '../wp-settings.php' ) ) {
64
	wp_die( '<p>' . sprintf(
65
			/* translators: %s: install.php */
66
			__( "The file 'wp-config.php' already exists one level above your WordPress installation. If you need to reset any of the configuration items in this file, please delete it first. You may try <a href='%s'>installing now</a>." ),
67
			'install.php'
68
		) . '</p>'
69
	);
70
}
71
72
$step = isset( $_GET['step'] ) ? (int) $_GET['step'] : -1;
73
74
/**
75
 * Display setup wp-config.php file header.
76
 *
77
 * @ignore
78
 * @since 2.3.0
79
 *
80
 * @global string    $wp_local_package
81
 * @global WP_Locale $wp_locale
82
 *
83
 * @param string|array $body_classes
84
 */
85
function setup_config_display_header( $body_classes = array() ) {
86
	$body_classes = (array) $body_classes;
87
	$body_classes[] = 'wp-core-ui';
88
	if ( is_rtl() ) {
89
		$body_classes[] = 'rtl';
90
	}
91
92
	header( 'Content-Type: text/html; charset=utf-8' );
93
?>
94
<!DOCTYPE html>
95
<html xmlns="http://www.w3.org/1999/xhtml"<?php if ( is_rtl() ) echo ' dir="rtl"'; ?>>
96
<head>
97
	<meta name="viewport" content="width=device-width" />
98
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
99
	<meta name="robots" content="noindex,nofollow" />
100
	<title><?php _e( 'WordPress &rsaquo; Setup Configuration File' ); ?></title>
101
	<?php wp_admin_css( 'install', true ); ?>
102
</head>
103
<body class="<?php echo implode( ' ', $body_classes ); ?>">
104
<p id="logo"><a href="<?php esc_attr_e( 'https://wordpress.org/' ); ?>" tabindex="-1"><?php _e( 'WordPress' ); ?></a></p>
105
<?php
106
} // end function setup_config_display_header();
107
108
$language = '';
109 View Code Duplication
if ( ! empty( $_REQUEST['language'] ) ) {
110
	$language = preg_replace( '/[^a-zA-Z_]/', '', $_REQUEST['language'] );
111
} elseif ( isset( $GLOBALS['wp_local_package'] ) ) {
112
	$language = $GLOBALS['wp_local_package'];
113
}
114
115
switch($step) {
116 View Code Duplication
	case -1:
117
		if ( wp_can_install_language_pack() && empty( $language ) && ( $languages = wp_get_available_translations() ) ) {
118
			setup_config_display_header( 'language-chooser' );
119
			echo '<h1 class="screen-reader-text">Select a default language</h1>';
120
			echo '<form id="setup" method="post" action="?step=0">';
121
			wp_install_language_form( $languages );
122
			echo '</form>';
123
			break;
124
		}
125
126
		// Deliberately fall through if we can't reach the translations API.
127
128
	case 0:
129 View Code Duplication
		if ( ! empty( $language ) ) {
130
			$loaded_language = wp_download_language_pack( $language );
131
			if ( $loaded_language ) {
132
				load_default_textdomain( $loaded_language );
0 ignored issues
show
Bug introduced by
It seems like $loaded_language defined by wp_download_language_pack($language) on line 130 can also be of type boolean; however, load_default_textdomain() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
133
				$GLOBALS['wp_locale'] = new WP_Locale();
134
			}
135
		}
136
137
		setup_config_display_header();
138
		$step_1 = 'setup-config.php?step=1';
139
		if ( isset( $_REQUEST['noapi'] ) ) {
140
			$step_1 .= '&amp;noapi';
141
		}
142
		if ( ! empty( $loaded_language ) ) {
143
			$step_1 .= '&amp;language=' . $loaded_language;
144
		}
145
?>
146
<h1 class="screen-reader-text"><?php _e( 'Before getting started' ) ?></h1>
147
<p><?php _e( 'Welcome to WordPress. Before getting started, we need some information on the database. You will need to know the following items before proceeding.' ) ?></p>
148
<ol>
149
	<li><?php _e( 'Database name' ); ?></li>
150
	<li><?php _e( 'Database username' ); ?></li>
151
	<li><?php _e( 'Database password' ); ?></li>
152
	<li><?php _e( 'Database host' ); ?></li>
153
	<li><?php _e( 'Table prefix (if you want to run more than one WordPress in a single database)' ); ?></li>
154
</ol>
155
<p><?php
156
	/* translators: %s: wp-config.php */
157
	printf( __( 'We&#8217;re going to use this information to create a %s file.' ),
158
		'<code>wp-config.php</code>'
159
	);
160
	?>
161
	<strong><?php
162
		/* translators: 1: wp-config-sample.php, 2: wp-config.php */
163
		printf( __( 'If for any reason this automatic file creation doesn&#8217;t work, don&#8217;t worry. All this does is fill in the database information to a configuration file. You may also simply open %1$s in a text editor, fill in your information, and save it as %2$s.' ),
164
			'<code>wp-config-sample.php</code>',
165
			'<code>wp-config.php</code>'
166
		);
167
	?></strong>
168
	<?php
169
	/* translators: %s: Codex URL */
170
	printf( __( 'Need more help? <a href="%s">We got it</a>.' ),
171
		__( 'https://codex.wordpress.org/Editing_wp-config.php' )
172
	);
173
?></p>
174
<p><?php _e( 'In all likelihood, these items were supplied to you by your Web Host. If you don&#8217;t have this information, then you will need to contact them before you can continue. If you&#8217;re all ready&hellip;' ); ?></p>
175
176
<p class="step"><a href="<?php echo $step_1; ?>" class="button button-large"><?php _e( 'Let&#8217;s go!' ); ?></a></p>
177
<?php
178
	break;
179
180
	case 1:
181
		load_default_textdomain( $language );
182
		$GLOBALS['wp_locale'] = new WP_Locale();
183
184
		setup_config_display_header();
185
	?>
186
<h1 class="screen-reader-text"><?php _e( 'Set up your database connection' ) ?></h1>
187
<form method="post" action="setup-config.php?step=2">
188
	<p><?php _e( 'Below you should enter your database connection details. If you&#8217;re not sure about these, contact your host.' ); ?></p>
189
	<table class="form-table">
190
		<tr>
191
			<th scope="row"><label for="dbname"><?php _e( 'Database Name' ); ?></label></th>
192
			<td><input name="dbname" id="dbname" type="text" size="25" value="wordpress" /></td>
193
			<td><?php _e( 'The name of the database you want to use with WordPress.' ); ?></td>
194
		</tr>
195
		<tr>
196
			<th scope="row"><label for="uname"><?php _e( 'Username' ); ?></label></th>
197
			<td><input name="uname" id="uname" type="text" size="25" value="<?php echo htmlspecialchars( _x( 'username', 'example username' ), ENT_QUOTES ); ?>" /></td>
198
			<td><?php _e( 'Your database username.' ); ?></td>
199
		</tr>
200
		<tr>
201
			<th scope="row"><label for="pwd"><?php _e( 'Password' ); ?></label></th>
202
			<td><input name="pwd" id="pwd" type="text" size="25" value="<?php echo htmlspecialchars( _x( 'password', 'example password' ), ENT_QUOTES ); ?>" autocomplete="off" /></td>
203
			<td><?php _e( 'Your database password.' ); ?></td>
204
		</tr>
205
		<tr>
206
			<th scope="row"><label for="dbhost"><?php _e( 'Database Host' ); ?></label></th>
207
			<td><input name="dbhost" id="dbhost" type="text" size="25" value="localhost" /></td>
208
			<td><?php
209
				/* translators: %s: localhost */
210
				printf( __( 'You should be able to get this info from your web host, if %s doesn&#8217;t work.' ),'<code>localhost</code>' );
211
			?></td>
212
		</tr>
213
		<tr>
214
			<th scope="row"><label for="prefix"><?php _e( 'Table Prefix' ); ?></label></th>
215
			<td><input name="prefix" id="prefix" type="text" value="wp_" size="25" /></td>
216
			<td><?php _e( 'If you want to run multiple WordPress installations in a single database, change this.' ); ?></td>
217
		</tr>
218
	</table>
219
	<?php if ( isset( $_GET['noapi'] ) ) { ?><input name="noapi" type="hidden" value="1" /><?php } ?>
220
	<input type="hidden" name="language" value="<?php echo esc_attr( $language ); ?>" />
221
	<p class="step"><input name="submit" type="submit" value="<?php echo htmlspecialchars( __( 'Submit' ), ENT_QUOTES ); ?>" class="button button-large" /></p>
222
</form>
223
<?php
224
	break;
225
226
	case 2:
227
	load_default_textdomain( $language );
228
	$GLOBALS['wp_locale'] = new WP_Locale();
229
230
	$dbname = trim( wp_unslash( $_POST[ 'dbname' ] ) );
231
	$uname = trim( wp_unslash( $_POST[ 'uname' ] ) );
232
	$pwd = trim( wp_unslash( $_POST[ 'pwd' ] ) );
233
	$dbhost = trim( wp_unslash( $_POST[ 'dbhost' ] ) );
234
	$prefix = trim( wp_unslash( $_POST[ 'prefix' ] ) );
235
236
	$step_1 = 'setup-config.php?step=1';
237
	$install = 'install.php';
238
	if ( isset( $_REQUEST['noapi'] ) ) {
239
		$step_1 .= '&amp;noapi';
240
	}
241
242
	if ( ! empty( $language ) ) {
243
		$step_1 .= '&amp;language=' . $language;
244
		$install .= '?language=' . $language;
245
	} else {
246
		$install .= '?language=en_US';
247
	}
248
249
	$tryagain_link = '</p><p class="step"><a href="' . $step_1 . '" onclick="javascript:history.go(-1);return false;" class="button button-large">' . __( 'Try again' ) . '</a>';
250
251
	if ( empty( $prefix ) )
252
		wp_die( __( '<strong>ERROR</strong>: "Table Prefix" must not be empty.' . $tryagain_link ) );
253
254
	// Validate $prefix: it can only contain letters, numbers and underscores.
255
	if ( preg_match( '|[^a-z0-9_]|i', $prefix ) )
256
		wp_die( __( '<strong>ERROR</strong>: "Table Prefix" can only contain numbers, letters, and underscores.' . $tryagain_link ) );
257
258
	// Test the db connection.
259
	/**#@+
260
	 * @ignore
261
	 */
262
	define('DB_NAME', $dbname);
263
	define('DB_USER', $uname);
264
	define('DB_PASSWORD', $pwd);
265
	define('DB_HOST', $dbhost);
266
	/**#@-*/
267
268
	// Re-construct $wpdb with these new values.
269
	unset( $wpdb );
270
	require_wp_db();
271
272
	/*
273
	 * The wpdb constructor bails when WP_SETUP_CONFIG is set, so we must
274
	 * fire this manually. We'll fail here if the values are no good.
275
	 */
276
	$wpdb->db_connect();
277
278
	if ( ! empty( $wpdb->error ) )
279
		wp_die( $wpdb->error->get_error_message() . $tryagain_link );
280
281
	$wpdb->query( "SELECT $prefix" );
282
	if ( ! $wpdb->last_error ) {
283
		// MySQL was able to parse the prefix as a value, which we don't want. Bail.
284
		wp_die( __( '<strong>ERROR</strong>: "Table Prefix" is invalid.' ) );
285
	}
286
287
	// Generate keys and salts using secure CSPRNG; fallback to API if enabled; further fallback to original wp_generate_password().
288
	try {
289
		$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_ []{}<>~`+=,.;:/?|';
290
		$max = strlen($chars) - 1;
291
		for ( $i = 0; $i < 8; $i++ ) {
292
			$key = '';
293
			for ( $j = 0; $j < 64; $j++ ) {
294
				$key .= substr( $chars, random_int( 0, $max ), 1 );
295
			}
296
			$secret_keys[] = $key;
297
		}
298
	} catch ( Exception $ex ) {
299
		$no_api = isset( $_POST['noapi'] );
300
301
		if ( ! $no_api ) {
302
			$secret_keys = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' );
303
		}
304
305
		if ( $no_api || is_wp_error( $secret_keys ) ) {
306
			$secret_keys = array();
307
			for ( $i = 0; $i < 8; $i++ ) {
308
				$secret_keys[] = wp_generate_password( 64, true, true );
309
			}
310
		} else {
311
			$secret_keys = explode( "\n", wp_remote_retrieve_body( $secret_keys ) );
0 ignored issues
show
Bug introduced by
It seems like $secret_keys can also be of type object<WP_Error>; however, wp_remote_retrieve_body() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
312
			foreach ( $secret_keys as $k => $v ) {
313
				$secret_keys[$k] = substr( $v, 28, 64 );
314
			}
315
		}
316
	}
317
318
	$key = 0;
319
	// Not a PHP5-style by-reference foreach, as this file must be parseable by PHP4.
320
	foreach ( $config_file as $line_num => $line ) {
321
		if ( '$table_prefix  =' == substr( $line, 0, 16 ) ) {
322
			$config_file[ $line_num ] = '$table_prefix  = \'' . addcslashes( $prefix, "\\'" ) . "';\r\n";
323
			continue;
324
		}
325
326
		if ( ! preg_match( '/^define\(\'([A-Z_]+)\',([ ]+)/', $line, $match ) )
327
			continue;
328
329
		$constant = $match[1];
330
		$padding  = $match[2];
331
332
		switch ( $constant ) {
333
			case 'DB_NAME'     :
334
			case 'DB_USER'     :
335
			case 'DB_PASSWORD' :
336
			case 'DB_HOST'     :
337
				$config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . addcslashes( constant( $constant ), "\\'" ) . "');\r\n";
338
				break;
339
			case 'DB_CHARSET'  :
340
				if ( 'utf8mb4' === $wpdb->charset || ( ! $wpdb->charset && $wpdb->has_cap( 'utf8mb4' ) ) ) {
341
					$config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'utf8mb4');\r\n";
342
				}
343
				break;
344
			case 'AUTH_KEY'         :
345
			case 'SECURE_AUTH_KEY'  :
346
			case 'LOGGED_IN_KEY'    :
347
			case 'NONCE_KEY'        :
348
			case 'AUTH_SALT'        :
349
			case 'SECURE_AUTH_SALT' :
350
			case 'LOGGED_IN_SALT'   :
351
			case 'NONCE_SALT'       :
352
				$config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . $secret_keys[$key++] . "');\r\n";
353
				break;
354
		}
355
	}
356
	unset( $line );
357
358
	if ( ! is_writable(ABSPATH) ) :
359
		setup_config_display_header();
360
?>
361
<p><?php
362
	/* translators: %s: wp-config.php */
363
	printf( __( 'Sorry, but I can&#8217;t write the %s file.' ), '<code>wp-config.php</code>' );
364
?></p>
365
<p><?php
366
	/* translators: %s: wp-config.php */
367
	printf( __( 'You can create the %s manually and paste the following text into it.' ), '<code>wp-config.php</code>' );
368
?></p>
369
<textarea id="wp-config" cols="98" rows="15" class="code" readonly="readonly"><?php
370
		foreach ( $config_file as $line ) {
371
			echo htmlentities($line, ENT_COMPAT, 'UTF-8');
372
		}
373
?></textarea>
374
<p><?php _e( 'After you&#8217;ve done that, click &#8220;Run the install.&#8221;' ); ?></p>
375
<p class="step"><a href="<?php echo $install; ?>" class="button button-large"><?php _e( 'Run the install' ); ?></a></p>
376
<script>
377
(function(){
378
if ( ! /iPad|iPod|iPhone/.test( navigator.userAgent ) ) {
379
	var el = document.getElementById('wp-config');
380
	el.focus();
381
	el.select();
382
}
383
})();
384
</script>
385
<?php
386
	else :
387
		/*
388
		 * If this file doesn't exist, then we are using the wp-config-sample.php
389
		 * file one level up, which is for the develop repo.
390
		 */
391
		if ( file_exists( ABSPATH . 'wp-config-sample.php' ) )
392
			$path_to_wp_config = ABSPATH . 'wp-config.php';
393
		else
394
			$path_to_wp_config = dirname( ABSPATH ) . '/wp-config.php';
395
396
		$handle = fopen( $path_to_wp_config, 'w' );
397
		foreach ( $config_file as $line ) {
398
			fwrite( $handle, $line );
399
		}
400
		fclose( $handle );
401
		chmod( $path_to_wp_config, 0666 );
402
		setup_config_display_header();
403
?>
404
<h1 class="screen-reader-text"><?php _e( 'Successful database connection' ) ?></h1>
405
<p><?php _e( 'All right, sparky! You&#8217;ve made it through this part of the installation. WordPress can now communicate with your database. If you are ready, time now to&hellip;' ); ?></p>
406
407
<p class="step"><a href="<?php echo $install; ?>" class="button button-large"><?php _e( 'Run the install' ); ?></a></p>
408
<?php
409
	endif;
410
	break;
411
}
412
?>
413
<?php wp_print_scripts( 'language-chooser' ); ?>
414
</body>
415
</html>
416