setup-config.php 15 KB

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