[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-admin/ -> setup-config.php (source)

   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  /**
  13   * We are installing.
  14   */
  15  define( 'WP_INSTALLING', true );
  16  
  17  if ( ! defined( 'ABSPATH' ) ) {
  18      define( 'ABSPATH', dirname( __DIR__ ) . '/' );
  19  }
  20  
  21  /*
  22   * Check whether a wp-config.php file already exists, either in the WordPress root
  23   * or one level above it (but not as part of another installation).
  24   * This mirrors the lookup in wp-load.php.
  25   */
  26  if ( file_exists( ABSPATH . 'wp-config.php' ) ) {
  27      $existing_config_location = 'root';
  28  } elseif ( @file_exists( dirname( ABSPATH ) . '/wp-config.php' ) && ! @file_exists( dirname( ABSPATH ) . '/wp-settings.php' ) ) {
  29      $existing_config_location = 'parent';
  30  } else {
  31      $existing_config_location = '';
  32  }
  33  
  34  if ( $existing_config_location ) {
  35      /*
  36       * A configuration file already exists, so there is nothing to set up here.
  37       * Load WordPress through that file, like any other request would, so that the
  38       * site's locale is known and the message below can be translated.
  39       */
  40      require_once  ABSPATH . 'wp-load.php';
  41  
  42      nocache_headers();
  43  
  44      if ( 'root' === $existing_config_location ) {
  45          $message = sprintf(
  46              /* translators: 1: wp-config.php, 2: install.php */
  47              __( '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>.' ),
  48              '<code>wp-config.php</code>',
  49              'install.php'
  50          );
  51      } else {
  52          $message = sprintf(
  53              /* translators: 1: wp-config.php, 2: install.php */
  54              __( '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>.' ),
  55              '<code>wp-config.php</code>',
  56              'install.php'
  57          );
  58      }
  59  
  60      wp_die( '<p>' . $message . '</p>', 409 );
  61  }
  62  
  63  /**
  64   * We are blissfully unaware of anything.
  65   */
  66  define( 'WP_SETUP_CONFIG', true );
  67  
  68  /**
  69   * Disable error reporting
  70   *
  71   * Set this to error_reporting( -1 ) for debugging
  72   */
  73  error_reporting( 0 );
  74  
  75  require  ABSPATH . 'wp-settings.php';
  76  
  77  /** Load WordPress Administration Upgrade API */
  78  require_once  ABSPATH . 'wp-admin/includes/upgrade.php';
  79  
  80  /** Load WordPress Translation Installation API */
  81  require_once  ABSPATH . 'wp-admin/includes/translation-install.php';
  82  
  83  nocache_headers();
  84  
  85  // Support wp-config-sample.php one level up, for the develop repo.
  86  if ( file_exists( ABSPATH . 'wp-config-sample.php' ) ) {
  87      $config_file = file( ABSPATH . 'wp-config-sample.php' );
  88  } elseif ( file_exists( dirname( ABSPATH ) . '/wp-config-sample.php' ) ) {
  89      $config_file = file( dirname( ABSPATH ) . '/wp-config-sample.php' );
  90  } else {
  91      wp_die(
  92          sprintf(
  93              /* translators: %s: wp-config-sample.php */
  94              __( 'Sorry, I need a %s file to work from. Please re-upload this file to your WordPress installation.' ),
  95              '<code>wp-config-sample.php</code>'
  96          )
  97      );
  98  }
  99  
 100  $step = isset( $_GET['step'] ) ? (int) $_GET['step'] : -1;
 101  
 102  /**
 103   * Display setup wp-config.php file header.
 104   *
 105   * @ignore
 106   * @since 2.3.0
 107   *
 108   * @param string|string[] $body_classes Class attribute values for the body tag.
 109   */
 110  function setup_config_display_header( $body_classes = array() ) {
 111      $body_classes   = (array) $body_classes;
 112      $body_classes[] = 'wp-core-ui';
 113      $body_classes[] = 'admin-color-modern';
 114  
 115      if ( is_rtl() ) {
 116          $body_classes[] = 'rtl';
 117      }
 118  
 119      header( 'Content-Type: text/html; charset=utf-8' );
 120      ?>
 121  <!DOCTYPE html>
 122  <html <?php language_attributes(); ?>>
 123  <head>
 124      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 125      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 126      <meta name="robots" content="noindex,nofollow" />
 127      <title><?php _e( 'WordPress &rsaquo; Setup Configuration File' ); ?></title>
 128      <?php wp_admin_css( 'install', true ); ?>
 129  </head>
 130  <body class="<?php echo implode( ' ', $body_classes ); ?>">
 131  <p id="logo"><?php _e( 'WordPress' ); ?></p>
 132      <?php
 133  } // End function setup_config_display_header();
 134  
 135  /**
 136   * @global string    $wp_local_package Locale code of the package.
 137   * @global WP_Locale $wp_locale        WordPress date and time locale object.
 138   */
 139  $language = '';
 140  if ( ! empty( $_REQUEST['language'] ) ) {
 141      $language = preg_replace( '/[^a-zA-Z0-9_]/', '', $_REQUEST['language'] );
 142  } elseif ( isset( $GLOBALS['wp_local_package'] ) ) {
 143      $language = $GLOBALS['wp_local_package'];
 144  }
 145  
 146  switch ( $step ) {
 147      case -1:
 148          if ( wp_can_install_language_pack() && empty( $language ) ) {
 149              $languages = wp_get_available_translations();
 150              if ( $languages ) {
 151                  setup_config_display_header( 'language-chooser' );
 152                  echo '<h1 class="screen-reader-text">Welcome to WordPress</h1>';
 153                  echo '<form id="setup" method="post" action="?step=0">';
 154                  wp_install_language_form( $languages );
 155                  echo '</form>';
 156                  break;
 157              }
 158          }
 159  
 160          // Deliberately fall through if we can't reach the translations API.
 161  
 162      case 0:
 163          if ( ! empty( $language ) ) {
 164              $loaded_language = wp_download_language_pack( $language );
 165              if ( $loaded_language ) {
 166                  load_default_textdomain( $loaded_language );
 167                  $GLOBALS['wp_locale'] = new WP_Locale();
 168              }
 169          }
 170  
 171          setup_config_display_header();
 172          $step_1 = 'setup-config.php?step=1';
 173          if ( isset( $_REQUEST['noapi'] ) ) {
 174              $step_1 .= '&amp;noapi';
 175          }
 176          if ( ! empty( $loaded_language ) ) {
 177              $step_1 .= '&amp;language=' . $loaded_language;
 178          }
 179          ?>
 180  <h1 class="screen-reader-text">
 181          <?php
 182          /* translators: Hidden accessibility text. */
 183          _e( 'Before getting started' );
 184          ?>
 185  </h1>
 186  <p><?php _e( 'Welcome to WordPress. Before getting started, you will need to know the following items.' ); ?></p>
 187  <ol>
 188      <li><?php _e( 'Database name' ); ?></li>
 189      <li><?php _e( 'Database username' ); ?></li>
 190      <li><?php _e( 'Database password' ); ?></li>
 191      <li><?php _e( 'Database host' ); ?></li>
 192      <li><?php _e( 'Table prefix (if you want to run more than one WordPress in a single database)' ); ?></li>
 193  </ol>
 194  <p>
 195          <?php
 196          printf(
 197              /* translators: %s: wp-config.php */
 198              __( 'This information is being used to create a %s file.' ),
 199              '<code>wp-config.php</code>'
 200          );
 201          ?>
 202      <strong>
 203          <?php
 204          printf(
 205              /* translators: 1: wp-config-sample.php, 2: wp-config.php */
 206              __( 'If for any reason this automatic file creation does not work, do not 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.' ),
 207              '<code>wp-config-sample.php</code>',
 208              '<code>wp-config.php</code>'
 209          );
 210          ?>
 211      </strong>
 212          <?php
 213          printf(
 214              /* translators: 1: Documentation URL, 2: wp-config.php */
 215              __( 'Need more help? <a href="%1$s">Read the support article on %2$s</a>.' ),
 216              __( 'https://developer.wordpress.org/advanced-administration/wordpress/wp-config/' ),
 217              '<code>wp-config.php</code>'
 218          );
 219          ?>
 220  </p>
 221  <p><?php _e( 'In all likelihood, these items were supplied to you by your web host. If you do not have this information, then you will need to contact them before you can continue. If you are ready&hellip;' ); ?></p>
 222  
 223  <p class="step"><a href="<?php echo $step_1; ?>" class="button button-large"><?php _e( 'Let&#8217;s go!' ); ?></a></p>
 224          <?php
 225          break;
 226  
 227      case 1:
 228          load_default_textdomain( $language );
 229          $GLOBALS['wp_locale'] = new WP_Locale();
 230  
 231          setup_config_display_header();
 232  
 233          $autofocus = wp_is_mobile() ? '' : ' autofocus';
 234          ?>
 235  <h1 class="screen-reader-text">
 236          <?php
 237          /* translators: Hidden accessibility text. */
 238          _e( 'Set up your database connection' );
 239          ?>
 240  </h1>
 241  <form method="post" action="setup-config.php?step=2">
 242      <p><?php _e( 'Below you should enter your database connection details. If you are not sure about these, contact your host.' ); ?></p>
 243      <table class="form-table" role="presentation">
 244          <tr>
 245              <th scope="row"><label for="dbname"><?php _e( 'Database Name' ); ?></label></th>
 246              <td><input name="dbname" id="dbname" type="text" aria-describedby="dbname-desc" size="25" placeholder="wordpress"<?php echo $autofocus; ?> />
 247              <p id="dbname-desc"><?php _e( 'The name of the database you want to use with WordPress.' ); ?></p></td>
 248          </tr>
 249          <tr>
 250              <th scope="row"><label for="uname"><?php _e( 'Username' ); ?></label></th>
 251              <td><input name="uname" id="uname" type="text" aria-describedby="uname-desc" size="25" placeholder="<?php echo htmlspecialchars( _x( 'username', 'example username' ), ENT_QUOTES ); ?>" />
 252              <p id="uname-desc"><?php _e( 'Your database username.' ); ?></p></td>
 253          </tr>
 254          <tr>
 255              <th scope="row"><label for="pwd"><?php _e( 'Password' ); ?></label></th>
 256              <td>
 257                  <div class="wp-pwd">
 258                      <input name="pwd" id="pwd" type="password" class="regular-text" data-reveal="1" aria-describedby="pwd-desc" size="25" placeholder="<?php echo htmlspecialchars( _x( 'password', 'example password' ), ENT_QUOTES ); ?>" autocomplete="off" spellcheck="false" />
 259                      <button type="button" class="button wp-hide-pw user-new-password-toggle pwd-toggle hide-if-no-js" data-toggle="0" data-start-masked="1" aria-label="<?php esc_attr_e( 'Show password' ); ?>">
 260                          <span class="dashicons dashicons-visibility"></span>
 261                          <span class="text"><?php _e( 'Show' ); ?></span>
 262                      </button>
 263                  </div>
 264                  <p id="pwd-desc"><?php _e( 'Your database password.' ); ?></p>
 265              </td>
 266          </tr>
 267          <tr>
 268              <th scope="row"><label for="dbhost"><?php _e( 'Database Host' ); ?></label></th>
 269              <td><input name="dbhost" id="dbhost" type="text" aria-describedby="dbhost-desc" size="25" value="localhost" />
 270              <p id="dbhost-desc">
 271              <?php
 272                  /* translators: %s: localhost */
 273                  printf( __( 'You should be able to get this info from your web host, if %s does not work.' ), '<code>localhost</code>' );
 274              ?>
 275              </p></td>
 276          </tr>
 277          <tr>
 278              <th scope="row"><label for="prefix"><?php _e( 'Table Prefix' ); ?></label></th>
 279              <td><input name="prefix" id="prefix" type="text" aria-describedby="prefix-desc" value="wp_" size="25" />
 280              <p id="prefix-desc"><?php _e( 'If you want to run multiple WordPress installations in a single database, change this.' ); ?></p></td>
 281          </tr>
 282      </table>
 283          <?php
 284          if ( isset( $_GET['noapi'] ) ) {
 285              ?>
 286  <input name="noapi" type="hidden" value="1" /><?php } ?>
 287      <input type="hidden" name="language" value="<?php echo esc_attr( $language ); ?>" />
 288      <p class="step"><input name="submit" type="submit" value="<?php echo htmlspecialchars( __( 'Submit' ), ENT_QUOTES ); ?>" class="button button-large" /></p>
 289  </form>
 290          <?php
 291          wp_print_scripts( 'password-toggle' );
 292          break;
 293  
 294      case 2:
 295          load_default_textdomain( $language );
 296          $GLOBALS['wp_locale'] = new WP_Locale();
 297  
 298          $dbname = trim( wp_unslash( $_POST['dbname'] ) );
 299          $uname  = trim( wp_unslash( $_POST['uname'] ) );
 300          $pwd    = trim( wp_unslash( $_POST['pwd'] ) );
 301          $dbhost = trim( wp_unslash( $_POST['dbhost'] ) );
 302          $prefix = trim( wp_unslash( $_POST['prefix'] ) );
 303  
 304          $step_1  = 'setup-config.php?step=1';
 305          $install = 'install.php';
 306          if ( isset( $_REQUEST['noapi'] ) ) {
 307              $step_1 .= '&amp;noapi';
 308          }
 309  
 310          if ( ! empty( $language ) ) {
 311              $step_1  .= '&amp;language=' . $language;
 312              $install .= '?language=' . $language;
 313          } else {
 314              $install .= '?language=en_US';
 315          }
 316  
 317          $tryagain_link = '</p><p class="step"><a href="' . $step_1 . '" onclick="javascript:history.go(-1);return false;" class="button button-large">' . __( 'Try Again' ) . '</a>';
 318  
 319          if ( empty( $prefix ) ) {
 320              wp_die( __( '<strong>Error:</strong> "Table Prefix" must not be empty.' ) . $tryagain_link );
 321          }
 322  
 323          // Validate $prefix: it can only contain letters, numbers and underscores.
 324          if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) {
 325              wp_die( __( '<strong>Error:</strong> "Table Prefix" can only contain numbers, letters, and underscores.' ) . $tryagain_link );
 326          }
 327  
 328          // Test the DB connection.
 329          /**#@+
 330           *
 331           * @ignore
 332           */
 333          define( 'DB_NAME', $dbname );
 334          define( 'DB_USER', $uname );
 335          define( 'DB_PASSWORD', $pwd );
 336          define( 'DB_HOST', $dbhost );
 337          /**#@-*/
 338  
 339          // Re-construct $wpdb with these new values.
 340          unset( $wpdb );
 341          require_wp_db();
 342  
 343          /*
 344          * The wpdb constructor bails when WP_SETUP_CONFIG is set, so we must
 345          * fire this manually. We'll fail here if the values are no good.
 346          */
 347          $wpdb->db_connect();
 348  
 349          if ( ! empty( $wpdb->error ) ) {
 350              wp_die( $wpdb->error->get_error_message() . $tryagain_link );
 351          }
 352  
 353          $errors = $wpdb->suppress_errors();
 354          $wpdb->query( "SELECT $prefix" );
 355          $wpdb->suppress_errors( $errors );
 356  
 357          if ( ! $wpdb->last_error ) {
 358              // MySQL was able to parse the prefix as a value, which we don't want. Bail.
 359              wp_die( __( '<strong>Error:</strong> "Table Prefix" is invalid.' ) );
 360          }
 361  
 362          // Generate keys and salts using secure CSPRNG; fallback to API if enabled; further fallback to original wp_generate_password().
 363          try {
 364              $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_ []{}<>~`+=,.;:/?|';
 365              $max   = strlen( $chars ) - 1;
 366              for ( $i = 0; $i < 8; $i++ ) {
 367                  $key = '';
 368                  for ( $j = 0; $j < 64; $j++ ) {
 369                      $key .= substr( $chars, random_int( 0, $max ), 1 );
 370                  }
 371                  $secret_keys[] = $key;
 372              }
 373          } catch ( Exception $ex ) {
 374              $no_api = isset( $_POST['noapi'] );
 375  
 376              if ( ! $no_api ) {
 377                  $secret_keys = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' );
 378              }
 379  
 380              if ( $no_api || is_wp_error( $secret_keys ) ) {
 381                  $secret_keys = array();
 382                  for ( $i = 0; $i < 8; $i++ ) {
 383                      $secret_keys[] = wp_generate_password( 64, true, true );
 384                  }
 385              } else {
 386                  $secret_keys = explode( "\n", wp_remote_retrieve_body( $secret_keys ) );
 387                  foreach ( $secret_keys as $k => $v ) {
 388                      $secret_keys[ $k ] = substr( $v, 28, 64 );
 389                  }
 390              }
 391          }
 392  
 393          $key = 0;
 394          foreach ( $config_file as $line_num => $line ) {
 395              if ( str_starts_with( $line, '$table_prefix =' ) ) {
 396                  $config_file[ $line_num ] = '$table_prefix = \'' . addcslashes( $prefix, "\\'" ) . "';\r\n";
 397                  continue;
 398              }
 399  
 400              if ( ! preg_match( '/^define\(\s*\'([A-Z_]+)\',([ ]+)/', $line, $match ) ) {
 401                  continue;
 402              }
 403  
 404              $constant = $match[1];
 405              $padding  = $match[2];
 406  
 407              switch ( $constant ) {
 408                  case 'DB_NAME':
 409                  case 'DB_USER':
 410                  case 'DB_PASSWORD':
 411                  case 'DB_HOST':
 412                      $config_file[ $line_num ] = "define( '" . $constant . "'," . $padding . "'" . addcslashes( constant( $constant ), "\\'" ) . "' );\r\n";
 413                      break;
 414                  case 'DB_CHARSET':
 415                      if ( 'utf8mb4' === $wpdb->charset || ( ! $wpdb->charset ) ) {
 416                          $config_file[ $line_num ] = "define( '" . $constant . "'," . $padding . "'utf8mb4' );\r\n";
 417                      }
 418                      break;
 419                  case 'AUTH_KEY':
 420                  case 'SECURE_AUTH_KEY':
 421                  case 'LOGGED_IN_KEY':
 422                  case 'NONCE_KEY':
 423                  case 'AUTH_SALT':
 424                  case 'SECURE_AUTH_SALT':
 425                  case 'LOGGED_IN_SALT':
 426                  case 'NONCE_SALT':
 427                      $config_file[ $line_num ] = "define( '" . $constant . "'," . $padding . "'" . $secret_keys[ $key++ ] . "' );\r\n";
 428                      break;
 429              }
 430          }
 431          unset( $line );
 432  
 433          if ( ! is_writable( ABSPATH ) ) :
 434              setup_config_display_header();
 435              ?>
 436  <p>
 437              <?php
 438              /* translators: %s: wp-config.php */
 439              printf( __( 'Unable to write to %s file.' ), '<code>wp-config.php</code>' );
 440              ?>
 441  </p>
 442  <p id="wp-config-description">
 443              <?php
 444              /* translators: %s: wp-config.php */
 445              printf( __( 'You can create the %s file manually and paste the following text into it.' ), '<code>wp-config.php</code>' );
 446  
 447              $config_text = '';
 448  
 449              foreach ( $config_file as $line ) {
 450                  $config_text .= htmlentities( $line, ENT_COMPAT, 'UTF-8' );
 451              }
 452              ?>
 453  </p>
 454  <p class="configuration-rules-label"><label for="wp-config">
 455              <?php
 456              /* translators: %s: wp-config.php */
 457              printf( __( 'Configuration rules for %s:' ), '<code>wp-config.php</code>' );
 458              ?>
 459      </label></p>
 460  <textarea id="wp-config" cols="98" rows="15" class="code" readonly="readonly" aria-describedby="wp-config-description"><?php echo $config_text; ?></textarea>
 461  <p><?php _e( 'After you&#8217;ve done that, click &#8220;Run the installation&#8221;.' ); ?></p>
 462  <p class="step"><a href="<?php echo $install; ?>" class="button button-large"><?php _e( 'Run the installation' ); ?></a></p>
 463  <script>
 464  (function(){
 465  if ( ! /iPad|iPod|iPhone/.test( navigator.userAgent ) ) {
 466      var el = document.getElementById('wp-config');
 467      el.focus();
 468      el.select();
 469  }
 470  })();
 471  </script>
 472              <?php
 473          else :
 474              /*
 475               * If this file doesn't exist, then we are using the wp-config-sample.php
 476               * file one level up, which is for the develop repo.
 477               */
 478              if ( file_exists( ABSPATH . 'wp-config-sample.php' ) ) {
 479                  $path_to_wp_config = ABSPATH . 'wp-config.php';
 480              } else {
 481                  $path_to_wp_config = dirname( ABSPATH ) . '/wp-config.php';
 482              }
 483  
 484              $error_message = '';
 485              $handle        = fopen( $path_to_wp_config, 'w' );
 486              /*
 487               * Why check for the absence of false instead of checking for resource with is_resource()?
 488               * To future-proof the check for when fopen returns object instead of resource, i.e. a known
 489               * change coming in PHP.
 490               */
 491              if ( false !== $handle ) {
 492                  foreach ( $config_file as $line ) {
 493                      fwrite( $handle, $line );
 494                  }
 495                  fclose( $handle );
 496              } else {
 497                  $wp_config_perms = fileperms( $path_to_wp_config );
 498                  if ( ! empty( $wp_config_perms ) && ! is_writable( $path_to_wp_config ) ) {
 499                      $error_message = sprintf(
 500                          /* translators: 1: wp-config.php, 2: Documentation URL. */
 501                          __( 'You need to make the file %1$s writable before you can save your changes. See <a href="%2$s">Changing File Permissions</a> for more information.' ),
 502                          '<code>wp-config.php</code>',
 503                          __( 'https://developer.wordpress.org/advanced-administration/server/file-permissions/' )
 504                      );
 505                  } else {
 506                      $error_message = sprintf(
 507                          /* translators: %s: wp-config.php */
 508                          __( 'Unable to write to %s file.' ),
 509                          '<code>wp-config.php</code>'
 510                      );
 511                  }
 512              }
 513  
 514              chmod( $path_to_wp_config, 0666 );
 515              setup_config_display_header();
 516  
 517              if ( false !== $handle ) :
 518                  ?>
 519  <h1 class="screen-reader-text">
 520                  <?php
 521                  /* translators: Hidden accessibility text. */
 522                  _e( 'Successful database connection' );
 523                  ?>
 524  </h1>
 525  <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>
 526  
 527  <p class="step"><a href="<?php echo $install; ?>" class="button button-large"><?php _e( 'Run the installation' ); ?></a></p>
 528                  <?php
 529              else :
 530                  printf( '<p>%s</p>', $error_message );
 531              endif;
 532          endif;
 533          break;
 534  } // End of the steps switch.
 535  ?>
 536  <?php wp_print_scripts( 'language-chooser' ); ?>
 537  </body>
 538  </html>


Generated : Thu Oct 1 08:20:30 2026 Cross-referenced by PHPXref