1 bootstrap.inc backdrop_settings_initialize()

Sets the base URL, cookie domain, and session name from configuration.

File

core/includes/bootstrap.inc, line 851
Functions that need to be loaded on every Backdrop request.

Code

function backdrop_settings_initialize() {
  global $base_url, $base_path, $base_root;

  // Export these settings.php variables to the global namespace.
  global $databases, $cookie_domain, $conf, $settings, $installed_profile, $is_https, $base_secure_url, $base_insecure_url, $config_directories, $config;
  $conf = array();

  $conf_path = conf_path();
  if (file_exists($conf_path . '/settings.php')) {
    require_once $conf_path . '/settings.php';
  }
  if (!empty($settings['backdrop_drupal_compatibility'])) {
    require_once BACKDROP_ROOT . '/core/includes/drupal.inc';
  }

  $database_is_set = FALSE;

  // The database connection can be specified in multiple formats:
  // - $database as a string.
  // - $database as an simple array.
  // - $databases as a multi-level nested array.
  // Both the simplified syntaxes are converted to the larger $databases array.

  // First option: the database connection settings have been provided in the
  // form of a connection string. This was the default format in versions prior
  // to Backdrop 1.30.0:
  if (!empty($database) && is_string($database)) {
    $default_db_string = 'mysql://user:pass@localhost/database_name';
    if ($database !== $default_db_string) {
      // Convert simplified database settings string into the full databases
      // array.
      $database_parts = parse_url($database);
      if (!$database_parts) {
        trigger_error('The database setting could not be parsed. Please check the $database setting in settings.php.', E_USER_ERROR);
      }
      $databases['default']['default'] = array(
        'driver' => $database_parts['scheme'],
        // Remove leading slash.
        'database' => rawurldecode(substr($database_parts['path'], 1)),
        'username' => isset($database_parts['user']) ? rawurldecode($database_parts['user']) : '',
        'password' => isset($database_parts['pass']) ? rawurldecode($database_parts['pass']) : '',
        'host' => $database_parts['host'],
        'port' => isset($database_parts['port']) ? $database_parts['port'] : NULL,
        'prefix' => !empty($database_prefix) ? $database_prefix : '',
      );
      $database_is_set = TRUE;
    }
  }
  // Second option: the database connection settings is a simplified array. This
  // is the default format in version 1.30.0 and higher.
  if (!empty($database) && is_array($database)) {
    $default_db_array = array(
      'database' => 'database_name',
      'username' => 'user',
      'password' => 'pass',
      'host' => 'localhost',
    );
    if ($database != $default_db_array) {
      // Specify default values.
      $database += array(
        'prefix' => '',
        'driver' => 'mysql',
        'port' => NULL,
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_general_ci',
      );
      $databases['default']['default'] = $database;
      $database_is_set = TRUE;
    }
  }

  // If using one of the simplified syntaxes, verify all the necessary parts
  // are specified.
  if ($database_is_set) {
    // Check that all required parts are included.
    $required_parts = array('driver', 'database', 'username', 'host');
    foreach ($required_parts as $key) {
      if (!$databases['default']['default'][$key]) {
        $missing_field = ($key == 'database') ? 'name' : $key;
        trigger_error('Could not find a value for the database "' . $missing_field . '" setting. Please check the $database setting in settings.php.', E_USER_ERROR);
      }
    }
  }

  $is_https = backdrop_is_https();

  // Load settings specified by the server, if present.
  if (isset($_SERVER['BACKDROP_SETTINGS'])) {
    $server_settings = @json_decode($_SERVER['BACKDROP_SETTINGS'], TRUE);
    if (!is_array($server_settings)) {
      trigger_error('The values in $_SERVER[BACKDROP_SETTINGS] could not be read. Ensure it is a valid JSON string with no spaces.', E_USER_ERROR);
    }
    else {
      foreach ($server_settings as $key => $value) {
        // One level of depth should be enough for $settings and $databases.
        if ($key == 'settings') {
          foreach ($value as $settings_key => $settings_value) {
            $settings[$settings_key] = $settings_value;
          }
        }
        elseif ($key == 'databases') {
          // Protect default configuration but allow the specification of
          // additional databases.
          if (!isset($databases) || !is_array($databases)) {
            $databases = array();
          }
          $databases = array_replace_recursive($databases, $value);
        }
        else {
          $$key = $value;
        }
      }
    }
  }

  // Pull in the database charset option if specified. This removes the need
  // to use the long-form array and allows enabling ut8mb4 support even if the
  // server provided options via $_SERVER['BACKDROP_SETTINGS'].
  if (isset($database_charset) && isset($databases['default']['default']) && !isset($databases['default']['default']['charset'])) {
    $databases['default']['default']['charset'] = $database_charset;
  }

  if (isset($base_url)) {
    // Parse fixed base URL from settings.php.
    $parts = parse_url($base_url);
    if (!isset($parts['path'])) {
      $parts['path'] = '';
    }
    $base_path = $parts['path'] . '/';
    // Build $base_root (everything until first slash after "scheme://").
    $base_root = substr($base_url, 0, strlen($base_url) - strlen($parts['path']));
  }
  else {
    // Create base URL.
    $http_protocol = $is_https ? 'https' : 'http';
    $base_root = $http_protocol . '://' . $_SERVER['HTTP_HOST'];

    $base_url = $base_root;

    // $_SERVER['SCRIPT_NAME'] can, in contrast to $_SERVER['PHP_SELF'], not
    // be modified by a visitor.
    if ($dir = rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/')) {
      // Remove "core" directory if present, allowing install.php, update.php,
      // cron.php and others to auto-detect a base path.
      $core_position = strrpos($dir, '/core');
      if ($core_position !== FALSE && strlen($dir) - 5 == $core_position) {
        $base_path = substr($dir, 0, $core_position);
      }
      else {
        $base_path = $dir;
      }
      $base_url .= $base_path;
      $base_path .= '/';
    }
    else {
      $base_path = '/';
    }
  }
  $base_secure_url = str_replace('http://', 'https://', $base_url);
  $base_insecure_url = str_replace('https://', 'http://', $base_url);

  if ($cookie_domain) {
    // If the user specifies the cookie domain, also use it for session name.
    $session_name = $cookie_domain;
  }
  else {
    // Otherwise use $base_url as session name, without the protocol
    // to use the same session identifiers across HTTP and HTTPS.
    list(, $session_name) = explode('://', $base_url, 2);
    // HTTP_HOST can be modified by a visitor, but we already sanitized it
    // in backdrop_settings_initialize().
    if (!empty($_SERVER['HTTP_HOST'])) {
      $cookie_domain = $_SERVER['HTTP_HOST'];
      // Strip leading periods, www., and port numbers from cookie domain.
      $cookie_domain = ltrim($cookie_domain, '.');
      if (strpos($cookie_domain, 'www.') === 0) {
        $cookie_domain = substr($cookie_domain, 4);
      }
      $cookie_domain = explode(':', $cookie_domain);
      $cookie_domain = '.' . $cookie_domain[0];
    }
  }
  // Per RFC 2109, cookie domains must contain at least one dot other than the
  // first. For hosts such as 'localhost' or IP Addresses we don't set a cookie domain.
  if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
    ini_set('session.cookie_domain', $cookie_domain);
  }
  // To prevent session cookies from being hijacked, a user can configure the
  // SSL version of their website to only transfer session cookies via SSL by
  // using PHP's session.cookie_secure setting. The browser will then use two
  // separate session cookies for the HTTPS and HTTP versions of the site. So we
  // must use different session identifiers for HTTPS and HTTP to prevent a
  // cookie collision.
  if ($is_https) {
    ini_set('session.cookie_secure', TRUE);
  }
  $prefix = ini_get('session.cookie_secure') ? 'SSESS' : 'SESS';
  session_name($prefix . substr(hash('sha256', $session_name), 0, 32));
}