setup-config.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  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. * @package WordPress
  9. * @subpackage Administration
  10. */
  11. /**
  12. * We are installing.
  13. */
  14. define('WP_INSTALLING', true);
  15. /**
  16. * We are blissfully unaware of anything.
  17. */
  18. define('WP_SETUP_CONFIG', true);
  19. /**
  20. * Disable error reporting
  21. *
  22. * Set this to error_reporting( -1 ) for debugging
  23. */
  24. error_reporting(0);
  25. if ( ! defined( 'ABSPATH' ) ) {
  26. define( 'ABSPATH', dirname( dirname( __FILE__ ) ) . '/' );
  27. }
  28. require( ABSPATH . 'wp-settings.php' );
  29. /** Load WordPress Administration Upgrade API */
  30. require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
  31. /** Load WordPress Translation Installation API */
  32. require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
  33. nocache_headers();
  34. // Support wp-config-sample.php one level up, for the develop repo.
  35. if ( file_exists( ABSPATH . 'wp-config-sample.php' ) ) {
  36. $config_file = file( ABSPATH . 'wp-config-sample.php' );
  37. } elseif ( file_exists( dirname( ABSPATH ) . '/wp-config-sample.php' ) ) {
  38. $config_file = file( dirname( ABSPATH ) . '/wp-config-sample.php' );
  39. } else {
  40. wp_die( sprintf(
  41. /* translators: %s: wp-config-sample.php */
  42. __( 'Sorry, I need a %s file to work from. Please re-upload this file to your WordPress installation.' ),
  43. '<code>wp-config-sample.php</code>'
  44. ) );
  45. }
  46. // Check if wp-config.php has been created
  47. if ( file_exists( ABSPATH . 'wp-config.php' ) ) {
  48. wp_die( '<p>' . sprintf(
  49. /* translators: 1: wp-config.php 2: install.php */
  50. __( 'The file %1$s already exists. If you need to reset any of the configuration items in this file, please delete it first. You may try <a href="%2$s">installing now</a>.' ),
  51. '<code>wp-config.php</code>',
  52. 'install.php'
  53. ) . '</p>'
  54. );
  55. }
  56. // Check if wp-config.php exists above the root directory but is not part of another installation
  57. if ( @file_exists( ABSPATH . '../wp-config.php' ) && ! @file_exists( ABSPATH . '../wp-settings.php' ) ) {
  58. wp_die( '<p>' . sprintf(
  59. /* translators: 1: wp-config.php 2: install.php */
  60. __( 'The file %1$s 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="%2$s">installing now</a>.' ),
  61. '<code>wp-config.php</code>',
  62. 'install.php'
  63. ) . '</p>'
  64. );
  65. }
  66. $step = isset( $_GET['step'] ) ? (int) $_GET['step'] : -1;
  67. /**
  68. * Display setup wp-config.php file header.
  69. *
  70. * @ignore
  71. * @since 2.3.0
  72. *
  73. * @global string $wp_local_package
  74. * @global WP_Locale $wp_locale
  75. *
  76. * @param string|array $body_classes
  77. */
  78. function setup_config_display_header( $body_classes = array() ) {
  79. $body_classes = (array) $body_classes;
  80. $body_classes[] = 'wp-core-ui';
  81. if ( is_rtl() ) {
  82. $body_classes[] = 'rtl';
  83. }
  84. header( 'Content-Type: text/html; charset=utf-8' );
  85. ?>
  86. <!DOCTYPE html>
  87. <html xmlns="http://www.w3.org/1999/xhtml"<?php if ( is_rtl() ) echo ' dir="rtl"'; ?>>
  88. <head>
  89. <meta name="viewport" content="width=device-width" />
  90. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  91. <meta name="robots" content="noindex,nofollow" />
  92. <title><?php _e( 'WordPress &rsaquo; Setup Configuration File' ); ?></title>
  93. <?php wp_admin_css( 'install', true ); ?>
  94. </head>
  95. <body class="<?php echo implode( ' ', $body_classes ); ?>">
  96. <p id="logo"><a href="<?php echo esc_url( __( 'https://wordpress.org/' ) ); ?>" tabindex="-1"><?php _e( 'WordPress' ); ?></a></p>
  97. <?php
  98. } // end function setup_config_display_header();
  99. $language = '';
  100. if ( ! empty( $_REQUEST['language'] ) ) {
  101. $language = preg_replace( '/[^a-zA-Z0-9_]/', '', $_REQUEST['language'] );
  102. } elseif ( isset( $GLOBALS['wp_local_package'] ) ) {
  103. $language = $GLOBALS['wp_local_package'];
  104. }
  105. switch($step) {
  106. case -1:
  107. if ( wp_can_install_language_pack() && empty( $language ) && ( $languages = wp_get_available_translations() ) ) {
  108. setup_config_display_header( 'language-chooser' );
  109. echo '<h1 class="screen-reader-text">Select a default language</h1>';
  110. echo '<form id="setup" method="post" action="?step=0">';
  111. wp_install_language_form( $languages );
  112. echo '</form>';
  113. break;
  114. }
  115. // Deliberately fall through if we can't reach the translations API.
  116. case 0:
  117. if ( ! empty( $language ) ) {
  118. $loaded_language = wp_download_language_pack( $language );
  119. if ( $loaded_language ) {
  120. load_default_textdomain( $loaded_language );
  121. $GLOBALS['wp_locale'] = new WP_Locale();
  122. }
  123. }
  124. setup_config_display_header();
  125. $step_1 = 'setup-config.php?step=1';
  126. if ( isset( $_REQUEST['noapi'] ) ) {
  127. $step_1 .= '&amp;noapi';
  128. }
  129. if ( ! empty( $loaded_language ) ) {
  130. $step_1 .= '&amp;language=' . $loaded_language;
  131. }
  132. ?>
  133. <h1 class="screen-reader-text"><?php _e( 'Before getting started' ) ?></h1>
  134. <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>
  135. <ol>
  136. <li><?php _e( 'Database name' ); ?></li>
  137. <li><?php _e( 'Database username' ); ?></li>
  138. <li><?php _e( 'Database password' ); ?></li>
  139. <li><?php _e( 'Database host' ); ?></li>
  140. <li><?php _e( 'Table prefix (if you want to run more than one WordPress in a single database)' ); ?></li>
  141. </ol>
  142. <p><?php
  143. /* translators: %s: wp-config.php */
  144. printf( __( 'We&#8217;re going to use this information to create a %s file.' ),
  145. '<code>wp-config.php</code>'
  146. );
  147. ?>
  148. <strong><?php
  149. /* translators: 1: wp-config-sample.php, 2: wp-config.php */
  150. 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.' ),
  151. '<code>wp-config-sample.php</code>',
  152. '<code>wp-config.php</code>'
  153. );
  154. ?></strong>
  155. <?php
  156. /* translators: %s: Codex URL */
  157. printf( __( 'Need more help? <a href="%s">We got it</a>.' ),
  158. __( 'https://codex.wordpress.org/Editing_wp-config.php' )
  159. );
  160. ?></p>
  161. <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>
  162. <p class="step"><a href="<?php echo $step_1; ?>" class="button button-large"><?php _e( 'Let&#8217;s go!' ); ?></a></p>
  163. <?php
  164. break;
  165. case 1:
  166. load_default_textdomain( $language );
  167. $GLOBALS['wp_locale'] = new WP_Locale();
  168. setup_config_display_header();
  169. ?>
  170. <h1 class="screen-reader-text"><?php _e( 'Set up your database connection' ) ?></h1>
  171. <form method="post" action="setup-config.php?step=2">
  172. <p><?php _e( 'Below you should enter your database connection details. If you&#8217;re not sure about these, contact your host.' ); ?></p>
  173. <table class="form-table">
  174. <tr>
  175. <th scope="row"><label for="dbname"><?php _e( 'Database Name' ); ?></label></th>
  176. <td><input name="dbname" id="dbname" type="text" size="25" value="wordpress" /></td>
  177. <td><?php _e( 'The name of the database you want to use with WordPress.' ); ?></td>
  178. </tr>
  179. <tr>
  180. <th scope="row"><label for="uname"><?php _e( 'Username' ); ?></label></th>
  181. <td><input name="uname" id="uname" type="text" size="25" value="<?php echo htmlspecialchars( _x( 'username', 'example username' ), ENT_QUOTES ); ?>" /></td>
  182. <td><?php _e( 'Your database username.' ); ?></td>
  183. </tr>
  184. <tr>
  185. <th scope="row"><label for="pwd"><?php _e( 'Password' ); ?></label></th>
  186. <td><input name="pwd" id="pwd" type="text" size="25" value="<?php echo htmlspecialchars( _x( 'password', 'example password' ), ENT_QUOTES ); ?>" autocomplete="off" /></td>
  187. <td><?php _e( 'Your database password.' ); ?></td>
  188. </tr>
  189. <tr>
  190. <th scope="row"><label for="dbhost"><?php _e( 'Database Host' ); ?></label></th>
  191. <td><input name="dbhost" id="dbhost" type="text" size="25" value="localhost" /></td>
  192. <td><?php
  193. /* translators: %s: localhost */
  194. printf( __( 'You should be able to get this info from your web host, if %s doesn&#8217;t work.' ),'<code>localhost</code>' );
  195. ?></td>
  196. </tr>
  197. <tr>
  198. <th scope="row"><label for="prefix"><?php _e( 'Table Prefix' ); ?></label></th>
  199. <td><input name="prefix" id="prefix" type="text" value="wp_" size="25" /></td>
  200. <td><?php _e( 'If you want to run multiple WordPress installations in a single database, change this.' ); ?></td>
  201. </tr>
  202. </table>
  203. <?php if ( isset( $_GET['noapi'] ) ) { ?><input name="noapi" type="hidden" value="1" /><?php } ?>
  204. <input type="hidden" name="language" value="<?php echo esc_attr( $language ); ?>" />
  205. <p class="step"><input name="submit" type="submit" value="<?php echo htmlspecialchars( __( 'Submit' ), ENT_QUOTES ); ?>" class="button button-large" /></p>
  206. </form>
  207. <?php
  208. break;
  209. case 2:
  210. load_default_textdomain( $language );
  211. $GLOBALS['wp_locale'] = new WP_Locale();
  212. $dbname = trim( wp_unslash( $_POST[ 'dbname' ] ) );
  213. $uname = trim( wp_unslash( $_POST[ 'uname' ] ) );
  214. $pwd = trim( wp_unslash( $_POST[ 'pwd' ] ) );
  215. $dbhost = trim( wp_unslash( $_POST[ 'dbhost' ] ) );
  216. $prefix = trim( wp_unslash( $_POST[ 'prefix' ] ) );
  217. $step_1 = 'setup-config.php?step=1';
  218. $install = 'install.php';
  219. if ( isset( $_REQUEST['noapi'] ) ) {
  220. $step_1 .= '&amp;noapi';
  221. }
  222. if ( ! empty( $language ) ) {
  223. $step_1 .= '&amp;language=' . $language;
  224. $install .= '?language=' . $language;
  225. } else {
  226. $install .= '?language=en_US';
  227. }
  228. $tryagain_link = '</p><p class="step"><a href="' . $step_1 . '" onclick="javascript:history.go(-1);return false;" class="button button-large">' . __( 'Try again' ) . '</a>';
  229. if ( empty( $prefix ) )
  230. wp_die( __( '<strong>ERROR</strong>: "Table Prefix" must not be empty.' . $tryagain_link ) );
  231. // Validate $prefix: it can only contain letters, numbers and underscores.
  232. if ( preg_match( '|[^a-z0-9_]|i', $prefix ) )
  233. wp_die( __( '<strong>ERROR</strong>: "Table Prefix" can only contain numbers, letters, and underscores.' . $tryagain_link ) );
  234. // Test the db connection.
  235. /**#@+
  236. * @ignore
  237. */
  238. define('DB_NAME', $dbname);
  239. define('DB_USER', $uname);
  240. define('DB_PASSWORD', $pwd);
  241. define('DB_HOST', $dbhost);
  242. /**#@-*/
  243. // Re-construct $wpdb with these new values.
  244. unset( $wpdb );
  245. require_wp_db();
  246. /*
  247. * The wpdb constructor bails when WP_SETUP_CONFIG is set, so we must
  248. * fire this manually. We'll fail here if the values are no good.
  249. */
  250. $wpdb->db_connect();
  251. if ( ! empty( $wpdb->error ) )
  252. wp_die( $wpdb->error->get_error_message() . $tryagain_link );
  253. $errors = $wpdb->hide_errors();
  254. $wpdb->query( "SELECT $prefix" );
  255. $wpdb->show_errors( $errors );
  256. if ( ! $wpdb->last_error ) {
  257. // MySQL was able to parse the prefix as a value, which we don't want. Bail.
  258. wp_die( __( '<strong>ERROR</strong>: "Table Prefix" is invalid.' ) );
  259. }
  260. // Generate keys and salts using secure CSPRNG; fallback to API if enabled; further fallback to original wp_generate_password().
  261. try {
  262. $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_ []{}<>~`+=,.;:/?|';
  263. $max = strlen($chars) - 1;
  264. for ( $i = 0; $i < 8; $i++ ) {
  265. $key = '';
  266. for ( $j = 0; $j < 64; $j++ ) {
  267. $key .= substr( $chars, random_int( 0, $max ), 1 );
  268. }
  269. $secret_keys[] = $key;
  270. }
  271. } catch ( Exception $ex ) {
  272. $no_api = isset( $_POST['noapi'] );
  273. if ( ! $no_api ) {
  274. $secret_keys = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' );
  275. }
  276. if ( $no_api || is_wp_error( $secret_keys ) ) {
  277. $secret_keys = array();
  278. for ( $i = 0; $i < 8; $i++ ) {
  279. $secret_keys[] = wp_generate_password( 64, true, true );
  280. }
  281. } else {
  282. $secret_keys = explode( "\n", wp_remote_retrieve_body( $secret_keys ) );
  283. foreach ( $secret_keys as $k => $v ) {
  284. $secret_keys[$k] = substr( $v, 28, 64 );
  285. }
  286. }
  287. }
  288. $key = 0;
  289. foreach ( $config_file as $line_num => $line ) {
  290. if ( '$table_prefix =' == substr( $line, 0, 16 ) ) {
  291. $config_file[ $line_num ] = '$table_prefix = \'' . addcslashes( $prefix, "\\'" ) . "';\r\n";
  292. continue;
  293. }
  294. if ( ! preg_match( '/^define\(\'([A-Z_]+)\',([ ]+)/', $line, $match ) )
  295. continue;
  296. $constant = $match[1];
  297. $padding = $match[2];
  298. switch ( $constant ) {
  299. case 'DB_NAME' :
  300. case 'DB_USER' :
  301. case 'DB_PASSWORD' :
  302. case 'DB_HOST' :
  303. $config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . addcslashes( constant( $constant ), "\\'" ) . "');\r\n";
  304. break;
  305. case 'DB_CHARSET' :
  306. if ( 'utf8mb4' === $wpdb->charset || ( ! $wpdb->charset && $wpdb->has_cap( 'utf8mb4' ) ) ) {
  307. $config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'utf8mb4');\r\n";
  308. }
  309. break;
  310. case 'AUTH_KEY' :
  311. case 'SECURE_AUTH_KEY' :
  312. case 'LOGGED_IN_KEY' :
  313. case 'NONCE_KEY' :
  314. case 'AUTH_SALT' :
  315. case 'SECURE_AUTH_SALT' :
  316. case 'LOGGED_IN_SALT' :
  317. case 'NONCE_SALT' :
  318. $config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . $secret_keys[$key++] . "');\r\n";
  319. break;
  320. }
  321. }
  322. unset( $line );
  323. if ( ! is_writable(ABSPATH) ) :
  324. setup_config_display_header();
  325. ?>
  326. <p><?php
  327. /* translators: %s: wp-config.php */
  328. printf( __( 'Sorry, but I can&#8217;t write the %s file.' ), '<code>wp-config.php</code>' );
  329. ?></p>
  330. <p><?php
  331. /* translators: %s: wp-config.php */
  332. printf( __( 'You can create the %s file manually and paste the following text into it.' ), '<code>wp-config.php</code>' );
  333. ?></p>
  334. <textarea id="wp-config" cols="98" rows="15" class="code" readonly="readonly"><?php
  335. foreach ( $config_file as $line ) {
  336. echo htmlentities($line, ENT_COMPAT, 'UTF-8');
  337. }
  338. ?></textarea>
  339. <p><?php _e( 'After you&#8217;ve done that, click &#8220;Run the installation.&#8221;' ); ?></p>
  340. <p class="step"><a href="<?php echo $install; ?>" class="button button-large"><?php _e( 'Run the installation' ); ?></a></p>
  341. <script>
  342. (function(){
  343. if ( ! /iPad|iPod|iPhone/.test( navigator.userAgent ) ) {
  344. var el = document.getElementById('wp-config');
  345. el.focus();
  346. el.select();
  347. }
  348. })();
  349. </script>
  350. <?php
  351. else :
  352. /*
  353. * If this file doesn't exist, then we are using the wp-config-sample.php
  354. * file one level up, which is for the develop repo.
  355. */
  356. if ( file_exists( ABSPATH . 'wp-config-sample.php' ) )
  357. $path_to_wp_config = ABSPATH . 'wp-config.php';
  358. else
  359. $path_to_wp_config = dirname( ABSPATH ) . '/wp-config.php';
  360. $handle = fopen( $path_to_wp_config, 'w' );
  361. foreach ( $config_file as $line ) {
  362. fwrite( $handle, $line );
  363. }
  364. fclose( $handle );
  365. chmod( $path_to_wp_config, 0666 );
  366. setup_config_display_header();
  367. ?>
  368. <h1 class="screen-reader-text"><?php _e( 'Successful database connection' ) ?></h1>
  369. <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>
  370. <p class="step"><a href="<?php echo $install; ?>" class="button button-large"><?php _e( 'Run the installation' ); ?></a></p>
  371. <?php
  372. endif;
  373. break;
  374. }
  375. ?>
  376. <?php wp_print_scripts( 'language-chooser' ); ?>
  377. </body>
  378. </html>