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


Generated : Wed Apr 15 08:20:10 2026 Cross-referenced by PHPXref