Newer
Older
/**
* @file
* Functions that need to be loaded on every Drupal request.
*/
Dries Buytaert
committed
/**
* The current system version.
*/
Dries Buytaert
committed
/**
* Core API compatibility.
*/
define('DRUPAL_CORE_COMPATIBILITY', '7.x');
/**
* Minimum supported version of PHP.
*/
define('DRUPAL_MINIMUM_PHP', '5.2.4');
Dries Buytaert
committed
/**
* Minimum recommended value of PHP memory_limit.
*/
define('DRUPAL_MINIMUM_PHP_MEMORY_LIMIT', '32M');
Dries Buytaert
committed
Dries Buytaert
committed
* Indicates that the item should never be removed unless explicitly selected.
*
* The item may be removed using cache_clear_all() with a cache ID.
/**
* Indicates that the item should be removed at the next general cache wipe.
*/
* Log message severity -- Emergency: system is unusable.
Dries Buytaert
committed
*
* The WATCHDOG_* constant definitions correspond to the logging severity levels
* defined in RFC 3164, section 4.1.1: http://www.faqs.org/rfcs/rfc3164.html
*
Gábor Hojtsy
committed
* @see watchdog()
* @see watchdog_severity_levels()
Dries Buytaert
committed
define('WATCHDOG_EMERGENCY', 0);
/**
* Log message severity -- Alert: action must be taken immediately.
*
* The WATCHDOG_* constant definitions correspond to the logging severity levels
* defined in RFC 3164, section 4.1.1: http://www.faqs.org/rfcs/rfc3164.html
*
* @see watchdog()
* @see watchdog_severity_levels()
*/
define('WATCHDOG_ALERT', 1);
/**
* Log message severity -- Critical: critical conditions.
*
* The WATCHDOG_* constant definitions correspond to the logging severity levels
* defined in RFC 3164, section 4.1.1: http://www.faqs.org/rfcs/rfc3164.html
*
* @see watchdog()
* @see watchdog_severity_levels()
*/
define('WATCHDOG_CRITICAL', 2);
/**
* Log message severity -- Error: error conditions.
*
* The WATCHDOG_* constant definitions correspond to the logging severity levels
* defined in RFC 3164, section 4.1.1: http://www.faqs.org/rfcs/rfc3164.html
*
* @see watchdog()
* @see watchdog_severity_levels()
*/
define('WATCHDOG_ERROR', 3);
/**
* Log message severity -- Warning: warning conditions.
*
* The WATCHDOG_* constant definitions correspond to the logging severity levels
* defined in RFC 3164, section 4.1.1: http://www.faqs.org/rfcs/rfc3164.html
*
* @see watchdog()
* @see watchdog_severity_levels()
*/
define('WATCHDOG_WARNING', 4);
/**
* Log message severity -- Notice: normal but significant condition.
*
* The WATCHDOG_* constant definitions correspond to the logging severity levels
* defined in RFC 3164, section 4.1.1: http://www.faqs.org/rfcs/rfc3164.html
*
* @see watchdog()
* @see watchdog_severity_levels()
*/
define('WATCHDOG_NOTICE', 5);
/**
* Log message severity -- Informational: informational messages.
*
* The WATCHDOG_* constant definitions correspond to the logging severity levels
* defined in RFC 3164, section 4.1.1: http://www.faqs.org/rfcs/rfc3164.html
*
* @see watchdog()
* @see watchdog_severity_levels()
*/
define('WATCHDOG_INFO', 6);
/**
* Log message severity -- Debug: debug-level messages.
*
* The WATCHDOG_* constant definitions correspond to the logging severity levels
* defined in RFC 3164, section 4.1.1: http://www.faqs.org/rfcs/rfc3164.html
*
* @see watchdog()
* @see watchdog_severity_levels()
*/
define('WATCHDOG_DEBUG', 7);
/**
* First bootstrap phase: initialize configuration.
*/
define('DRUPAL_BOOTSTRAP_CONFIGURATION', 0);
* Second bootstrap phase: try to serve a cached page.
define('DRUPAL_BOOTSTRAP_PAGE_CACHE', 1);
/**
* Third bootstrap phase: initialize database layer.
*/
define('DRUPAL_BOOTSTRAP_DATABASE', 2);
Dries Buytaert
committed
* Fourth bootstrap phase: initialize the variable system.
Dries Buytaert
committed
define('DRUPAL_BOOTSTRAP_VARIABLES', 3);
Dries Buytaert
committed
* Fifth bootstrap phase: initialize session handling.
Dries Buytaert
committed
define('DRUPAL_BOOTSTRAP_SESSION', 4);
Dries Buytaert
committed
* Sixth bootstrap phase: set up the page header.
Dries Buytaert
committed
*/
Dries Buytaert
committed
define('DRUPAL_BOOTSTRAP_PAGE_HEADER', 5);
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Seventh bootstrap phase: find out language of the page.
Dries Buytaert
committed
define('DRUPAL_BOOTSTRAP_LANGUAGE', 6);
/**
* Final bootstrap phase: Drupal is fully loaded; validate and fix
* input data.
*/
Angie Byron
committed
define('DRUPAL_BOOTSTRAP_FULL', 7);
/**
* Role ID for anonymous users; should match what's in the "role" table.
*/
Dries Buytaert
committed
define('DRUPAL_ANONYMOUS_RID', 1);
/**
* Role ID for authenticated users; should match what's in the "role" table.
*/
Dries Buytaert
committed
define('DRUPAL_AUTHENTICATED_RID', 2);
Dries Buytaert
committed
/**
Angie Byron
committed
* The number of bytes in a kilobyte. For more information, visit
Dries Buytaert
committed
* http://en.wikipedia.org/wiki/Kilobyte.
*/
define('DRUPAL_KILOBYTE', 1024);
/**
* The language code used when no language is explicitly assigned.
*
Dries Buytaert
committed
* Defined by ISO639-2 for "Undetermined".
Dries Buytaert
committed
define('LANGUAGE_NONE', 'und');
/**
Angie Byron
committed
* The type of language used to define the content language.
*/
Angie Byron
committed
define('LANGUAGE_TYPE_CONTENT', 'language_content');
/**
Angie Byron
committed
* The type of language used to select the user interface.
*/
Angie Byron
committed
define('LANGUAGE_TYPE_INTERFACE', 'language');
/**
Angie Byron
committed
* The type of language used for URLs.
*/
Angie Byron
committed
define('LANGUAGE_TYPE_URL', 'language_url');
/**
* Language written left to right. Possible value of $language->direction.
*/
define('LANGUAGE_LTR', 0);
/**
* Language written right to left. Possible value of $language->direction.
*/
define('LANGUAGE_RTL', 1);
Dries Buytaert
committed
/**
* For convenience, define a short form of the request time global.
*/
define('REQUEST_TIME', $_SERVER['REQUEST_TIME']);
Dries Buytaert
committed
/**
* Flag for drupal_set_title(); text is not sanitized, so run check_plain().
*/
define('CHECK_PLAIN', 0);
/**
* Flag for drupal_set_title(); text has already been sanitized.
*/
define('PASS_THROUGH', -1);
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Signals that the registry lookup cache should be reset.
Dries Buytaert
committed
*/
define('REGISTRY_RESET_LOOKUP_CACHE', 1);
/**
Dries Buytaert
committed
* Signals that the registry lookup cache should be written to storage.
Dries Buytaert
committed
*/
define('REGISTRY_WRITE_LOOKUP_CACHE', 2);
Dries Buytaert
committed
/**
* Regular expression to match PHP function names.
*
* @see http://php.net/manual/en/language.functions.php
*/
define('DRUPAL_PHP_FUNCTION_PATTERN', '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*');
* Start the timer with the specified name. If you start and stop the same
* timer multiple times, the measured intervals will be accumulated.
*
* @param name
* The name of the timer.
*/
function timer_start($name) {
global $timers;
Dries Buytaert
committed
$timers[$name]['start'] = microtime(TRUE);
$timers[$name]['count'] = isset($timers[$name]['count']) ? ++$timers[$name]['count'] : 1;
}
/**
* Read the current timer value without stopping the timer.
*
* @param name
* The name of the timer.
* @return
* The current timer value in ms.
*/
function timer_read($name) {
global $timers;
if (isset($timers[$name]['start'])) {
Dries Buytaert
committed
$stop = microtime(TRUE);
$diff = round(($stop - $timers[$name]['start']) * 1000, 2);
if (isset($timers[$name]['time'])) {
$diff += $timers[$name]['time'];
}
return $diff;
Dries Buytaert
committed
return $timers[$name]['time'];
}
/**
* Stop the timer with the specified name.
*
* @param name
* The name of the timer.
* @return
* A timer array. The array contains the number of times the timer has been
* started and stopped (count) and the accumulated timer value in ms (time).
Dries Buytaert
committed
if (isset($timers[$name]['start'])) {
$stop = microtime(TRUE);
$diff = round(($stop - $timers[$name]['start']) * 1000, 2);
if (isset($timers[$name]['time'])) {
$timers[$name]['time'] += $diff;
}
else {
$timers[$name]['time'] = $diff;
}
unset($timers[$name]['start']);
Dries Buytaert
committed
}
* Find the appropriate configuration directory.
* Try finding a matching configuration directory by stripping the website's
* hostname from left to right and pathname from right to left. The first
* configuration file found will be used; the remaining will ignored. If no
* configuration file is found, return a default value '$confdir/default'.
Dries Buytaert
committed
* Example for a fictitious site installed at
* http://www.drupal.org:8080/mysite/test/ the 'settings.php' is searched in
* the following directories:
* 1. $confdir/8080.www.drupal.org.mysite.test
* 2. $confdir/www.drupal.org.mysite.test
* 3. $confdir/drupal.org.mysite.test
* 4. $confdir/org.mysite.test
* 5. $confdir/8080.www.drupal.org.mysite
* 6. $confdir/www.drupal.org.mysite
* 7. $confdir/drupal.org.mysite
* 8. $confdir/org.mysite
* 9. $confdir/8080.www.drupal.org
* 10. $confdir/www.drupal.org
* 11. $confdir/drupal.org
* 12. $confdir/org
* 13. $confdir/default
* If a file named sites.php is present in the $confdir, it will be loaded
Dries Buytaert
committed
* prior to scanning for directories. It should define an associative array
* named $sites, which maps domains to directories. It should be in the form
* of:
*
* $sites = array(
* 'The url to alias' => 'A directory within the sites directory'
* );
*
* For example:
*
* $sites = array(
* 'devexample.com' => 'example.com',
Dries Buytaert
committed
* 'localhost.example' => 'example.com',
* );
*
* The above array will cause Drupal to look for a directory named
* "example.com" in the sites directory whenever a request comes from
* "example.com", "devexample.com", or "localhost/example". That is useful
* on development servers, where the domain name may not be the same as the
Dries Buytaert
committed
* domain of the live server. Since Drupal stores file paths into the database
* (files, system table, etc.) this will ensure the paths are correct while
* accessed on development servers.
*
* @param $require_settings
* Only configuration directories with an existing settings.php file
* will be recognized. Defaults to TRUE. During initial installation,
* this is set to FALSE so that Drupal can detect a matching directory,
* then create a new settings.php file in it.
* @param reset
* Force a full search for matching directories even if one had been
* found previously.
* @return
* The path of the matching directory.
function conf_path($require_settings = TRUE, $reset = FALSE) {
Dries Buytaert
committed
$conf = &drupal_static(__FUNCTION__, '');
if ($conf && !$reset) {
$sites = array();
if (file_exists(DRUPAL_ROOT . '/' . $confdir . '/sites.php')) {
// This will overwrite $sites with the desired mappings.
include(DRUPAL_ROOT . '/' . $confdir . '/sites.php');
}
$uri = explode('/', $_SERVER['SCRIPT_NAME'] ? $_SERVER['SCRIPT_NAME'] : $_SERVER['SCRIPT_FILENAME']);
$server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.')))));
for ($i = count($uri) - 1; $i > 0; $i--) {
for ($j = count($server); $j > 0; $j--) {
$dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
if (isset($sites[$dir]) && file_exists(DRUPAL_ROOT . '/' . $confdir . '/' . $sites[$dir])) {
$dir = $sites[$dir];
}
if (file_exists(DRUPAL_ROOT . '/' . $confdir . '/' . $dir . '/settings.php') || (!$require_settings && file_exists(DRUPAL_ROOT . '/' . $confdir . '/' . $dir))) {
$conf = "$confdir/$dir";
return $conf;
}
$conf = "$confdir/default";
return $conf;
Dries Buytaert
committed
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
/**
* Set appropriate server variables needed for command line scripts to work.
*
* This function can be called by command line scripts before bootstrapping
* Drupal, to ensure that the page loads with the desired server parameters.
* This is because many parts of Drupal assume that they are running in a web
* browser and therefore use information from the global PHP $_SERVER variable
* that does not get set when Drupal is run from the command line.
*
* In many cases, the default way in which this function populates the $_SERVER
* variable is sufficient, and it can therefore be called without passing in
* any input. However, command line scripts running on a multisite installation
* (or on any installation that has settings.php stored somewhere other than
* the sites/default folder) need to pass in the URL of the site to allow
* Drupal to detect the correct location of the settings.php file. Passing in
* the 'url' parameter is also required for functions like request_uri() to
* return the expected values.
*
* Most other parameters do not need to be passed in, but may be necessary in
* some cases; for example, if Drupal's ip_address() function needs to return
* anything but the standard localhost value ('127.0.0.1'), the command line
* script should pass in the desired value via the 'REMOTE_ADDR' key.
*
* @param $variables
* (optional) An associative array of variables within $_SERVER that should
* be replaced. If the special element 'url' is provided in this array, it
* will be used to populate some of the server defaults; it should be set to
* the URL of the current page request, excluding any $_GET request but
* including the script name (e.g., http://www.example.com/mysite/index.php).
*
* @see conf_path()
* @see request_uri()
* @see ip_address()
*/
function drupal_override_server_variables($variables = array()) {
// Allow the provided URL to override any existing values in $_SERVER.
Dries Buytaert
committed
if (isset($variables['url'])) {
$url = parse_url($variables['url']);
if (isset($url['host'])) {
$_SERVER['HTTP_HOST'] = $url['host'];
}
if (isset($url['path'])) {
$_SERVER['SCRIPT_NAME'] = $url['path'];
}
Dries Buytaert
committed
unset($variables['url']);
}
// Define default values for $_SERVER keys. These will be used if $_SERVER
// does not already define them and no other values are passed in to this
// function.
Dries Buytaert
committed
$defaults = array(
'HTTP_HOST' => 'localhost',
'SCRIPT_NAME' => NULL,
Dries Buytaert
committed
'REMOTE_ADDR' => '127.0.0.1',
'REQUEST_METHOD' => 'GET',
'SERVER_NAME' => NULL,
Dries Buytaert
committed
'SERVER_SOFTWARE' => NULL,
Dries Buytaert
committed
'HTTP_USER_AGENT' => NULL,
);
// Replace elements of the $_SERVER array, as appropriate.
$_SERVER = $variables + $_SERVER + $defaults;
}
Gerhard Killesreiter
committed
/**
Dries Buytaert
committed
* Initialize PHP environment.
*/
Dries Buytaert
committed
function drupal_environment_initialize() {
if (!isset($_SERVER['HTTP_REFERER'])) {
$_SERVER['HTTP_REFERER'] = '';
Gerhard Killesreiter
committed
}
Dries Buytaert
committed
if (!isset($_SERVER['SERVER_PROTOCOL']) || ($_SERVER['SERVER_PROTOCOL'] != 'HTTP/1.0' && $_SERVER['SERVER_PROTOCOL'] != 'HTTP/1.1')) {
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0';
}
Dries Buytaert
committed
if (isset($_SERVER['HTTP_HOST'])) {
// As HTTP_HOST is user input, ensure it only contains characters allowed
// in hostnames. See RFC 952 (and RFC 2181).
// $_SERVER['HTTP_HOST'] is lowercased here per specifications.
$_SERVER['HTTP_HOST'] = strtolower($_SERVER['HTTP_HOST']);
if (!drupal_valid_http_host($_SERVER['HTTP_HOST'])) {
// HTTP_HOST is invalid, e.g. if containing slashes it may be an attack.
header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
exit;
}
}
else {
// Some pre-HTTP/1.1 clients will not send a Host header. Ensure the key is
// defined for E_ALL compliance.
$_SERVER['HTTP_HOST'] = '';
Dries Buytaert
committed
}
Dries Buytaert
committed
// When clean URLs are enabled, emulate ?q=foo/bar using REQUEST_URI. It is
// not possible to append the query string using mod_rewrite without the B
// flag (this was added in Apache 2.2.8), because mod_rewrite unescapes the
// path before passing it on to PHP. This is a problem when the path contains
// e.g. "&" or "%" that have special meanings in URLs and must be encoded.
$_GET['q'] = request_path();
Dries Buytaert
committed
// Enforce E_ALL, but allow users to set levels not part of E_ALL.
error_reporting(E_ALL | error_reporting());
// Override PHP settings required for Drupal to work properly.
// sites/default/default.settings.php contains more runtime settings.
// The .htaccess file contains settings that cannot be changed at runtime.
// Don't escape quotes when reading files from the database, disk, etc.
ini_set('magic_quotes_runtime', '0');
Dries Buytaert
committed
// Use session cookies, not transparent sessions that puts the session id in
// the query string.
ini_set('session.use_cookies', '1');
Dries Buytaert
committed
ini_set('session.use_only_cookies', '1');
ini_set('session.use_trans_sid', '0');
Dries Buytaert
committed
// Don't send HTTP headers using PHP's session handler.
ini_set('session.cache_limiter', 'none');
Dries Buytaert
committed
// Use httponly session cookies.
ini_set('session.cookie_httponly', '1');
// Set sane locale settings, to ensure consistent string, dates, times and
// numbers handling.
setlocale(LC_ALL, 'C');
Gerhard Killesreiter
committed
}
Dries Buytaert
committed
/**
* Validate that a hostname (for example $_SERVER['HTTP_HOST']) is safe.
Dries Buytaert
committed
*
* @return
* TRUE if only containing valid characters, or FALSE otherwise.
*/
function drupal_valid_http_host($host) {
return preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host);
Dries Buytaert
committed
}
Dries Buytaert
committed
* Loads the configuration and sets the base URL, cookie domain, and
* session name correctly.
Dries Buytaert
committed
function drupal_settings_initialize() {
global $base_url, $base_path, $base_root;
// Export the following settings.php variables to the global namespace
Angie Byron
committed
global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url;
Angie Byron
committed
if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) {
include_once DRUPAL_ROOT . '/' . conf_path() . '/settings.php';
Dries Buytaert
committed
}
Dries Buytaert
committed
$is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on';
if (isset($base_url)) {
// Parse fixed base URL from settings.php.
$parts = parse_url($base_url);
Dries Buytaert
committed
$http_protocol = $parts['scheme'];
Neil Drumm
committed
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
Dries Buytaert
committed
$http_protocol = $is_https ? 'https' : 'http';
Dries Buytaert
committed
$base_root = $http_protocol . '://' . $_SERVER['HTTP_HOST'];
Dries Buytaert
committed
$base_url = $base_root;
// $_SERVER['SCRIPT_NAME'] can, in contrast to $_SERVER['PHP_SELF'], not
// be modified by a visitor.
Dries Buytaert
committed
if ($dir = rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/')) {
$base_path = $dir;
$base_url .= $base_path;
$base_path .= '/';
}
else {
$base_path = '/';
}
}
Dries Buytaert
committed
$base_secure_url = str_replace('http://', 'https://', $base_url);
$base_insecure_url = str_replace('https://', 'http://', $base_url);
Dries Buytaert
committed
if ($cookie_domain) {
// If the user specifies the cookie domain, also use it for session name.
$session_name = $cookie_domain;
}
else {
Gábor Hojtsy
committed
// 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 drupal_settings_initialize().
Dries Buytaert
committed
if (!empty($_SERVER['HTTP_HOST'])) {
$cookie_domain = $_SERVER['HTTP_HOST'];
Dries Buytaert
committed
// 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];
Dries Buytaert
committed
}
}
// 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);
}
Dries Buytaert
committed
// 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';
Dries Buytaert
committed
session_name($prefix . substr(hash('sha256', $session_name), 0, 32));
/**
* Returns and optionally sets the filename for a system item (module,
* theme, etc.). The filename, whether provided, cached, or retrieved
* from the database, is only returned if the file exists.
*
* This function plays a key role in allowing Drupal's resources (modules
* and themes) to be located in different places depending on a site's
* configuration. For example, a module 'foo' may legally be be located
* in any of these three places:
*
* modules/foo/foo.module
* sites/all/modules/foo/foo.module
* sites/example.com/modules/foo/foo.module
*
* Calling drupal_get_filename('module', 'foo') will give you one of
* the above, depending on where the module is located.
*
Angie Byron
committed
* The type of the item (i.e. theme, theme_engine, module, profile).
* @param $name
* The name of the item for which the filename is requested.
* @param $filename
* The filename of the item if it is to be set explicitly rather
* than by consulting the database.
*
* @return
* The filename of the requested item.
*/
function drupal_get_filename($type, $name, $filename = NULL) {
// The location of files will not change during the request, so do not use
// drupal_static().
static $files = array();
if (!isset($files[$type])) {
if (!empty($filename) && file_exists($filename)) {
elseif (isset($files[$type][$name])) {
// Verify that we have an active database connection, before querying
Dries Buytaert
committed
// the database. This is required because this function is called both
// before we have a database connection (i.e. during installation) and
// when a database connection fails.
Angie Byron
committed
try {
Angie Byron
committed
if (function_exists('db_query')) {
$file = db_query("SELECT filename FROM {system} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type))->fetchField();
Dries Buytaert
committed
if (file_exists(DRUPAL_ROOT . '/' . $file)) {
Angie Byron
committed
$files[$type][$name] = $file;
}
Angie Byron
committed
}
}
Angie Byron
committed
catch (Exception $e) {
Angie Byron
committed
// The database table may not exist because Drupal is not yet installed,
// or the database might be down. We have a fallback for this case so we
// hide the error completely.
}
// Fallback to searching the filesystem if the database could not find the
// file or the file returned by the database is not found.
if (!isset($files[$type][$name])) {
// We have a consistent directory naming: modules, themes...
$dir = $type . 's';
if ($type == 'theme_engine') {
$dir = 'themes/engines';
Angie Byron
committed
$extension = 'engine';
Angie Byron
committed
}
elseif ($type == 'theme') {
Angie Byron
committed
$extension = 'info';
Angie Byron
committed
}
else {
Angie Byron
committed
$extension = $type;
Angie Byron
committed
}
if (!function_exists('drupal_system_listing')) {
require_once DRUPAL_ROOT . '/includes/common.inc';
}
Angie Byron
committed
// Scan the appropriate directories for all files with the requested
// extension, not just the file we are currently looking for. This
// prevents unnecessary scans from being repeated when this function is
// called more than once in the same page request.
Dries Buytaert
committed
$matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0);
Angie Byron
committed
foreach ($matches as $matched_name => $file) {
$files[$type][$matched_name] = $file->uri;
Steven Wittens
committed
if (isset($files[$type][$name])) {
return $files[$type][$name];
}
/**
* Load the persistent variable table.
*
* The variable table is composed of values that have been saved in the table
* with variable_set() as well as those explicitly specified in the configuration
* file.
*/
Dries Buytaert
committed
function variable_initialize($conf = array()) {
Dries Buytaert
committed
// NOTE: caching the variables improves performance by 20% when serving
// cached pages.
Dries Buytaert
committed
if ($cached = cache_get('variables', 'cache_bootstrap')) {
Dries Buytaert
committed
$variables = $cached->data;
Dries Buytaert
committed
// Cache miss. Avoid a stampede.
$name = 'variable_init';
if (!lock_acquire($name, 1)) {
// Another request is building the variable cache.
// Wait, then re-run this function.
lock_wait($name);
return variable_initialize($conf);
}
else {
// Proceed with variable rebuild.
$variables = array_map('unserialize', db_query('SELECT name, value FROM {variable}')->fetchAllKeyed());
cache_set('variables', $variables, 'cache_bootstrap');
lock_release($name);
}
}
foreach ($conf as $name => $value) {
$variables[$name] = $value;
Dries Buytaert
committed
* Returns a persistent variable.
*
* Case-sensitivity of the variable_* functions depends on the database
* collation used. To avoid problems, always use lower case for persistent
* variable names.
*
* @param $name
* The name of the variable to return.
* @param $default
* The default value to use if this variable has never been set.
Dries Buytaert
committed
*
*
Dries Buytaert
committed
* @see variable_del()
* @see variable_set()
function variable_get($name, $default = NULL) {
global $conf;
return isset($conf[$name]) ? $conf[$name] : $default;
}
Dries Buytaert
committed
* Sets a persistent variable.
*
* Case-sensitivity of the variable_* functions depends on the database
* collation used. To avoid problems, always use lower case for persistent
* variable names.
*
* @param $name
* The name of the variable to set.
* @param $value
* The value to set. This can be any PHP data type; these functions take care
* of serialization as necessary.
*
Dries Buytaert
committed
* @see variable_del()
* @see variable_get()
Dries Buytaert
committed
db_merge('variable')->key(array('name' => $name))->fields(array('value' => serialize($value)))->execute();
Dries Buytaert
committed
cache_clear_all('variables', 'cache_bootstrap');
Dries Buytaert
committed
* Unsets a persistent variable.
*
* Case-sensitivity of the variable_* functions depends on the database
* collation used. To avoid problems, always use lower case for persistent
* variable names.
*
Dries Buytaert
committed
* @see variable_get()
* @see variable_set()
Dries Buytaert
committed
db_delete('variable')
->condition('name', $name)
->execute();
Dries Buytaert
committed
cache_clear_all('variables', 'cache_bootstrap');
Dries Buytaert
committed
* Note: we do not serve cached pages to authenticated users, or to anonymous
* users when $_SESSION is non-empty. $_SESSION may contain status messages
* from a form submission, the contents of a shopping cart, or other user-
* specific content that should not be cached and displayed to other users.
*
Dries Buytaert
committed
* @param $check_only
* (optional) Set to TRUE to only return whether a previous call found a
* cache entry.
*
Dries Buytaert
committed
* @return
Dries Buytaert
committed
* The cache object, if the page was found in the cache, NULL otherwise.
Dries Buytaert
committed
function drupal_page_get_cache($check_only = FALSE) {
Dries Buytaert
committed
global $base_root;
Dries Buytaert
committed
static $cache_hit = FALSE;
if ($check_only) {
return $cache_hit;
}
Dries Buytaert
committed
if (drupal_page_is_cacheable()) {
Dries Buytaert
committed
$cache = cache_get($base_root . request_uri(), 'cache_page');
if ($cache !== FALSE) {
$cache_hit = TRUE;
}
return $cache;
Dries Buytaert
committed
}
Dries Buytaert
committed
}
/**
* Determine the cacheability of the current page.
*
* @param $allow_caching
Dries Buytaert
committed
* Set to FALSE if you want to prevent this page to get cached.
*
Dries Buytaert
committed
* @return
Dries Buytaert
committed
* TRUE if the current page can be cached, FALSE otherwise.
Dries Buytaert
committed
*/
function drupal_page_is_cacheable($allow_caching = NULL) {
$allow_caching_static = &drupal_static(__FUNCTION__, TRUE);
if (isset($allow_caching)) {
$allow_caching_static = $allow_caching;
Dries Buytaert
committed
return $allow_caching_static && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD')
Dries Buytaert
committed
&& !drupal_is_cli();
/**
Dries Buytaert
committed
* Invoke a bootstrap hook in all bootstrap modules that implement it.
*
* @param $hook
Dries Buytaert
committed
* The name of the bootstrap hook to invoke.
Dries Buytaert
committed
*
* @see bootstrap_hooks()
*/
function bootstrap_invoke_all($hook) {
Dries Buytaert
committed
// Bootstrap modules should have been loaded when this function is called, so
// we don't need to tell module_list() to reset its internal list (and we
// therefore leave the first parameter at its default value of FALSE). We
// still pass in TRUE for the second parameter, though; in case this is the
// first time during the bootstrap that module_list() is called, we want to
// make sure that its internal cache is primed with the bootstrap modules
// only.
Dries Buytaert
committed
foreach (module_list(FALSE, TRUE) as $module) {
drupal_load('module', $module);
module_invoke($module, $hook);
}
}
* Includes a file with the provided type and name. This prevents
* including a theme, engine, module, etc., more than once.
*
* @param $type
* The type of item to load (i.e. theme, theme_engine, module).
* @param $name
* The name of the item to load.
*
* @return
* TRUE if the item is loaded or has already been loaded.
*/
function drupal_load($type, $name) {
// Once a file is included this can't be reversed during a request so do not
// use drupal_static() here.
static $files = array();
if (isset($files[$type][$name])) {
return TRUE;
}
$filename = drupal_get_filename($type, $name);
if ($filename) {
Angie Byron
committed
include_once DRUPAL_ROOT . '/' . $filename;
$files[$type][$name] = TRUE;
return TRUE;
}
return FALSE;
}
Dries Buytaert
committed
/**
* Set an HTTP response header for the current page.
*
* Note: When sending a Content-Type header, always include a 'charset' type,
* too. This is necessary to avoid security bugs (e.g. UTF-7 XSS).
*
* @param $name
Dries Buytaert
committed
* The HTTP header name, or the special 'Status' header name.
Dries Buytaert
committed
* @param $value
Dries Buytaert
committed
* The HTTP header value; if equal to FALSE, the specified header is unset.
* If $name is 'Status', this is expected to be a status code followed by a
* reason phrase, e.g. "404 Not Found".
Dries Buytaert
committed
* @param $append
* Whether to append the value to an existing header or to replace it.
*/
Dries Buytaert
committed
function drupal_add_http_header($name, $value, $append = FALSE) {
Dries Buytaert
committed
// The headers as name/value pairs.
Dries Buytaert
committed
$headers = &drupal_static('drupal_http_headers', array());
Dries Buytaert
committed
Dries Buytaert
committed
$name_lower = strtolower($name);
Dries Buytaert
committed
_drupal_set_preferred_header_name($name);
Dries Buytaert
committed
Dries Buytaert
committed
if ($value === FALSE) {
Dries Buytaert
committed
$headers[$name_lower] = FALSE;
Dries Buytaert
committed
}
Dries Buytaert
committed
elseif (isset($headers[$name_lower]) && $append) {
Dries Buytaert
committed
// Multiple headers with identical names may be combined using comma (RFC
// 2616, section 4.2).
Dries Buytaert
committed
$headers[$name_lower] .= ',' . $value;
Dries Buytaert
committed
}
else {
Dries Buytaert
committed
$headers[$name_lower] = $value;
Dries Buytaert
committed
}
Dries Buytaert
committed
drupal_send_headers(array($name => $headers[$name_lower]), TRUE);
Dries Buytaert
committed
}
/**
* Get the HTTP response headers for the current page.
*
* @param $name
* An HTTP header name. If omitted, all headers are returned as name/value
* pairs. If an array value is FALSE, the header has been unset.
* @return
* A string containing the header value, or FALSE if the header has been set,
* or NULL if the header has not been set.
*/
Dries Buytaert
committed
function drupal_get_http_header($name = NULL) {
Dries Buytaert
committed
$headers = &drupal_static('drupal_http_headers', array());
Dries Buytaert
committed
if (isset($name)) {
$name = strtolower($name);
return isset($headers[$name]) ? $headers[$name] : NULL;
}
else {
return $headers;
}
}
/**
* Header names are case-insensitive, but for maximum compatibility they should
* follow "common form" (see RFC 2617, section 4.2).