2006-12-12 06:27:17 +00:00
< ? php
2004-09-09 05:51:08 +00:00
// $Id$
2003-11-18 19:44:36 +00:00
2004-07-13 07:21:14 +00:00
/**
* @ file
* Functions that need to be loaded on every Drupal request .
*/
2004-09-16 07:17:56 +00:00
2006-12-12 06:16:33 +00:00
/**
* Indicates that the item should never be removed unless explicitly told to
* using cache_clear_all () with a cache ID .
*/
2004-09-15 20:34:35 +00:00
define ( 'CACHE_PERMANENT' , 0 );
2006-12-12 06:16:33 +00:00
/**
* Indicates that the item should be removed at the next general cache wipe .
*/
2004-09-15 20:34:35 +00:00
define ( 'CACHE_TEMPORARY' , - 1 );
2003-11-18 19:44:36 +00:00
2006-12-12 06:16:33 +00:00
/**
* Indicates that page caching is disabled .
*/
2005-04-11 19:05:52 +00:00
define ( 'CACHE_DISABLED' , 0 );
2006-12-12 06:16:33 +00:00
/**
* Indicates that page caching is enabled , using " normal " mode .
*/
2006-08-31 18:40:04 +00:00
define ( 'CACHE_NORMAL' , 1 );
2006-12-12 06:16:33 +00:00
/**
* Indicates that page caching is using " aggressive " mode . This bypasses
* loading any modules for additional speed , which may break functionality in
* modules that expect to be run on each page load .
*/
2006-08-31 18:40:04 +00:00
define ( 'CACHE_AGGRESSIVE' , 2 );
2005-04-11 19:05:52 +00:00
2006-12-11 12:01:54 +00:00
/**
2008-05-26 17:12:55 +00:00
* Log message severity -- Emergency : system is unusable .
2007-04-10 10:10:27 +00:00
*
2008-01-08 10:35:43 +00:00
* @ see watchdog ()
* @ see watchdog_severity_levels ()
2006-12-11 12:01:54 +00:00
*/
2008-05-26 17:12:55 +00:00
define ( 'WATCHDOG_EMERG' , 0 );
/**
* Log message severity -- Alert : action must be taken immediately .
*
* @ see watchdog ()
* @ see watchdog_severity_levels ()
*/
define ( 'WATCHDOG_ALERT' , 1 );
/**
* Log message severity -- Critical : critical conditions .
*
* @ see watchdog ()
* @ see watchdog_severity_levels ()
*/
define ( 'WATCHDOG_CRITICAL' , 2 );
/**
* Log message severity -- Error : error conditions .
*
* @ see watchdog ()
* @ see watchdog_severity_levels ()
*/
define ( 'WATCHDOG_ERROR' , 3 );
/**
* Log message severity -- Warning : warning conditions .
*
* @ see watchdog ()
* @ see watchdog_severity_levels ()
*/
define ( 'WATCHDOG_WARNING' , 4 );
/**
* Log message severity -- Notice : normal but significant condition .
*
* @ see watchdog ()
* @ see watchdog_severity_levels ()
*/
define ( 'WATCHDOG_NOTICE' , 5 );
/**
* Log message severity -- Informational : informational messages .
*
* @ see watchdog ()
* @ see watchdog_severity_levels ()
*/
define ( 'WATCHDOG_INFO' , 6 );
/**
* Log message severity -- Debug : debug - level messages .
*
* @ see watchdog ()
* @ see watchdog_severity_levels ()
*/
define ( 'WATCHDOG_DEBUG' , 7 );
2005-01-09 09:22:40 +00:00
2006-12-08 12:09:54 +00:00
/**
* First bootstrap phase : initialize configuration .
*/
2006-06-14 14:01:12 +00:00
define ( 'DRUPAL_BOOTSTRAP_CONFIGURATION' , 0 );
2006-12-08 12:09:54 +00:00
/**
* Second bootstrap phase : try to call a non - database cache
* fetch routine .
*/
2006-06-14 14:01:12 +00:00
define ( 'DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE' , 1 );
2006-12-08 12:09:54 +00:00
/**
* Third bootstrap phase : initialize database layer .
*/
2006-06-14 14:01:12 +00:00
define ( 'DRUPAL_BOOTSTRAP_DATABASE' , 2 );
2006-12-08 12:09:54 +00:00
/**
* Fourth bootstrap phase : identify and reject banned hosts .
*/
2006-09-06 07:53:01 +00:00
define ( 'DRUPAL_BOOTSTRAP_ACCESS' , 3 );
2006-12-08 12:09:54 +00:00
/**
* Fifth bootstrap phase : initialize session handling .
*/
2006-09-06 07:53:01 +00:00
define ( 'DRUPAL_BOOTSTRAP_SESSION' , 4 );
2006-12-08 12:09:54 +00:00
/**
* Sixth bootstrap phase : load bootstrap . inc and module . inc , start
* the variable system and try to serve a page from the cache .
*/
2006-09-06 07:53:01 +00:00
define ( 'DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE' , 5 );
2006-12-08 12:09:54 +00:00
/**
2007-03-26 01:32:22 +00:00
* Seventh bootstrap phase : find out language of the page .
2006-12-08 12:09:54 +00:00
*/
2007-03-26 01:32:22 +00:00
define ( 'DRUPAL_BOOTSTRAP_LANGUAGE' , 6 );
/**
* Eighth bootstrap phase : set $_GET [ 'q' ] to Drupal path of request .
*/
define ( 'DRUPAL_BOOTSTRAP_PATH' , 7 );
2006-12-08 12:09:54 +00:00
/**
* Final bootstrap phase : Drupal is fully loaded ; validate and fix
* input data .
*/
2007-03-26 01:32:22 +00:00
define ( 'DRUPAL_BOOTSTRAP_FULL' , 8 );
2005-07-23 05:57:27 +00:00
2006-12-11 12:00:07 +00:00
/**
* Role ID for anonymous users ; should match what ' s in the " role " table .
*/
2006-01-21 08:28:55 +00:00
define ( 'DRUPAL_ANONYMOUS_RID' , 1 );
2006-12-11 12:00:07 +00:00
/**
* Role ID for authenticated users ; should match what ' s in the " role " table .
*/
2006-01-21 08:28:55 +00:00
define ( 'DRUPAL_AUTHENTICATED_RID' , 2 );
2007-03-26 01:32:22 +00:00
/**
* No language negotiation . The default language is used .
*/
define ( 'LANGUAGE_NEGOTIATION_NONE' , 0 );
/**
* Path based negotiation with fallback to default language
* if no defined path prefix identified .
*/
define ( 'LANGUAGE_NEGOTIATION_PATH_DEFAULT' , 1 );
/**
* Path based negotiation with fallback to user preferences
* and browser language detection if no defined path prefix
* identified .
*/
define ( 'LANGUAGE_NEGOTIATION_PATH' , 2 );
/**
* Domain based negotiation with fallback to default language
* if no language identified by domain .
*/
define ( 'LANGUAGE_NEGOTIATION_DOMAIN' , 3 );
2008-09-17 07:11:59 +00:00
/**
* For convenience , define a short form of the request time global .
*/
2008-10-06 22:40:20 +00:00
define ( 'REQUEST_TIME' , $_SERVER [ 'REQUEST_TIME' ]);
2008-09-17 07:11:59 +00:00
2008-10-13 04:06:22 +00:00
/**
* @ name Title text filtering flags
* @ {
* Flags for use in drupal_set_title () .
*/
/**
* 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 );
/**
* @ } End of " Title text filtering flags " .
*/
2005-05-12 11:21:35 +00:00
/**
2006-05-07 00:08:36 +00:00
* Start the timer with the specified name . If you start and stop
2005-05-12 11:21:35 +00:00
* the same timer multiple times , the measured intervals will be
* accumulated .
*
* @ param name
* The name of the timer .
*/
function timer_start ( $name ) {
global $timers ;
2008-10-16 21:16:06 +00:00
$timers [ $name ][ 'start' ] = microtime ( TRUE );
2006-02-27 13:46:01 +00:00
$timers [ $name ][ 'count' ] = isset ( $timers [ $name ][ 'count' ]) ? ++ $timers [ $name ][ 'count' ] : 1 ;
2005-05-12 11:21:35 +00:00
}
/**
* 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 ;
2006-11-12 00:21:15 +00:00
if ( isset ( $timers [ $name ][ 'start' ])) {
2008-10-16 21:16:06 +00:00
$stop = microtime ( TRUE );
2006-11-12 00:21:15 +00:00
$diff = round (( $stop - $timers [ $name ][ 'start' ]) * 1000 , 2 );
2005-05-12 11:21:35 +00:00
2006-11-12 00:21:15 +00:00
if ( isset ( $timers [ $name ][ 'time' ])) {
$diff += $timers [ $name ][ 'time' ];
}
return $diff ;
2006-09-06 06:43:03 +00:00
}
2005-05-12 11:21:35 +00:00
}
/**
* Stop the timer with the specified name .
*
* @ param name
* The name of the timer .
* @ return
2006-05-07 00:08:36 +00:00
* A timer array . The array contains the number of times the
2005-05-12 11:21:35 +00:00
* timer has been started and stopped ( count ) and the accumulated
* timer value in ms ( time ) .
*/
function timer_stop ( $name ) {
global $timers ;
2006-01-23 07:54:08 +00:00
$timers [ $name ][ 'time' ] = timer_read ( $name );
2005-05-12 11:21:35 +00:00
unset ( $timers [ $name ][ 'start' ]);
return $timers [ $name ];
}
2005-01-09 09:22:40 +00:00
2004-07-13 07:21:14 +00:00
/**
2006-04-12 08:42:47 +00:00
* Find the appropriate configuration directory .
2004-07-13 07:21:14 +00:00
*
2005-11-21 21:33:44 +00:00
* Try finding a matching configuration directory by stripping the website ' s
* hostname from left to right and pathname from right to left . The first
2006-08-25 05:42:00 +00:00
* configuration file found will be used ; the remaining will ignored . If no
2005-11-21 21:33:44 +00:00
* configuration file is found , return a default value '$confdir/default' .
2004-11-24 22:44:01 +00:00
*
2005-03-31 21:18:08 +00:00
* Example for a fictitious site installed at
2005-11-21 21:33:44 +00:00
* http :// www . drupal . org : 8080 / mysite / test / the 'settings.php' is searched in
* the following directories :
2004-12-29 19:56:25 +00:00
*
2005-11-21 21:33:44 +00:00
* 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
2004-12-29 19:56:25 +00:00
*
2005-11-21 21:33:44 +00:00
* 5. $confdir / 8080. www . drupal . org . mysite
* 6. $confdir / www . drupal . org . mysite
* 7. $confdir / drupal . org . mysite
* 8. $confdir / org . mysite
2004-12-29 19:56:25 +00:00
*
2005-11-21 21:33:44 +00:00
* 9. $confdir / 8080. www . drupal . org
* 10. $confdir / www . drupal . org
* 11. $confdir / drupal . org
* 12. $confdir / org
2004-12-29 19:56:25 +00:00
*
2005-11-21 21:33:44 +00:00
* 13. $confdir / default
2007-07-30 19:22:47 +00:00
*
2008-10-12 02:47:50 +00:00
* If a file named sites . php is present in the $confdir , it will be loaded
* 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' ,
* '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
* 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 .
*
2007-07-30 19:22:47 +00:00
* @ 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 .
2004-07-13 07:21:14 +00:00
*/
2007-07-30 19:22:47 +00:00
function conf_path ( $require_settings = TRUE , $reset = FALSE ) {
2004-11-24 22:44:01 +00:00
static $conf = '' ;
2003-11-18 19:44:36 +00:00
2007-07-30 19:22:47 +00:00
if ( $conf && ! $reset ) {
2004-11-24 22:44:01 +00:00
return $conf ;
}
2003-11-18 19:44:36 +00:00
2004-12-29 19:56:25 +00:00
$confdir = 'sites' ;
2008-10-12 02:47:50 +00:00
$sites = array ();
if ( file_exists ( DRUPAL_ROOT . '/' . $confdir . '/sites.php' )) {
// This will overwrite $sites with the desired mappings.
include ( DRUPAL_ROOT . '/' . $confdir . '/sites.php' );
}
2007-08-30 15:53:39 +00:00
$uri = explode ( '/' , $_SERVER [ 'SCRIPT_NAME' ] ? $_SERVER [ 'SCRIPT_NAME' ] : $_SERVER [ 'SCRIPT_FILENAME' ]);
2005-11-21 16:24:41 +00:00
$server = explode ( '.' , implode ( '.' , array_reverse ( explode ( ':' , rtrim ( $_SERVER [ 'HTTP_HOST' ], '.' )))));
2004-11-24 22:44:01 +00:00
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 ));
2008-10-12 02:47:50 +00:00
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 ))) {
2004-11-24 22:44:01 +00:00
$conf = " $confdir / $dir " ;
return $conf ;
}
2003-11-18 19:44:36 +00:00
}
}
2004-11-24 22:44:01 +00:00
$conf = " $confdir /default " ;
return $conf ;
2003-11-18 19:44:36 +00:00
}
2006-04-21 06:39:00 +00:00
/**
2008-09-06 15:20:09 +00:00
* Initialize variables needed for the rest of the execution .
*/
function drupal_initialize_variables () {
if ( ! isset ( $_SERVER [ 'HTTP_REFERER' ])) {
$_SERVER [ 'HTTP_REFERER' ] = '' ;
2006-04-21 06:39:00 +00:00
}
2008-09-08 21:24:30 +00:00
if ( ! isset ( $_SERVER [ 'SERVER_PROTOCOL' ]) || ( $_SERVER [ 'SERVER_PROTOCOL' ] != 'HTTP/1.0' && $_SERVER [ 'SERVER_PROTOCOL' ] != 'HTTP/1.1' )) {
$_SERVER [ 'SERVER_PROTOCOL' ] = 'HTTP/1.0' ;
}
2008-10-15 16:05:51 +00:00
// Enforce E_ALL, but allow users to set levels not part of E_ALL.
error_reporting ( E_ALL | error_reporting ());
// Prevent PHP from generating HTML errors messages.
ini_set ( 'html_errors' , 0 );
2006-04-21 06:39:00 +00:00
}
2006-04-12 08:42:47 +00:00
/**
2007-04-30 14:37:36 +00:00
* Loads the configuration and sets the base URL , cookie domain , and
* session name correctly .
2006-04-12 08:42:47 +00:00
*/
function conf_init () {
2007-04-24 08:43:31 +00:00
global $base_url , $base_path , $base_root ;
2007-04-24 10:45:20 +00:00
// Export the following settings.php variables to the global namespace
2008-08-21 19:36:39 +00:00
global $databases , $db_prefix , $cookie_domain , $conf , $installed_profile , $update_free_access ;
2007-04-24 10:45:20 +00:00
$conf = array ();
2008-09-20 20:22:25 +00:00
if ( file_exists ( DRUPAL_ROOT . '/' . conf_path () . '/settings.php' )) {
include_once DRUPAL_ROOT . '/' . conf_path () . '/settings.php' ;
2007-05-08 16:36:55 +00:00
}
2006-04-12 08:42:47 +00:00
if ( isset ( $base_url )) {
// Parse fixed base URL from settings.php.
$parts = parse_url ( $base_url );
2006-05-02 08:37:42 +00:00
if ( ! isset ( $parts [ 'path' ])) {
$parts [ 'path' ] = '' ;
}
2008-04-14 17:48:46 +00:00
$base_path = $parts [ 'path' ] . '/' ;
2006-04-12 08:42:47 +00:00
// 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
$base_root = ( isset ( $_SERVER [ 'HTTPS' ]) && $_SERVER [ 'HTTPS' ] == 'on' ) ? 'https' : 'http' ;
2007-08-30 15:53:39 +00:00
// As $_SERVER['HTTP_HOST'] is user input, ensure it only contains
// characters allowed in hostnames.
2008-04-14 17:48:46 +00:00
$base_url = $base_root .= '://' . preg_replace ( '/[^a-z0-9-:._]/i' , '' , $_SERVER [ 'HTTP_HOST' ]);
2007-08-30 15:53:39 +00:00
// $_SERVER['SCRIPT_NAME'] can, in contrast to $_SERVER['PHP_SELF'], not
// be modified by a visitor.
if ( $dir = trim ( dirname ( $_SERVER [ 'SCRIPT_NAME' ]), '\,/' )) {
2006-04-12 08:42:47 +00:00
$base_path = " / $dir " ;
$base_url .= $base_path ;
$base_path .= '/' ;
}
else {
$base_path = '/' ;
}
}
2007-04-30 14:37:36 +00:00
if ( $cookie_domain ) {
// If the user specifies the cookie domain, also use it for session name.
$session_name = $cookie_domain ;
}
else {
2007-07-25 10:06:44 +00:00
// 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 );
2007-08-30 15:53:39 +00:00
// We escape the hostname because it can be modified by a visitor.
2007-04-30 14:37:36 +00:00
if ( ! empty ( $_SERVER [ 'HTTP_HOST' ])) {
2007-08-30 15:53:39 +00:00
$cookie_domain = check_plain ( $_SERVER [ 'HTTP_HOST' ]);
2007-04-30 14:37:36 +00:00
}
}
2008-08-18 18:56:01 +00:00
// 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 ( ini_get ( 'session.cookie_secure' )) {
$session_name .= 'SSL' ;
}
2007-04-30 14:37:36 +00:00
// 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 );
}
2007-06-09 07:26:36 +00:00
$cookie_domain = explode ( ':' , $cookie_domain );
2008-04-14 17:48:46 +00:00
$cookie_domain = '.' . $cookie_domain [ 0 ];
2007-04-30 14:37:36 +00:00
// 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 );
}
2008-04-14 17:48:46 +00:00
session_name ( 'SESS' . md5 ( $session_name ));
2006-04-12 08:42:47 +00:00
}
2004-11-25 06:14:59 +00:00
/**
* Returns and optionally sets the filename for a system item ( module ,
2006-05-07 00:08:36 +00:00
* theme , etc . ) . The filename , whether provided , cached , or retrieved
2004-11-25 06:14:59 +00:00
* from the database , is only returned if the file exists .
*
2006-11-24 10:16:50 +00:00
* 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 .
*
2004-11-25 06:14:59 +00:00
* @ param $type
* The type of the item ( i . e . theme , theme_engine , module ) .
* @ 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 .
*/
2006-11-24 10:16:50 +00:00
function drupal_get_filename ( $type , $name , $filename = NULL ) {
2004-11-25 06:14:59 +00:00
static $files = array ();
2005-10-22 15:14:46 +00:00
if ( ! isset ( $files [ $type ])) {
2004-11-25 06:14:59 +00:00
$files [ $type ] = array ();
}
2005-10-22 15:14:46 +00:00
if ( ! empty ( $filename ) && file_exists ( $filename )) {
2004-11-25 06:14:59 +00:00
$files [ $type ][ $name ] = $filename ;
}
2005-10-22 15:14:46 +00:00
elseif ( isset ( $files [ $type ][ $name ])) {
2004-11-25 06:14:59 +00:00
// nothing
}
2006-11-24 10:16:50 +00:00
// Verify that we have an active database connection, before querying
// 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.
2008-10-06 14:26:54 +00:00
elseif ( db_is_active () && (( $file = db_query ( " SELECT filename FROM { system} WHERE name = :name AND type = :type " , array ( ':name' => $name , ':type' => $type )) -> fetchField ()) && file_exists ( $file ))) {
2004-11-25 06:14:59 +00:00
$files [ $type ][ $name ] = $file ;
}
else {
2006-11-24 10:16:50 +00:00
// Fallback to searching the filesystem if the database connection is
// not established or the requested file is not found.
2006-04-12 20:58:09 +00:00
$config = conf_path ();
2004-11-25 06:14:59 +00:00
$dir = (( $type == 'theme_engine' ) ? 'themes/engines' : " ${ type } s " );
2005-03-16 19:41:12 +00:00
$file = (( $type == 'theme_engine' ) ? " $name .engine " : " $name . $type " );
2004-11-25 06:14:59 +00:00
foreach ( array ( " $config / $dir / $file " , " $config / $dir / $name / $file " , " $dir / $file " , " $dir / $name / $file " ) as $file ) {
if ( file_exists ( $file )) {
$files [ $type ][ $name ] = $file ;
break ;
}
}
}
2007-03-27 05:13:55 +00:00
if ( isset ( $files [ $type ][ $name ])) {
return $files [ $type ][ $name ];
}
2004-11-25 06:14:59 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* 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 .
*/
2003-11-18 19:44:36 +00:00
function variable_init ( $conf = array ()) {
2006-08-25 05:42:00 +00:00
// NOTE: caching the variables improves performance by 20% when serving cached pages.
2006-08-30 08:46:17 +00:00
if ( $cached = cache_get ( 'variables' , 'cache' )) {
2007-04-25 21:34:32 +00:00
$variables = $cached -> data ;
2004-09-08 18:06:04 +00:00
}
else {
2008-10-06 14:26:54 +00:00
$variables = array_map ( 'unserialize' , db_query ( 'SELECT name, value FROM {variable}' ) -> fetchAllKeyed ());
2007-04-25 21:34:32 +00:00
cache_set ( 'variables' , $variables );
2004-09-08 18:06:04 +00:00
}
foreach ( $conf as $name => $value ) {
$variables [ $name ] = $value ;
2003-11-18 19:44:36 +00:00
}
2004-09-08 18:06:04 +00:00
return $variables ;
2003-11-18 19:44:36 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Return a persistent variable .
*
* @ param $name
* The name of the variable to return .
* @ param $default
* The default value to use if this variable has never been set .
* @ return
* The value of the variable .
*/
2003-11-18 19:44:36 +00:00
function variable_get ( $name , $default ) {
global $conf ;
return isset ( $conf [ $name ]) ? $conf [ $name ] : $default ;
}
2004-07-13 07:21:14 +00:00
/**
* Set a persistent variable .
*
* @ 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 .
*/
2003-11-18 19:44:36 +00:00
function variable_set ( $name , $value ) {
global $conf ;
2008-08-21 19:36:39 +00:00
db_merge ( 'variable' ) -> key ( array ( 'name' => $name )) -> fields ( array ( 'value' => serialize ( $value ))) -> execute ();
2005-05-12 11:21:35 +00:00
2006-08-30 08:46:17 +00:00
cache_clear_all ( 'variables' , 'cache' );
2003-11-18 19:44:36 +00:00
$conf [ $name ] = $value ;
}
2004-07-13 07:21:14 +00:00
/**
* Unset a persistent variable .
*
* @ param $name
* The name of the variable to undefine .
*/
2003-11-18 19:44:36 +00:00
function variable_del ( $name ) {
global $conf ;
2008-10-06 14:26:54 +00:00
db_delete ( 'variable' )
-> condition ( 'name' , $name )
-> execute ();
2006-08-30 08:46:17 +00:00
cache_clear_all ( 'variables' , 'cache' );
2003-11-18 19:44:36 +00:00
unset ( $conf [ $name ]);
}
2007-03-26 01:32:22 +00:00
2004-07-13 07:21:14 +00:00
/**
* Retrieve the current page from the cache .
*
2006-08-25 05:42:00 +00:00
* Note : we do not serve cached pages when status messages are waiting ( from
2004-07-13 07:21:14 +00:00
* a redirected form submission which was completed ) .
*/
2003-11-18 19:44:36 +00:00
function page_get_cache () {
2006-04-12 08:42:47 +00:00
global $user , $base_root ;
2003-11-18 19:44:36 +00:00
$cache = NULL ;
2004-06-30 07:26:02 +00:00
2008-07-17 21:10:39 +00:00
if ( ! $user -> uid && ( $_SERVER [ 'REQUEST_METHOD' ] == 'GET' || $_SERVER [ 'REQUEST_METHOD' ] == 'HEAD' ) && count ( drupal_set_message ()) == 0 ) {
2006-08-30 08:46:17 +00:00
$cache = cache_get ( $base_root . request_uri (), 'cache_page' );
2003-11-18 19:44:36 +00:00
if ( empty ( $cache )) {
ob_start ();
}
}
return $cache ;
}
2004-11-25 06:14:59 +00:00
/**
* Call all init or exit hooks without including all modules .
*
2006-01-05 10:51:47 +00:00
* @ param $hook
2004-11-25 06:14:59 +00:00
* The name of the bootstrap hook we wish to invoke .
*/
2006-01-05 10:51:47 +00:00
function bootstrap_invoke_all ( $hook ) {
2006-06-28 21:18:30 +00:00
foreach ( module_list ( TRUE , TRUE ) as $module ) {
2006-01-05 10:51:47 +00:00
module_invoke ( $module , $hook );
2007-12-08 14:06:23 +00:00
}
2004-11-25 06:14:59 +00:00
}
/**
2006-05-07 00:08:36 +00:00
* Includes a file with the provided type and name . This prevents
2004-11-25 06:14:59 +00:00
* 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 ) {
static $files = array ();
2005-05-14 09:23:47 +00:00
if ( isset ( $files [ $type ][ $name ])) {
2004-11-25 06:14:59 +00:00
return TRUE ;
}
$filename = drupal_get_filename ( $type , $name );
if ( $filename ) {
2008-09-20 20:22:25 +00:00
include_once DRUPAL_ROOT . '/' . $filename ;
2004-11-25 06:14:59 +00:00
$files [ $type ][ $name ] = TRUE ;
return TRUE ;
}
return FALSE ;
}
2004-07-13 07:21:14 +00:00
/**
* Set HTTP headers in preparation for a page response .
2005-10-09 21:51:43 +00:00
*
2006-08-03 13:42:34 +00:00
* Authenticated users are always given a 'no-cache' header , and will
* fetch a fresh page on every request . This prevents authenticated
* users seeing locally cached pages that show them as logged out .
*
2008-01-08 10:35:43 +00:00
* @ see page_set_cache ()
2004-07-13 07:21:14 +00:00
*/
2003-11-18 19:44:36 +00:00
function drupal_page_header () {
2006-08-31 18:40:04 +00:00
header ( " Expires: Sun, 19 Nov 1978 05:00:00 GMT " );
2008-04-14 17:48:46 +00:00
header ( " Last-Modified: " . gmdate ( " D, d M Y H:i:s " ) . " GMT " );
2007-01-29 19:25:19 +00:00
header ( " Cache-Control: store, no-cache, must-revalidate " );
2006-08-31 18:40:04 +00:00
header ( " Cache-Control: post-check=0, pre-check=0 " , FALSE );
}
2004-02-15 15:57:55 +00:00
2006-08-31 18:40:04 +00:00
/**
* Set HTTP headers in preparation for a cached page response .
*
* The general approach here is that anonymous users can keep a local
* cache of the page , but must revalidate it on every request . Then ,
* they are given a '304 Not Modified' response as long as they stay
* logged out and the page has not been modified .
*
*/
function drupal_page_cache_header ( $cache ) {
// Set default values:
2008-04-14 17:48:46 +00:00
$last_modified = gmdate ( 'D, d M Y H:i:s' , $cache -> created ) . ' GMT' ;
$etag = '"' . md5 ( $last_modified ) . '"' ;
2006-08-31 18:40:04 +00:00
// See if the client has provided the required HTTP headers:
$if_modified_since = isset ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ]) ? stripslashes ( $_SERVER [ 'HTTP_IF_MODIFIED_SINCE' ]) : FALSE ;
$if_none_match = isset ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ]) ? stripslashes ( $_SERVER [ 'HTTP_IF_NONE_MATCH' ]) : FALSE ;
if ( $if_modified_since && $if_none_match
&& $if_none_match == $etag // etag must match
&& $if_modified_since == $last_modified ) { // if-modified-since must match
2008-09-08 21:24:30 +00:00
header ( $_SERVER [ 'SERVER_PROTOCOL' ] . ' 304 Not Modified' );
2006-08-31 18:40:04 +00:00
// All 304 responses must send an etag if the 200 response for the same object contained an etag
header ( " Etag: $etag " );
2008-10-11 04:56:34 +00:00
return ;
2006-08-31 18:40:04 +00:00
}
2006-08-03 13:42:34 +00:00
2006-08-31 18:40:04 +00:00
// Send appropriate response:
header ( " Last-Modified: $last_modified " );
header ( " ETag: $etag " );
2006-07-02 19:25:34 +00:00
2006-08-31 18:40:04 +00:00
// The following headers force validation of cache:
header ( " Expires: Sun, 19 Nov 1978 05:00:00 GMT " );
header ( " Cache-Control: must-revalidate " );
2006-07-02 19:25:34 +00:00
2007-10-25 15:38:25 +00:00
if ( variable_get ( 'page_compression' , TRUE )) {
// Determine if the browser accepts gzipped data.
if ( @ strpos ( $_SERVER [ 'HTTP_ACCEPT_ENCODING' ], 'gzip' ) === FALSE && function_exists ( 'gzencode' )) {
// Strip the gzip header and run uncompress.
$cache -> data = gzinflate ( substr ( substr ( $cache -> data , 10 ), 0 , - 8 ));
}
elseif ( function_exists ( 'gzencode' )) {
header ( 'Content-Encoding: gzip' );
}
2003-11-18 19:44:36 +00:00
}
2006-08-31 18:40:04 +00:00
// Send the original request's headers. We send them one after
// another so PHP's header() function can deal with duplicate
// headers.
$headers = explode ( " \n " , $cache -> headers );
foreach ( $headers as $header ) {
header ( $header );
}
print $cache -> data ;
2003-11-18 19:44:36 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Define the critical hooks that force modules to always be loaded .
*/
2003-11-18 19:44:36 +00:00
function bootstrap_hooks () {
2007-01-24 14:48:36 +00:00
return array ( 'boot' , 'exit' );
2003-11-18 19:44:36 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Unserializes and appends elements from a serialized string .
*
* @ param $obj
* The object to which the elements are appended .
* @ param $field
* The attribute of $obj whose value should be unserialized .
*/
2004-01-13 19:25:37 +00:00
function drupal_unpack ( $obj , $field = 'data' ) {
if ( $obj -> $field && $data = unserialize ( $obj -> $field )) {
foreach ( $data as $key => $value ) {
if ( ! isset ( $obj -> $key )) {
$obj -> $key = $value ;
}
}
}
return $obj ;
}
2005-11-29 20:37:19 +00:00
/**
* Encode special characters in a plain - text string for display as HTML .
2008-01-10 22:47:17 +00:00
*
* Uses drupal_validate_utf8 to prevent cross site scripting attacks on
* Internet Explorer 6.
2005-11-29 20:37:19 +00:00
*/
function check_plain ( $text ) {
2008-01-10 22:47:17 +00:00
return drupal_validate_utf8 ( $text ) ? htmlspecialchars ( $text , ENT_QUOTES ) : '' ;
}
/**
* Checks whether a string is valid UTF - 8.
*
* All functions designed to filter input should use drupal_validate_utf8
* to ensure they operate on valid UTF - 8 strings to prevent bypass of the
* filter .
*
* When text containing an invalid UTF - 8 lead byte ( 0xC0 - 0xFF ) is presented
* as UTF - 8 to Internet Explorer 6 , the program may misinterpret subsequent
* bytes . When these subsequent bytes are HTML control characters such as
* quotes or angle brackets , parts of the text that were deemed safe by filters
* end up in locations that are potentially unsafe ; An onerror attribute that
* is outside of a tag , and thus deemed safe by a filter , can be interpreted
* by the browser as if it were inside the tag .
*
* This function exploits preg_match behaviour ( since PHP 4.3 . 5 ) when used
* with the u modifier , as a fast way to find invalid UTF - 8. When the matched
* string contains an invalid byte sequence , it will fail silently .
*
* preg_match may not fail on 4 and 5 octet sequences , even though they
* are not supported by the specification .
*
* The specific preg_match behaviour is present since PHP 4.3 . 5.
*
* @ param $text
* The text to check .
* @ return
* TRUE if the text is valid UTF - 8 , FALSE if not .
*/
function drupal_validate_utf8 ( $text ) {
if ( strlen ( $text ) == 0 ) {
return TRUE ;
}
return ( preg_match ( '/^./us' , $text ) == 1 );
2005-11-29 20:37:19 +00:00
}
2004-07-13 07:21:14 +00:00
/**
2006-12-10 20:13:36 +00:00
* Since $_SERVER [ 'REQUEST_URI' ] is only available on Apache , we
* generate an equivalent using other environment variables .
2004-07-13 07:21:14 +00:00
*/
2003-11-18 19:44:36 +00:00
function request_uri () {
2006-12-10 20:13:36 +00:00
if ( isset ( $_SERVER [ 'REQUEST_URI' ])) {
$uri = $_SERVER [ 'REQUEST_URI' ];
}
else {
if ( isset ( $_SERVER [ 'argv' ])) {
2008-04-14 17:48:46 +00:00
$uri = $_SERVER [ 'SCRIPT_NAME' ] . '?' . $_SERVER [ 'argv' ][ 0 ];
2004-10-12 19:50:12 +00:00
}
2007-10-17 13:03:03 +00:00
elseif ( isset ( $_SERVER [ 'QUERY_STRING' ])) {
2008-04-14 17:48:46 +00:00
$uri = $_SERVER [ 'SCRIPT_NAME' ] . '?' . $_SERVER [ 'QUERY_STRING' ];
2004-10-12 19:50:12 +00:00
}
2007-10-17 13:03:03 +00:00
else {
$uri = $_SERVER [ 'SCRIPT_NAME' ];
}
2003-11-18 19:44:36 +00:00
}
2004-10-18 18:35:19 +00:00
2005-03-31 09:25:33 +00:00
return $uri ;
2003-11-18 19:44:36 +00:00
}
2003-12-13 14:10:23 +00:00
2004-07-13 07:21:14 +00:00
/**
* Log a system message .
*
* @ param $type
* The category to which this message belongs .
* @ param $message
2007-04-24 13:53:15 +00:00
* The message to store in the log . See t () for documentation
* on how $message and $variables interact . Keep $message
2007-04-24 15:53:53 +00:00
* translatable by not concatenating dynamic values into it !
2007-04-24 13:53:15 +00:00
* @ param $variables
* Array of variables to replace in the message on display or
* NULL if message is already translated or not possible to
* translate .
2005-01-09 09:22:40 +00:00
* @ param $severity
2007-04-10 10:10:27 +00:00
* The severity of the message , as per RFC 3164
2004-07-13 07:21:14 +00:00
* @ param $link
* A link to associate with the message .
2007-04-30 11:12:35 +00:00
*
2008-01-08 10:35:43 +00:00
* @ see watchdog_severity_levels ()
2004-07-13 07:21:14 +00:00
*/
2007-04-24 13:53:15 +00:00
function watchdog ( $type , $message , $variables = array (), $severity = WATCHDOG_NOTICE , $link = NULL ) {
2006-04-12 08:42:47 +00:00
global $user , $base_root ;
2006-03-26 14:11:38 +00:00
2008-08-21 19:36:39 +00:00
static $in_error_state = FALSE ;
// It is possible that the error handling will itself trigger an error. In that case, we could
// end up in an infinite loop. To avoid that, we implement a simple static semaphore.
if ( ! $in_error_state ) {
$in_error_state = TRUE ;
// Prepare the fields to be logged
$log_message = array (
'type' => $type ,
'message' => $message ,
'variables' => $variables ,
'severity' => $severity ,
'link' => $link ,
'user' => $user ,
'request_uri' => $base_root . request_uri (),
2008-09-06 08:36:22 +00:00
'referer' => $_SERVER [ 'HTTP_REFERER' ],
2008-08-21 19:36:39 +00:00
'ip' => ip_address (),
2008-09-17 07:11:59 +00:00
'timestamp' => REQUEST_TIME ,
2007-04-10 10:10:27 +00:00
);
2008-08-21 19:36:39 +00:00
// Call the logging hooks to log/process the message
foreach ( module_implements ( 'watchdog' , TRUE ) as $module ) {
module_invoke ( $module , 'watchdog' , $log_message );
}
2006-03-26 14:11:38 +00:00
}
2008-08-21 19:36:39 +00:00
$in_error_state = FALSE ;
2003-12-10 23:09:31 +00:00
}
2004-07-13 07:21:14 +00:00
/**
2005-05-14 18:32:22 +00:00
* Set a message which reflects the status of the performed operation .
2004-07-13 07:21:14 +00:00
*
2005-05-14 18:32:22 +00:00
* If the function is called with no arguments , this function returns all set
* messages without clearing them .
2004-07-13 07:21:14 +00:00
*
2005-05-14 18:32:22 +00:00
* @ param $message
* The message should begin with a capital letter and always ends with a
* period '.' .
* @ param $type
* The type of the message . One of the following values are possible :
* - 'status'
2007-10-17 12:11:30 +00:00
* - 'warning'
2005-05-14 18:32:22 +00:00
* - 'error'
2008-01-02 14:29:32 +00:00
* @ param $repeat
* If this is FALSE and the message is already set , then the message won ' t
* be repeated .
2004-07-13 07:21:14 +00:00
*/
2008-01-02 14:29:32 +00:00
function drupal_set_message ( $message = NULL , $type = 'status' , $repeat = TRUE ) {
2006-02-10 05:42:11 +00:00
if ( $message ) {
2004-07-08 16:04:07 +00:00
if ( ! isset ( $_SESSION [ 'messages' ])) {
$_SESSION [ 'messages' ] = array ();
}
if ( ! isset ( $_SESSION [ 'messages' ][ $type ])) {
$_SESSION [ 'messages' ][ $type ] = array ();
}
2008-01-02 14:29:32 +00:00
if ( $repeat || ! in_array ( $message , $_SESSION [ 'messages' ][ $type ])) {
$_SESSION [ 'messages' ][ $type ][] = $message ;
}
2004-06-28 20:00:53 +00:00
}
2005-10-22 15:14:46 +00:00
// messages not set when DB connection fails
return isset ( $_SESSION [ 'messages' ]) ? $_SESSION [ 'messages' ] : NULL ;
2004-06-28 20:00:53 +00:00
}
2004-07-13 07:21:14 +00:00
/**
* Return all messages that have been set .
*
2006-07-13 13:14:25 +00:00
* @ param $type
* ( optional ) Only return messages of this type .
2006-09-07 07:11:15 +00:00
* @ param $clear_queue
* ( optional ) Set to FALSE if you do not want to clear the messages queue
2007-04-04 20:50:53 +00:00
* @ return
* An associative array , the key is the message type , the value an array
* of messages . If the $type parameter is passed , you get only that type ,
* or an empty array if there are no such messages . If $type is not passed ,
* all message types are returned , or an empty array if none exist .
2004-07-13 07:21:14 +00:00
*/
2006-09-07 07:11:15 +00:00
function drupal_get_messages ( $type = NULL , $clear_queue = TRUE ) {
2006-04-01 14:53:03 +00:00
if ( $messages = drupal_set_message ()) {
2006-07-13 13:14:25 +00:00
if ( $type ) {
2006-09-07 07:11:15 +00:00
if ( $clear_queue ) {
2007-12-08 14:06:23 +00:00
unset ( $_SESSION [ 'messages' ][ $type ]);
2006-09-07 07:11:15 +00:00
}
2007-04-04 20:50:53 +00:00
if ( isset ( $messages [ $type ])) {
return array ( $type => $messages [ $type ]);
}
2006-07-13 13:14:25 +00:00
}
else {
2006-09-07 07:11:15 +00:00
if ( $clear_queue ) {
2007-12-08 14:06:23 +00:00
unset ( $_SESSION [ 'messages' ]);
2006-09-07 07:11:15 +00:00
}
2006-07-13 13:14:25 +00:00
return $messages ;
}
2006-04-01 14:53:03 +00:00
}
2006-07-13 13:14:25 +00:00
return array ();
2004-06-28 20:00:53 +00:00
}
2005-06-07 18:54:37 +00:00
/**
2008-04-08 22:50:55 +00:00
* Check to see if an IP address has been blocked .
*
* Blocked IP addresses are stored in the database by default . However for
* performance reasons we allow an override in settings . php . This allows us
* to avoid querying the database at this critical stage of the bootstrap if
* an administrative interface for IP address blocking is not required .
*
* @ param $ip string
* IP address to check .
2006-08-29 08:36:14 +00:00
* @ return bool
* TRUE if access is denied , FALSE if access is allowed .
2005-06-07 18:54:37 +00:00
*/
2008-04-08 22:50:55 +00:00
function drupal_is_denied ( $ip ) {
// Because this function is called on every page request, we first check
// for an array of IP addresses in settings.php before querying the
// database.
$blocked_ips = variable_get ( 'blocked_ips' , NULL );
if ( isset ( $blocked_ips ) && is_array ( $blocked_ips )) {
return in_array ( $ip , $blocked_ips );
}
else {
2008-10-06 14:26:54 +00:00
return ( bool ) db_query ( " SELECT 1 FROM { blocked_ips} WHERE ip = :ip " , array ( ':ip' => $ip )) -> fetchField ();
2008-04-08 22:50:55 +00:00
}
2005-06-07 18:54:37 +00:00
}
2006-08-16 13:13:34 +00:00
/**
2006-08-25 05:42:00 +00:00
* Generates a default anonymous $user object .
2006-08-16 13:13:34 +00:00
*
* @ return Object - the user object .
*/
2006-08-18 19:24:52 +00:00
function drupal_anonymous_user ( $session = '' ) {
2006-08-16 13:13:34 +00:00
$user = new stdClass ();
$user -> uid = 0 ;
2007-05-25 15:04:42 +00:00
$user -> hostname = ip_address ();
2006-08-16 13:13:34 +00:00
$user -> roles = array ();
$user -> roles [ DRUPAL_ANONYMOUS_RID ] = 'anonymous user' ;
2006-08-18 19:24:52 +00:00
$user -> session = $session ;
2007-03-25 20:54:33 +00:00
$user -> cache = 0 ;
2006-08-16 13:13:34 +00:00
return $user ;
}
2005-06-22 20:19:58 +00:00
/**
* A string describing a phase of Drupal to load . Each phase adds to the
* previous one , so invoking a later phase automatically runs the earlier
2006-08-25 05:42:00 +00:00
* phases too . The most important usage is that if you want to access the
2005-06-22 20:19:58 +00:00
* Drupal database from a script without loading anything else , you can
2005-07-23 05:57:27 +00:00
* include bootstrap . inc , and call drupal_bootstrap ( DRUPAL_BOOTSTRAP_DATABASE ) .
2005-06-22 20:19:58 +00:00
*
* @ param $phase
2005-07-23 05:57:27 +00:00
* A constant . Allowed values are :
2006-08-25 05:42:00 +00:00
* DRUPAL_BOOTSTRAP_CONFIGURATION : initialize configuration .
* DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE : try to call a non - database cache fetch routine .
2005-07-23 05:57:27 +00:00
* DRUPAL_BOOTSTRAP_DATABASE : initialize database layer .
2006-12-06 16:14:11 +00:00
* DRUPAL_BOOTSTRAP_ACCESS : identify and reject banned hosts .
2005-07-23 05:57:27 +00:00
* DRUPAL_BOOTSTRAP_SESSION : initialize session handling .
2006-06-14 14:01:12 +00:00
* DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE : load bootstrap . inc and module . inc , start
2005-07-23 05:57:27 +00:00
* the variable system and try to serve a page from the cache .
2007-03-26 01:32:22 +00:00
* DRUPAL_BOOTSTRAP_LANGUAGE : identify the language used on the page .
2006-12-06 16:14:11 +00:00
* DRUPAL_BOOTSTRAP_PATH : set $_GET [ 'q' ] to Drupal path of request .
2006-08-25 05:42:00 +00:00
* DRUPAL_BOOTSTRAP_FULL : Drupal is fully loaded , validate and fix input data .
2005-06-22 20:19:58 +00:00
*/
2008-10-19 21:27:13 +00:00
function drupal_bootstrap ( $phase = NULL ) {
static $phases = array ( DRUPAL_BOOTSTRAP_CONFIGURATION , DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE , DRUPAL_BOOTSTRAP_DATABASE , DRUPAL_BOOTSTRAP_ACCESS , DRUPAL_BOOTSTRAP_SESSION , DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE , DRUPAL_BOOTSTRAP_LANGUAGE , DRUPAL_BOOTSTRAP_PATH , DRUPAL_BOOTSTRAP_FULL ), $completed_phase = - 1 ;
if ( isset ( $phase ) && $phase > $completed_phase ) {
while ( $phases ) {
$current_phase = array_shift ( $phases );
_drupal_bootstrap ( $current_phase );
$completed_phase = $current_phase ;
}
2005-06-22 20:19:58 +00:00
}
2008-10-19 21:27:13 +00:00
return $completed_phase ;
2005-06-22 20:19:58 +00:00
}
2005-06-07 18:54:37 +00:00
2008-08-21 19:36:39 +00:00
/**
* Return the current bootstrap phase for this Drupal process . The
* current phase is the one most recently completed by
* drupal_bootstrap () .
*
* @ see drupal_bootstrap
*/
function drupal_get_bootstrap_phase () {
2008-10-19 21:27:13 +00:00
return drupal_bootstrap ();
2008-08-21 19:36:39 +00:00
}
2005-06-22 20:19:58 +00:00
function _drupal_bootstrap ( $phase ) {
global $conf ;
2003-11-18 19:44:36 +00:00
2005-06-22 20:19:58 +00:00
switch ( $phase ) {
2006-08-31 18:40:04 +00:00
2006-06-14 14:01:12 +00:00
case DRUPAL_BOOTSTRAP_CONFIGURATION :
2008-09-06 15:20:09 +00:00
drupal_initialize_variables ();
2007-10-24 11:30:39 +00:00
// Start a page timer:
timer_start ( 'page' );
2006-04-12 08:42:47 +00:00
// Initialize the configuration
conf_init ();
2006-06-14 14:01:12 +00:00
break ;
2006-08-31 18:40:04 +00:00
2006-06-14 14:01:12 +00:00
case DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE :
2007-10-24 11:30:39 +00:00
// Allow specifying special cache handlers in settings.php, like
// using memcached or files for storing cache information.
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/' . variable_get ( 'cache_inc' , 'includes/cache.inc' );
2007-10-24 11:30:39 +00:00
// If the page_cache_fastpath is set to TRUE in settings.php and
// page_cache_fastpath (implemented in the special implementation of
// cache.inc) printed the page and indicated this with a returned TRUE
// then we are done.
if ( variable_get ( 'page_cache_fastpath' , FALSE ) && page_cache_fastpath ()) {
exit ;
}
2006-06-14 14:01:12 +00:00
break ;
2006-08-31 18:40:04 +00:00
2006-06-14 14:01:12 +00:00
case DRUPAL_BOOTSTRAP_DATABASE :
2008-08-21 19:36:39 +00:00
// Initialize the database system. Note that the connection
// won't be initialized until it is actually requested.
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/database/database.inc' ;
2008-05-06 12:18:54 +00:00
// Register autoload functions so that we can access classes and interfaces.
spl_autoload_register ( 'drupal_autoload_class' );
spl_autoload_register ( 'drupal_autoload_interface' );
2005-06-22 20:19:58 +00:00
break ;
2005-07-23 05:57:27 +00:00
2006-09-06 07:53:01 +00:00
case DRUPAL_BOOTSTRAP_ACCESS :
2008-04-08 22:50:55 +00:00
// Deny access to blocked IP addresses - t() is not yet available.
if ( drupal_is_denied ( ip_address ())) {
2008-09-08 21:24:30 +00:00
header ( $_SERVER [ 'SERVER_PROTOCOL' ] . ' 403 Forbidden' );
2008-04-14 17:48:46 +00:00
print 'Sorry, ' . check_plain ( ip_address ()) . ' has been banned.' ;
2006-09-06 07:53:01 +00:00
exit ();
}
break ;
2005-07-23 05:57:27 +00:00
case DRUPAL_BOOTSTRAP_SESSION :
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/' . variable_get ( 'session_inc' , 'includes/session.inc' );
2008-09-15 15:18:59 +00:00
session_set_save_handler ( '_sess_open' , '_sess_close' , '_sess_read' , '_sess_write' , '_sess_destroy_sid' , '_sess_gc' );
2005-06-22 20:19:58 +00:00
session_start ();
break ;
2005-07-23 05:57:27 +00:00
2006-06-14 14:01:12 +00:00
case DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE :
2006-08-31 18:40:04 +00:00
// Initialize configuration variables, using values from settings.php if available.
$conf = variable_init ( isset ( $conf ) ? $conf : array ());
2007-10-24 11:30:39 +00:00
// Load module handling.
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/module.inc' ;
2007-10-24 11:30:39 +00:00
$cache_mode = variable_get ( 'cache' , CACHE_DISABLED );
// Get the page from the cache.
$cache = $cache_mode == CACHE_DISABLED ? '' : page_get_cache ();
// If the skipping of the bootstrap hooks is not enforced, call hook_boot.
if ( $cache_mode != CACHE_AGGRESSIVE ) {
bootstrap_invoke_all ( 'boot' );
}
// If there is a cached page, display it.
if ( $cache ) {
drupal_page_cache_header ( $cache );
// If the skipping of the bootstrap hooks is not enforced, call hook_exit.
if ( $cache_mode != CACHE_AGGRESSIVE ) {
bootstrap_invoke_all ( 'exit' );
}
// We are done.
exit ;
}
// Prepare for non-cached page workflow.
2005-06-22 20:19:58 +00:00
drupal_page_header ();
break ;
2005-07-23 05:57:27 +00:00
2007-03-26 01:32:22 +00:00
case DRUPAL_BOOTSTRAP_LANGUAGE :
drupal_init_language ();
break ;
2006-01-23 07:54:08 +00:00
case DRUPAL_BOOTSTRAP_PATH :
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/path.inc' ;
2006-01-23 07:54:08 +00:00
// Initialize $_GET['q'] prior to loading modules and invoking hook_init().
drupal_init_path ();
break ;
2005-07-23 05:57:27 +00:00
case DRUPAL_BOOTSTRAP_FULL :
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/common.inc' ;
2005-06-22 20:19:58 +00:00
_drupal_bootstrap_full ();
break ;
}
2005-06-07 18:54:37 +00:00
}
2005-07-27 01:58:43 +00:00
/**
2007-11-30 12:19:10 +00:00
* Enables use of the theme system without requiring database access .
*
* Loads and initializes the theme system for site installs , updates and when
2008-07-01 20:36:40 +00:00
* the site is in offline mode . This also applies when the database fails .
2007-11-30 12:19:10 +00:00
*
* @ see _drupal_maintenance_theme ()
2005-07-27 01:58:43 +00:00
*/
function drupal_maintenance_theme () {
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/theme.maintenance.inc' ;
2007-11-30 12:19:10 +00:00
_drupal_maintenance_theme ();
2005-07-27 01:58:43 +00:00
}
2006-09-01 08:44:53 +00:00
/**
* Return the name of the localisation function . Use in code that needs to
* run both during installation and normal operation .
*/
function get_t () {
static $t ;
if ( is_null ( $t )) {
$t = function_exists ( 'install_main' ) ? 'st' : 't' ;
}
return $t ;
}
2007-03-26 01:32:22 +00:00
/**
* Choose a language for the current page , based on site and user preferences .
*/
function drupal_init_language () {
global $language , $user ;
// Ensure the language is correctly returned, even without multilanguage support.
// Useful for eg. XML/HTML 'lang' attributes.
if ( variable_get ( 'language_count' , 1 ) == 1 ) {
$language = language_default ();
}
else {
2008-09-20 20:22:25 +00:00
include_once DRUPAL_ROOT . '/includes/language.inc' ;
2007-03-26 01:32:22 +00:00
$language = language_initialize ();
}
}
/**
* Get a list of languages set up indexed by the specified key
*
* @ param $field The field to index the list with .
* @ param $reset Boolean to request a reset of the list .
*/
function language_list ( $field = 'language' , $reset = FALSE ) {
static $languages = NULL ;
// Reset language list
if ( $reset ) {
$languages = NULL ;
}
// Init language list
if ( ! isset ( $languages )) {
2007-09-07 10:33:06 +00:00
if ( variable_get ( 'language_count' , 1 ) > 1 || module_exists ( 'locale' )) {
2008-10-06 14:26:54 +00:00
$languages [ 'language' ] = db_query ( 'SELECT * FROM {languages} ORDER BY weight ASC, name ASC' ) -> fetchAllAssoc ( 'language' );
2007-07-01 19:49:19 +00:00
}
else {
2007-09-01 12:50:47 +00:00
// No locale module, so use the default language only.
2007-07-01 19:49:19 +00:00
$default = language_default ();
$languages [ 'language' ][ $default -> language ] = $default ;
2007-03-26 01:32:22 +00:00
}
}
// Return the array indexed by the right field
if ( ! isset ( $languages [ $field ])) {
$languages [ $field ] = array ();
2007-04-13 08:56:59 +00:00
foreach ( $languages [ 'language' ] as $lang ) {
2007-03-26 01:32:22 +00:00
// Some values should be collected into an array
if ( in_array ( $field , array ( 'enabled' , 'weight' ))) {
$languages [ $field ][ $lang -> $field ][ $lang -> language ] = $lang ;
}
else {
$languages [ $field ][ $lang -> $field ] = $lang ;
}
}
}
return $languages [ $field ];
}
/**
* Default language used on the site
2007-05-30 08:08:59 +00:00
*
2007-05-29 14:37:49 +00:00
* @ param $property
* Optional property of the language object to return
2007-03-26 01:32:22 +00:00
*/
2007-05-29 14:37:49 +00:00
function language_default ( $property = NULL ) {
2007-11-11 16:14:45 +00:00
$language = variable_get ( 'language_default' , ( object ) array ( 'language' => 'en' , 'name' => 'English' , 'native' => 'English' , 'direction' => 0 , 'enabled' => 1 , 'plurals' => 0 , 'formula' => '' , 'domain' => '' , 'prefix' => '' , 'weight' => 0 , 'javascript' => '' ));
2007-05-29 14:37:49 +00:00
return $property ? $language -> $property : $language ;
2007-03-26 01:32:22 +00:00
}
2007-05-25 15:04:42 +00:00
/**
* If Drupal is behind a reverse proxy , we use the X - Forwarded - For header
2008-07-02 20:05:11 +00:00
* instead of $_SERVER [ 'REMOTE_ADDR' ], which would be the IP address of
2008-06-26 11:29:20 +00:00
* the proxy server , and not the client ' s . If Drupal is run in a cluster
* we use the X - Cluster - Client - Ip header instead .
2007-05-25 15:04:42 +00:00
*
2008-06-26 11:29:20 +00:00
* @ param $reset
* Reset the current IP address saved in static .
2007-05-25 15:04:42 +00:00
* @ return
2008-06-26 11:29:20 +00:00
* IP address of client machine , adjusted for reverse proxy and / or cluster
* environments .
2007-05-25 15:04:42 +00:00
*/
2008-09-19 07:53:59 +00:00
function ip_address ( $reset = FALSE ) {
2007-07-29 21:04:03 +00:00
static $ip_address = NULL ;
2007-05-25 15:04:42 +00:00
2008-06-26 11:29:20 +00:00
if ( ! isset ( $ip_address ) || $reset ) {
2007-07-29 21:04:03 +00:00
$ip_address = $_SERVER [ 'REMOTE_ADDR' ];
2008-07-08 01:08:15 +00:00
2008-07-04 22:54:09 +00:00
if ( variable_get ( 'reverse_proxy' , 0 )) {
if ( array_key_exists ( 'HTTP_X_FORWARDED_FOR' , $_SERVER )) {
// If an array of known reverse proxy IPs is provided, then trust
// the XFF header if request really comes from one of them.
$reverse_proxy_addresses = variable_get ( 'reverse_proxy_addresses' , array ());
if ( ! empty ( $reverse_proxy_addresses ) && in_array ( $ip_address , $reverse_proxy_addresses , TRUE )) {
// If there are several arguments, we need to check the most
// recently added one, i.e. the last one.
2008-10-12 08:37:14 +00:00
$ip_address_parts = explode ( ',' , $_SERVER [ 'HTTP_X_FORWARDED_FOR' ]);
$ip_address = array_pop ( $ip_address_parts );
2008-07-04 22:54:09 +00:00
}
2007-11-26 08:06:52 +00:00
}
2008-06-26 11:29:20 +00:00
2008-07-04 22:54:09 +00:00
// When Drupal is run in a cluster environment, REMOTE_ADDR contains the IP
// address of a server in the cluster, while the IP address of the client is
// stored in HTTP_X_CLUSTER_CLIENT_IP.
if ( array_key_exists ( 'HTTP_X_CLUSTER_CLIENT_IP' , $_SERVER )) {
$ip_address = $_SERVER [ 'HTTP_X_CLUSTER_CLIENT_IP' ];
}
2008-06-26 11:29:20 +00:00
}
2007-05-25 15:04:42 +00:00
}
2007-07-29 17:28:23 +00:00
2007-07-29 21:04:03 +00:00
return $ip_address ;
2007-05-25 15:04:42 +00:00
}
2008-05-06 12:18:54 +00:00
2008-08-21 19:36:39 +00:00
/**
* @ ingroup schemaapi
* @ {
*/
/**
* Get the schema definition of a table , or the whole database schema .
*
* The returned schema will include any modifications made by any
* module that implements hook_schema_alter () .
*
* @ param $table
* The name of the table . If not given , the schema of all tables is returned .
* @ param $rebuild
* If true , the schema will be rebuilt instead of retrieved from the cache .
*/
function drupal_get_schema ( $table = NULL , $rebuild = FALSE ) {
static $schema = array ();
if ( empty ( $schema ) || $rebuild ) {
// Try to load the schema from cache.
if ( ! $rebuild && $cached = cache_get ( 'schema' )) {
$schema = $cached -> data ;
}
// Otherwise, rebuild the schema cache.
else {
$schema = array ();
// Load the .install files to get hook_schema.
// On some databases this function may be called before bootstrap has
// been completed, so we force the functions we need to load just in case.
if ( drupal_function_exists ( 'module_load_all_includes' )) {
// There is currently a bug in module_list() where it caches what it
// was last called with, which is not always what you want.
// module_load_all_includes() calls module_list(), but if this function
// is called very early in the bootstrap process then it will be
// uninitialized and therefore return no modules. Instead, we have to
// "prime" module_list() here to to values we want, specifically
// "yes rebuild the list and don't limit to bootstrap".
// TODO: Remove this call after http://drupal.org/node/222109 is fixed.
module_list ( TRUE , FALSE );
module_load_all_includes ( 'install' );
}
// Invoke hook_schema for all modules.
foreach ( module_implements ( 'schema' ) as $module ) {
$current = module_invoke ( $module , 'schema' );
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/common.inc' ;
2008-08-21 19:36:39 +00:00
if ( drupal_function_exists ( '_drupal_initialize_schema' )) {
_drupal_initialize_schema ( $module , $current );
}
$schema = array_merge ( $schema , $current );
}
if ( drupal_function_exists ( 'drupal_alter' )) {
drupal_alter ( 'schema' , $schema );
}
if ( drupal_get_bootstrap_phase () == DRUPAL_BOOTSTRAP_FULL ) {
cache_set ( 'schema' , $schema );
}
}
}
if ( ! isset ( $table )) {
return $schema ;
}
elseif ( isset ( $schema [ $table ])) {
return $schema [ $table ];
}
else {
return FALSE ;
}
}
/**
* @ } End of " ingroup schemaapi " .
*/
2008-05-06 12:18:54 +00:00
/**
* @ ingroup registry
* @ {
*/
/**
* Confirm that a function is available .
*
* If the function is already available , this function does nothing .
* If the function is not available , it tries to load the file where the
* function lives . If the file is not available , it returns false , so that it
* can be used as a drop - in replacement for function_exists () .
*
* @ param $function
* The name of the function to check or load .
* @ return
* TRUE if the function is now available , FALSE otherwise .
*/
function drupal_function_exists ( $function ) {
static $checked = array ();
if ( defined ( 'MAINTENANCE_MODE' )) {
return function_exists ( $function );
}
if ( isset ( $checked [ $function ])) {
return $checked [ $function ];
}
$checked [ $function ] = FALSE ;
if ( function_exists ( $function )) {
registry_mark_code ( 'function' , $function );
$checked [ $function ] = TRUE ;
return TRUE ;
}
2008-10-06 14:26:54 +00:00
$file = db_query ( " SELECT filename FROM { registry} WHERE name = :name AND type = :type " , array (
':name' => $function ,
':type' => 'function' ,
))
-> fetchField ();
2008-05-06 12:18:54 +00:00
if ( $file ) {
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/' . $file ;
2008-05-06 12:18:54 +00:00
$checked [ $function ] = function_exists ( $function );
if ( $checked [ $function ]) {
registry_mark_code ( 'function' , $function );
}
}
return $checked [ $function ];
}
/**
* Confirm that an interface is available .
*
* This function parallels drupal_function_exists (), but is rarely
* called directly . Instead , it is registered as an spl_autoload ()
* handler , and PHP calls it for us when necessary .
*
* @ param $interface
* The name of the interface to check or load .
* @ return
* TRUE if the interface is currently available , FALSE otherwise .
*/
function drupal_autoload_interface ( $interface ) {
return _registry_check_code ( 'interface' , $interface );
}
/**
* Confirm that a class is available .
*
* This function parallels drupal_function_exists (), but is rarely
* called directly . Instead , it is registered as an spl_autoload ()
* handler , and PHP calls it for us when necessary .
*
* @ param $class
* The name of the class to check or load .
* @ return
* TRUE if the class is currently available , FALSE otherwise .
*/
function drupal_autoload_class ( $class ) {
return _registry_check_code ( 'class' , $class );
}
/**
* Helper for registry_check_ { interface , class } .
*/
function _registry_check_code ( $type , $name ) {
2008-10-06 14:26:54 +00:00
$file = db_query ( " SELECT filename FROM { registry} WHERE name = :name AND type = :type " , array (
':name' => $name ,
':type' => $type ,
))
-> fetchField ();
2008-05-06 12:18:54 +00:00
if ( $file ) {
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/' . $file ;
2008-05-06 12:18:54 +00:00
registry_mark_code ( $type , $name );
return TRUE ;
}
}
/**
* Collect the resources used for this request .
*
* @ param $type
* The type of resource .
* @ param $name
* The name of the resource .
* @ param $return
* Boolean flag to indicate whether to return the resources .
*/
function registry_mark_code ( $type , $name , $return = FALSE ) {
static $resources = array ();
if ( $type && $name ) {
if ( ! isset ( $resources [ $type ])) {
$resources [ $type ] = array ();
}
if ( ! in_array ( $name , $resources [ $type ])) {
$resources [ $type ][] = $name ;
}
}
if ( $return ) {
return $resources ;
}
}
/**
* Rescan all enabled modules and rebuild the registry .
*
* Rescans all code in modules or includes directory , storing a mapping of
* each function , file , and hook implementation in the database .
*/
2008-08-02 19:01:02 +00:00
function registry_rebuild () {
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/registry.inc' ;
2008-08-02 19:01:02 +00:00
_registry_rebuild ();
2008-05-06 12:18:54 +00:00
}
/**
* Save hook implementations cache .
*
* @ param $hook
* Array with the hook name and list of modules that implement it .
* @ param $write_to_persistent_cache
* Whether to write to the persistent cache .
*/
function registry_cache_hook_implementations ( $hook , $write_to_persistent_cache = FALSE ) {
static $implementations ;
if ( $hook ) {
// Newer is always better, so overwrite anything that's come before.
$implementations [ $hook [ 'hook' ]] = $hook [ 'modules' ];
}
if ( $write_to_persistent_cache === TRUE ) {
2008-05-13 17:38:42 +00:00
// Only write this to cache if the implementations data we are going to cache
// is different to what we loaded earlier in the request.
2008-08-21 19:36:39 +00:00
if ( $implementations != module_implements ()) {
2008-05-13 17:38:42 +00:00
cache_set ( 'hooks' , $implementations , 'cache_registry' );
}
2008-05-06 12:18:54 +00:00
}
}
/**
* Save the files required by the registry for this path .
*/
function registry_cache_path_files () {
if ( $used_code = registry_mark_code ( NULL , NULL , TRUE )) {
$files = array ();
$type_sql = array ();
$params = array ();
2008-10-06 14:26:54 +00:00
$select = db_select ( 'registry' ) -> distinct ();
$select -> addField ( 'registry' , 'filename' );
// This creates a series of 2-clause AND conditions that are then ORed together.
$ors = db_or ();
2008-05-06 12:18:54 +00:00
foreach ( $used_code as $type => $names ) {
2008-10-06 14:26:54 +00:00
$and = db_and ()
-> condition ( 'name' , $names , 'IN' )
-> condition ( 'type' , $type );
$ors -> condition ( $and );
2008-05-06 12:18:54 +00:00
}
2008-10-06 14:26:54 +00:00
$select -> condition ( $ors );
$files = $select -> execute () -> fetchCol ();
2008-05-06 12:18:54 +00:00
if ( $files ) {
2008-05-13 17:38:42 +00:00
sort ( $files );
// Only write this to cache if the file list we are going to cache
// is different to what we loaded earlier in the request.
if ( $files != registry_load_path_files ( TRUE )) {
$menu = menu_get_item ();
cache_set ( 'registry:' . $menu [ 'path' ], implode ( ';' , $files ), 'cache_registry' );
}
}
}
}
/**
* registry_load_path_files
*/
function registry_load_path_files ( $return = FALSE ) {
static $file_cache_data = array ();
if ( $return ) {
sort ( $file_cache_data );
return $file_cache_data ;
}
$menu = menu_get_item ();
$cache = cache_get ( 'registry:' . $menu [ 'path' ], 'cache_registry' );
if ( ! empty ( $cache -> data )) {
foreach ( explode ( ';' , $cache -> data ) as $file ) {
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/' . $file ;
2008-05-13 17:38:42 +00:00
$file_cache_data [] = $file ;
2008-05-06 12:18:54 +00:00
}
}
}
/**
* @ } End of " ingroup registry " .
*/