bootstrap.inc

  1. drupal
    1. 4.6 includes/bootstrap.inc
    2. 4.7 includes/bootstrap.inc
    3. 5 includes/bootstrap.inc
    4. 6 includes/bootstrap.inc
    5. 7 includes/bootstrap.inc
    6. 8 core/includes/bootstrap.inc

Functions that need to be loaded on every Drupal request.

Functions & methods

NameDescription
bootstrap_hooksDefine the critical hooks that force modules to always be loaded.
bootstrap_invoke_allCall all init or exit hooks without including all modules.
cache_clear_allExpire data from the cache.
cache_getReturn data from the persistent cache.
cache_setStore data in the persistent cache.
check_plainEncode special characters in a plain-text string for display as HTML.
conf_initLoads the configuration and sets the base URL correctly.
conf_pathFind the appropriate configuration directory.
drupal_bootstrapA string describing a phase of Drupal to load. Each phase adds to the previous one, so invoking a later phase automatically runs the earlier phases too. The most important usage is that if you want to access Drupal database from a script without…
drupal_get_filenameReturns 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.
drupal_get_messagesReturn all messages that have been set.
drupal_is_deniedPerform an access check for a given mask and rule type. Rules are usually created via admin/access/rules page.
drupal_loadIncludes a file with the provided type and name. This prevents including a theme, engine, module, etc., more than once.
drupal_maintenance_themeEnables use of the theme system without requiring database access. Since there is not database access no theme will be enabled and the default themeable functions will be called. Some themeable functions can not be used without the full Drupal API…
drupal_page_headerSet HTTP headers in preparation for a page response.
drupal_set_messageSet a message which reflects the status of the performed operation.
drupal_unpackUnserializes and appends elements from a serialized string.
drupal_unset_globalsUnsets all disallowed global variables. See $allowed for what's allowed.
drupal_validate_utf8Checks whether a string is valid UTF-8.
page_get_cacheRetrieve the current page from the cache.
referer_uriReturn the URI of the referring page.
request_uriSince request_uri() is only available on Apache, we generate an equivalent using other environment variables.
timer_readRead the current timer value without stopping the timer.
timer_startStart the timer with the specified name. If you start and stop the same timer multiple times, the measured intervals will be accumulated.
timer_stopStop the timer with the specified name.
variable_delUnset a persistent variable.
variable_getReturn a persistent variable.
variable_initLoad the persistent variable table.
variable_setSet a persistent variable.
watchdogLog a system message.
_drupal_bootstrap

Constants

NameDescription
CACHE_DISABLED
CACHE_ENABLED
CACHE_PERMANENT
CACHE_TEMPORARY
DRUPAL_ANONYMOUS_RID
DRUPAL_AUTHENTICATED_RID
DRUPAL_BOOTSTRAP_DATABASE
DRUPAL_BOOTSTRAP_FULL
DRUPAL_BOOTSTRAP_PAGE_CACHE
DRUPAL_BOOTSTRAP_PATH
DRUPAL_BOOTSTRAP_SESSION
WATCHDOG_ERROR
WATCHDOG_NOTICE
WATCHDOG_WARNING

File

includes/bootstrap.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. * Functions that need to be loaded on every Drupal request.
  5. */
  6. define('CACHE_PERMANENT', 0);
  7. define('CACHE_TEMPORARY', -1);
  8. define('CACHE_DISABLED', 0);
  9. define('CACHE_ENABLED', 1);
  10. define('WATCHDOG_NOTICE', 0);
  11. define('WATCHDOG_WARNING', 1);
  12. define('WATCHDOG_ERROR', 2);
  13. define('DRUPAL_BOOTSTRAP_DATABASE', 0);
  14. define('DRUPAL_BOOTSTRAP_SESSION', 1);
  15. define('DRUPAL_BOOTSTRAP_PAGE_CACHE', 2);
  16. define('DRUPAL_BOOTSTRAP_PATH', 3);
  17. define('DRUPAL_BOOTSTRAP_FULL', 4);
  18. // these values should match the'role' table
  19. define('DRUPAL_ANONYMOUS_RID', 1);
  20. define('DRUPAL_AUTHENTICATED_RID', 2);
  21. /**
  22. * Start the timer with the specified name. If you start and stop
  23. * the same timer multiple times, the measured intervals will be
  24. * accumulated.
  25. *
  26. * @param name
  27. * The name of the timer.
  28. */
  29. function timer_start($name) {
  30. global $timers;
  31. list($usec, $sec) = explode(' ', microtime());
  32. $timers[$name]['start'] = (float)$usec + (float)$sec;
  33. $timers[$name]['count'] = isset($timers[$name]['count']) ? ++$timers[$name]['count'] : 1;
  34. }
  35. /**
  36. * Read the current timer value without stopping the timer.
  37. *
  38. * @param name
  39. * The name of the timer.
  40. * @return
  41. * The current timer value in ms.
  42. */
  43. function timer_read($name) {
  44. global $timers;
  45. list($usec, $sec) = explode(' ', microtime());
  46. $stop = (float)$usec + (float)$sec;
  47. $diff = round(($stop - $timers[$name]['start']) * 1000, 2);
  48. return $timers[$name]['time'] + $diff;
  49. }
  50. /**
  51. * Stop the timer with the specified name.
  52. *
  53. * @param name
  54. * The name of the timer.
  55. * @return
  56. * A timer array. The array contains the number of times the
  57. * timer has been started and stopped (count) and the accumulated
  58. * timer value in ms (time).
  59. */
  60. function timer_stop($name) {
  61. global $timers;
  62. $timers[$name]['time'] = timer_read($name);
  63. unset($timers[$name]['start']);
  64. return $timers[$name];
  65. }
  66. /**
  67. * Find the appropriate configuration directory.
  68. *
  69. * Try finding a matching configuration directory by stripping the website's
  70. * hostname from left to right and pathname from right to left. The first
  71. * configuration file found will be used, the remaining will ignored. If no
  72. * configuration file is found, return a default value '$confdir/default'.
  73. *
  74. * Example for a fictitious site installed at
  75. * http://www.drupal.org:8080/mysite/test/ the 'settings.php' is searched in
  76. * the following directories:
  77. *
  78. * 1. $confdir/8080.www.drupal.org.mysite.test
  79. * 2. $confdir/www.drupal.org.mysite.test
  80. * 3. $confdir/drupal.org.mysite.test
  81. * 4. $confdir/org.mysite.test
  82. *
  83. * 5. $confdir/8080.www.drupal.org.mysite
  84. * 6. $confdir/www.drupal.org.mysite
  85. * 7. $confdir/drupal.org.mysite
  86. * 8. $confdir/org.mysite
  87. *
  88. * 9. $confdir/8080.www.drupal.org
  89. * 10. $confdir/www.drupal.org
  90. * 11. $confdir/drupal.org
  91. * 12. $confdir/org
  92. *
  93. * 13. $confdir/default
  94. */
  95. function conf_path() {
  96. static $conf = '';
  97. if ($conf) {
  98. return $conf;
  99. }
  100. $confdir = 'sites';
  101. $uri = explode('/', $_SERVER['SCRIPT_NAME'] ? $_SERVER['SCRIPT_NAME'] : $_SERVER['SCRIPT_FILENAME']);
  102. $server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.')))));
  103. for ($i = count($uri) - 1; $i > 0; $i--) {
  104. for ($j = count($server); $j > 0; $j--) {
  105. $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
  106. if (file_exists("$confdir/$dir/settings.php")) {
  107. $conf = "$confdir/$dir";
  108. return $conf;
  109. }
  110. }
  111. }
  112. $conf = "$confdir/default";
  113. return $conf;
  114. }
  115. /**
  116. * Unsets all disallowed global variables. See $allowed for what's allowed.
  117. */
  118. function drupal_unset_globals() {
  119. if (ini_get('register_globals')) {
  120. $allowed = array('_ENV' => 1, '_GET' => 1, '_POST' => 1, '_COOKIE' => 1, '_FILES' => 1, '_SERVER' => 1, '_REQUEST' => 1, 'access_check' => 1, 'GLOBALS' => 1);
  121. foreach ($GLOBALS as $key => $value) {
  122. if (!isset($allowed[$key])) {
  123. unset($GLOBALS[$key]);
  124. }
  125. }
  126. }
  127. }
  128. /**
  129. * Loads the configuration and sets the base URL correctly.
  130. */
  131. function conf_init() {
  132. global $db_url, $db_prefix, $base_url, $base_path, $base_root, $conf;
  133. $conf = array();
  134. require_once './'. conf_path() .'/settings.php';
  135. if (isset($base_url)) {
  136. // Parse fixed base URL from settings.php.
  137. $parts = parse_url($base_url);
  138. if (!isset($parts['path'])) {
  139. $parts['path'] = '';
  140. }
  141. $base_path = $parts['path'] . '/';
  142. // Build $base_root (everything until first slash after "scheme://").
  143. $base_root = substr($base_url, 0, strlen($base_url) - strlen($parts['path']));
  144. }
  145. else {
  146. // Create base URL
  147. $base_root = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
  148. // As $_SERVER['HTTP_HOST'] is user input, ensure it only contains
  149. // characters allowed in hostnames.
  150. $base_url = $base_root .= '://'. preg_replace('/[^a-z0-9-:._]/i', '', $_SERVER['HTTP_HOST']);
  151. // $_SERVER['SCRIPT_NAME'] can, in contrast to $_SERVER['PHP_SELF'], not
  152. // be modified by a visitor.
  153. if ($dir = trim(dirname($_SERVER['SCRIPT_NAME']), '\,/')) {
  154. $base_path = "/$dir";
  155. $base_url .= $base_path;
  156. $base_path .= '/';
  157. }
  158. else {
  159. $base_path = '/';
  160. }
  161. }
  162. }
  163. /**
  164. * Returns and optionally sets the filename for a system item (module,
  165. * theme, etc.). The filename, whether provided, cached, or retrieved
  166. * from the database, is only returned if the file exists.
  167. *
  168. * @param $type
  169. * The type of the item (i.e. theme, theme_engine, module).
  170. * @param $name
  171. * The name of the item for which the filename is requested.
  172. * @param $filename
  173. * The filename of the item if it is to be set explicitly rather
  174. * than by consulting the database.
  175. *
  176. * @return
  177. * The filename of the requested item.
  178. */
  179. function drupal_get_filename($type, $name, $filename = NULL) {
  180. static $files = array();
  181. if (!isset($files[$type])) {
  182. $files[$type] = array();
  183. }
  184. if (!empty($filename) && file_exists($filename)) {
  185. $files[$type][$name] = $filename;
  186. }
  187. elseif (isset($files[$type][$name])) {
  188. // nothing
  189. }
  190. elseif (($file = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s' AND type = '%s'", $name, $type))) && file_exists($file)) {
  191. $files[$type][$name] = $file;
  192. }
  193. else {
  194. $config = conf_path();
  195. $dir = (($type == 'theme_engine') ? 'themes/engines' : "${type}s");
  196. $file = (($type == 'theme_engine') ? "$name.engine" : "$name.$type");
  197. foreach (array("$config/$dir/$file", "$config/$dir/$name/$file", "$dir/$file", "$dir/$name/$file") as $file) {
  198. if (file_exists($file)) {
  199. $files[$type][$name] = $file;
  200. break;
  201. }
  202. }
  203. }
  204. return $files[$type][$name];
  205. }
  206. /**
  207. * Load the persistent variable table.
  208. *
  209. * The variable table is composed of values that have been saved in the table
  210. * with variable_set() as well as those explicitly specified in the configuration
  211. * file.
  212. */
  213. function variable_init($conf = array()) {
  214. // NOTE: caching the variables improves performance with 20% when serving cached pages.
  215. if ($cached = cache_get('variables')) {
  216. $variables = unserialize($cached->data);
  217. }
  218. else {
  219. $result = db_query('SELECT * FROM {variable}');
  220. while ($variable = db_fetch_object($result)) {
  221. $variables[$variable->name] = unserialize($variable->value);
  222. }
  223. cache_set('variables', serialize($variables));
  224. }
  225. foreach ($conf as $name => $value) {
  226. $variables[$name] = $value;
  227. }
  228. return $variables;
  229. }
  230. /**
  231. * Return a persistent variable.
  232. *
  233. * @param $name
  234. * The name of the variable to return.
  235. * @param $default
  236. * The default value to use if this variable has never been set.
  237. * @return
  238. * The value of the variable.
  239. */
  240. function variable_get($name, $default) {
  241. global $conf;
  242. return isset($conf[$name]) ? $conf[$name] : $default;
  243. }
  244. /**
  245. * Set a persistent variable.
  246. *
  247. * @param $name
  248. * The name of the variable to set.
  249. * @param $value
  250. * The value to set. This can be any PHP data type; these functions take care
  251. * of serialization as necessary.
  252. */
  253. function variable_set($name, $value) {
  254. global $conf;
  255. db_lock_table('variable');
  256. db_query("DELETE FROM {variable} WHERE name = '%s'", $name);
  257. db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", $name, serialize($value));
  258. db_unlock_tables();
  259. cache_clear_all('variables');
  260. $conf[$name] = $value;
  261. }
  262. /**
  263. * Unset a persistent variable.
  264. *
  265. * @param $name
  266. * The name of the variable to undefine.
  267. */
  268. function variable_del($name) {
  269. global $conf;
  270. db_query("DELETE FROM {variable} WHERE name = '%s'", $name);
  271. cache_clear_all('variables');
  272. unset($conf[$name]);
  273. }
  274. /**
  275. * Return data from the persistent cache.
  276. *
  277. * @param $key
  278. * The cache ID of the data to retrieve.
  279. */
  280. function cache_get($key) {
  281. global $user;
  282. // Garbage collection necessary when enforcing a minimum cache lifetime
  283. $cache_flush = variable_get('cache_flush', 0);
  284. if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= time())) {
  285. // Time to flush old cache data
  286. db_query("DELETE FROM {cache} WHERE expire != %d AND expire <= %d", CACHE_PERMANENT, $cache_flush);
  287. variable_set('cache_flush', 0);
  288. }
  289. $cache = db_fetch_object(db_query("SELECT data, created, headers, expire FROM {cache} WHERE cid = '%s'", $key));
  290. if (isset($cache->data)) {
  291. // If the data is permanent or we're not enforcing a minimum cache lifetime
  292. // always return the cached data.
  293. if ($cache->expire == CACHE_PERMANENT || !variable_get('cache_lifetime', 0)) {
  294. $cache->data = db_decode_blob($cache->data);
  295. }
  296. // If enforcing a minimum cache lifetime, validate that the data is
  297. // currently valid for this user before we return it by making sure the
  298. // cache entry was created before the timestamp in the current session's
  299. // cache timer. The cache variable is loaded into the $user object by
  300. // sess_read() in session.inc.
  301. else {
  302. if (isset($user->cache) && ($user->cache > $cache->created)) {
  303. // This cache data is too old and thus not valid for us, ignore it.
  304. return 0;
  305. }
  306. else {
  307. $cache->data = db_decode_blob($cache->data);
  308. }
  309. }
  310. return $cache;
  311. }
  312. return 0;
  313. }
  314. /**
  315. * Store data in the persistent cache.
  316. *
  317. * @param $cid
  318. * The cache ID of the data to store.
  319. * @param $data
  320. * The data to store in the cache. Complex data types must be serialized first.
  321. * @param $expire
  322. * One of the following values:
  323. * - CACHE_PERMANENT: Indicates that the item should never be removed unless
  324. * explicitly told to using cache_clear_all() with a cache ID.
  325. * - CACHE_TEMPORARY: Indicates that the item should be removed at the next
  326. * general cache wipe.
  327. * - A Unix timestamp: Indicates that the item should be kept at least until
  328. * the given time, after which it behaves like CACHE_TEMPORARY.
  329. * @param $headers
  330. * A string containing HTTP header information for cached pages.
  331. */
  332. function cache_set($cid, $data, $expire = CACHE_PERMANENT, $headers = NULL) {
  333. db_lock_table('cache');
  334. db_query("UPDATE {cache} SET data = %b, created = %d, expire = %d, headers = '%s' WHERE cid = '%s'", $data, time(), $expire, $headers, $cid);
  335. if (!db_affected_rows()) {
  336. @db_query("INSERT INTO {cache} (cid, data, created, expire, headers) VALUES ('%s', %b, %d, %d, '%s')", $cid, $data, time(), $expire, $headers);
  337. }
  338. db_unlock_tables();
  339. }
  340. /**
  341. * Expire data from the cache.
  342. *
  343. * @param $cid
  344. * If set, the cache ID to delete. Otherwise, all cache entries that can
  345. * expire are deleted.
  346. *
  347. * @param $wildcard
  348. * If set to true, the $cid is treated as a substring to match rather than a
  349. * complete ID.
  350. */
  351. function cache_clear_all($cid = NULL, $wildcard = false) {
  352. global $user;
  353. if (empty($cid)) {
  354. if (variable_get('cache_lifetime', 0)) {
  355. // We store the time in the current user's $user->cache variable which
  356. // will be saved into the sessions table by sess_write(). We then
  357. // simulate that the cache was flushed for this user by not returning
  358. // cached data that was cached before the timestamp.
  359. $user->cache = time();
  360. $cache_flush = variable_get('cache_flush', 0);
  361. if ($cache_flush == 0) {
  362. // This is the first request to clear the cache, start a timer.
  363. variable_set('cache_flush', time());
  364. }
  365. else if (time() > ($cache_flush + variable_get('cache_lifetime', 0))) {
  366. // Clear the cache for everyone, cache_flush_delay seconds have
  367. // passed since the first request to clear the cache.
  368. db_query("DELETE FROM {cache} WHERE expire != %d AND expire < %d", CACHE_PERMANENT, time());
  369. variable_set('cache_flush', 0);
  370. }
  371. }
  372. else {
  373. // No minimum cache lifetime, flush all temporary cache entries now.
  374. db_query("DELETE FROM {cache} WHERE expire != %d AND expire < %d", CACHE_PERMANENT, time());
  375. }
  376. }
  377. else {
  378. if ($wildcard) {
  379. db_query("DELETE FROM {cache} WHERE cid LIKE '%%%s%%'", $cid);
  380. }
  381. else {
  382. db_query("DELETE FROM {cache} WHERE cid = '%s'", $cid);
  383. }
  384. }
  385. }
  386. /**
  387. * Retrieve the current page from the cache.
  388. *
  389. * Note, we do not serve cached pages when status messages are waiting (from
  390. * a redirected form submission which was completed).
  391. * Because the output handler is not activated, the resulting page will not
  392. * get cached either.
  393. */
  394. function page_get_cache() {
  395. global $user, $base_root;
  396. $cache = NULL;
  397. if (!$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET' && count(drupal_set_message()) == 0) {
  398. $cache = cache_get($base_root . request_uri());
  399. if (empty($cache)) {
  400. ob_start();
  401. }
  402. }
  403. return $cache;
  404. }
  405. /**
  406. * Call all init or exit hooks without including all modules.
  407. *
  408. * @param $hook
  409. * The name of the bootstrap hook we wish to invoke.
  410. */
  411. function bootstrap_invoke_all($hook) {
  412. foreach (module_list(FALSE, TRUE) as $module) {
  413. drupal_load('module', $module);
  414. module_invoke($module, $hook);
  415. }
  416. }
  417. /**
  418. * Includes a file with the provided type and name. This prevents
  419. * including a theme, engine, module, etc., more than once.
  420. *
  421. * @param $type
  422. * The type of item to load (i.e. theme, theme_engine, module).
  423. * @param $name
  424. * The name of the item to load.
  425. *
  426. * @return
  427. * TRUE if the item is loaded or has already been loaded.
  428. */
  429. function drupal_load($type, $name) {
  430. static $files = array();
  431. if (isset($files[$type][$name])) {
  432. return TRUE;
  433. }
  434. $filename = drupal_get_filename($type, $name);
  435. if ($filename) {
  436. include_once "./$filename";
  437. $files[$type][$name] = TRUE;
  438. return TRUE;
  439. }
  440. return FALSE;
  441. }
  442. /**
  443. * Set HTTP headers in preparation for a page response.
  444. *
  445. * The general approach here is that anonymous users can keep a local cache of
  446. * the page, but must revalidate it on every request. Then, they are given a
  447. * '304 Not Modified' response as long as they stay logged out and the page
  448. * has not been modified.
  449. * This prevents authenticated users seeing locally cached pages that show them
  450. * as logged out.
  451. * Authenticated users are always given a 'no-cache' header set, and will fetch
  452. * a fresh page on every request.
  453. *
  454. * @see page_set_cache
  455. */
  456. function drupal_page_header() {
  457. if (variable_get('cache', 0) && $cache = page_get_cache()) {
  458. bootstrap_invoke_all('init');
  459. // Set default values:
  460. $date = gmdate('D, d M Y H:i:s', $cache->created) .' GMT';
  461. $etag = '"'. md5($date) .'"';
  462. // Check http headers:
  463. $modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $date : NULL;
  464. if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && ($timestamp = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) > 0) {
  465. $modified_since = $cache->created <= $timestamp;
  466. }
  467. else {
  468. $modified_since = NULL;
  469. }
  470. $none_match = !empty($_SERVER['HTTP_IF_NONE_MATCH']) ? $_SERVER['HTTP_IF_NONE_MATCH'] == $etag : NULL;
  471. // The type checking here is very important, be careful when changing entries.
  472. if (($modified_since !== NULL || $none_match !== NULL) && $modified_since !== false && $none_match !== false) {
  473. header('HTTP/1.0 304 Not Modified');
  474. exit();
  475. }
  476. // Send appropriate response:
  477. header("Last-Modified: $date");
  478. header("ETag: $etag");
  479. // The following headers force validation of cache
  480. header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
  481. header("Cache-Control: must-revalidate");
  482. // Determine if the browser accepts gzipped data.
  483. if (@strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === false && function_exists('gzencode')) {
  484. // Strip the gzip header and run uncompress.
  485. $cache->data = gzinflate(substr(substr($cache->data, 10), 0, -8));
  486. }
  487. elseif (function_exists('gzencode')) {
  488. header('Content-Encoding: gzip');
  489. }
  490. // Send the original request's headers. We send them one after
  491. // another so PHP's header() function can deal with duplicate
  492. // headers.
  493. $headers = explode("\n", $cache->headers);
  494. foreach ($headers as $header) {
  495. header($header);
  496. }
  497. print $cache->data;
  498. bootstrap_invoke_all('exit');
  499. exit();
  500. }
  501. else {
  502. header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
  503. header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  504. header("Cache-Control: no-store, no-cache, must-revalidate");
  505. header("Cache-Control: post-check=0, pre-check=0", false);
  506. header("Pragma: no-cache");
  507. }
  508. }
  509. /**
  510. * Define the critical hooks that force modules to always be loaded.
  511. */
  512. function bootstrap_hooks() {
  513. return array('init', 'exit');
  514. }
  515. /**
  516. * Unserializes and appends elements from a serialized string.
  517. *
  518. * @param $obj
  519. * The object to which the elements are appended.
  520. * @param $field
  521. * The attribute of $obj whose value should be unserialized.
  522. */
  523. function drupal_unpack($obj, $field = 'data') {
  524. if ($obj->$field && $data = unserialize($obj->$field)) {
  525. foreach ($data as $key => $value) {
  526. if (!isset($obj->$key)) {
  527. $obj->$key = $value;
  528. }
  529. }
  530. }
  531. return $obj;
  532. }
  533. /**
  534. * Return the URI of the referring page.
  535. */
  536. function referer_uri() {
  537. if (isset($_SERVER['HTTP_REFERER'])) {
  538. return $_SERVER['HTTP_REFERER'];
  539. }
  540. }
  541. /**
  542. * Encode special characters in a plain-text string for display as HTML.
  543. *
  544. * Uses drupal_validate_utf8 to prevent cross site scripting attacks on
  545. * Internet Explorer 6.
  546. *
  547. */
  548. function check_plain($text) {
  549. return drupal_validate_utf8($text) ? htmlspecialchars($text, ENT_QUOTES) : '';
  550. }
  551. /**
  552. * Checks whether a string is valid UTF-8.
  553. *
  554. * All functions designed to filter input should use drupal_validate_utf8
  555. * to ensure they operate on valid UTF-8 strings to prevent bypass of the
  556. * filter.
  557. *
  558. * When text containing an invalid UTF-8 lead byte (0xC0 - 0xFF) is presented
  559. * as UTF-8 to Internet Explorer 6, the program may misinterpret subsequent
  560. * bytes. When these subsequent bytes are HTML control characters such as
  561. * quotes or angle brackets, parts of the text that were deemed safe by filters
  562. * end up in locations that are potentially unsafe; An onerror attribute that
  563. * is outside of a tag, and thus deemed safe by a filter, can be interpreted
  564. * by the browser as if it were inside the tag.
  565. *
  566. * This function exploits preg_match behaviour (since PHP 4.3.5) when used with
  567. * the u modifier as a fast way to find invalid UTF-8. When the matched string
  568. * contains invalid byte sequences, it will fail silently.
  569. *
  570. * preg_match may not fail on 4 and 5 octet sequences, even though they
  571. * are not supported by the specification.
  572. *
  573. * The specific preg_match behaviour is present
  574. *
  575. * @param $text
  576. * The text to check.
  577. * @return
  578. * TRUE if the text is valid UTF-8, FALSE if not.
  579. */
  580. function drupal_validate_utf8($text) {
  581. if (strlen($text) == 0) {
  582. return TRUE;
  583. }
  584. return (preg_match('/^./us', $text) == 1);
  585. }
  586. /**
  587. * Since request_uri() is only available on Apache, we generate an
  588. * equivalent using other environment variables.
  589. */
  590. function request_uri() {
  591. if (isset($_SERVER['REQUEST_URI'])) {
  592. $uri = $_SERVER['REQUEST_URI'];
  593. }
  594. else {
  595. if (isset($_SERVER['argv'])) {
  596. $uri = $_SERVER['SCRIPT_NAME'] .'?'. $_SERVER['argv'][0];
  597. }
  598. else {
  599. $uri = $_SERVER['SCRIPT_NAME'] .'?'. $_SERVER['QUERY_STRING'];
  600. }
  601. }
  602. return $uri;
  603. }
  604. /**
  605. * Log a system message.
  606. *
  607. * @param $type
  608. * The category to which this message belongs.
  609. * @param $message
  610. * The message to store in the log.
  611. * @param $severity
  612. * The severity of the message. One of the following values:
  613. * - WATCHDOG_NOTICE
  614. * - WATCHDOG_WARNING
  615. * - WATCHDOG_ERROR
  616. * @param $link
  617. * A link to associate with the message.
  618. */
  619. function watchdog($type, $message, $severity = WATCHDOG_NOTICE, $link = NULL) {
  620. global $user, $base_root;
  621. $current_db = db_set_active();
  622. // Note: log the exact, entire absolute URL.
  623. $request_uri = $base_root . request_uri();
  624. db_query("INSERT INTO {watchdog} (uid, type, message, severity, link, location, referer, hostname, timestamp) VALUES (%d, '%s', '%s', %d, '%s', '%s', '%s', '%s', %d)", $user->uid, $type, $message, $severity, $link, $request_uri, referer_uri(), $_SERVER['REMOTE_ADDR'], time());
  625. if ($current_db) {
  626. db_set_active($current_db);
  627. }
  628. }
  629. /**
  630. * Set a message which reflects the status of the performed operation.
  631. *
  632. * If the function is called with no arguments, this function returns all set
  633. * messages without clearing them.
  634. *
  635. * @param $message
  636. * The message should begin with a capital letter and always ends with a
  637. * period '.'.
  638. * @param $type
  639. * The type of the message. One of the following values are possible:
  640. * - 'status'
  641. * - 'error'
  642. */
  643. function drupal_set_message($message = NULL, $type = 'status') {
  644. if ($message) {
  645. if (!isset($_SESSION['messages'])) {
  646. $_SESSION['messages'] = array();
  647. }
  648. if (!isset($_SESSION['messages'][$type])) {
  649. $_SESSION['messages'][$type] = array();
  650. }
  651. $_SESSION['messages'][$type][] = $message;
  652. }
  653. // messages not set when DB connection fails
  654. return isset($_SESSION['messages']) ? $_SESSION['messages'] : NULL;
  655. }
  656. /**
  657. * Return all messages that have been set.
  658. *
  659. * As a side effect, this function clears the message queue.
  660. */
  661. function drupal_get_messages() {
  662. if ($messages = drupal_set_message()) {
  663. unset($_SESSION['messages']);
  664. }
  665. return $messages;
  666. }
  667. /**
  668. * Perform an access check for a given mask and rule type. Rules are usually created via admin/access/rules page.
  669. */
  670. function drupal_is_denied($type, $mask) {
  671. $allow = db_fetch_object(db_query("SELECT * FROM {access} WHERE status = 1 AND type = '%s' AND LOWER('%s') LIKE LOWER(mask)", $type, $mask));
  672. $deny = db_fetch_object(db_query("SELECT * FROM {access} WHERE status = 0 AND type = '%s' AND LOWER('%s') LIKE LOWER(mask)", $type, $mask));
  673. return $deny && !$allow;
  674. }
  675. /**
  676. * A string describing a phase of Drupal to load. Each phase adds to the
  677. * previous one, so invoking a later phase automatically runs the earlier
  678. * phases too. The most important usage is that if you want to access
  679. * Drupal database from a script without loading anything else, you can
  680. * include bootstrap.inc, and call drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE).
  681. *
  682. * @param $phase
  683. * A constant. Allowed values are:
  684. * DRUPAL_BOOTSTRAP_DATABASE: initialize database layer.
  685. * DRUPAL_BOOTSTRAP_SESSION: initialize session handling.
  686. * DRUPAL_BOOTSTRAP_PAGE_CACHE: load bootstrap.inc and module.inc, start
  687. * the variable system and try to serve a page from the cache.
  688. * DRUPAL_BOOTSTRAP_FULL: Drupal is fully loaded, validate and fix input
  689. * data.
  690. */
  691. function drupal_bootstrap($phase) {
  692. static $phases = array(DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_PAGE_CACHE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL);
  693. while (!is_null($current_phase = array_shift($phases))) {
  694. _drupal_bootstrap($current_phase);
  695. if ($phase == $current_phase) {
  696. return;
  697. }
  698. }
  699. }
  700. function _drupal_bootstrap($phase) {
  701. global $conf;
  702. switch ($phase) {
  703. case DRUPAL_BOOTSTRAP_DATABASE:
  704. drupal_unset_globals();
  705. // Initialize the configuration
  706. conf_init();
  707. // Initialize the default database.
  708. require_once './includes/database.inc';
  709. db_set_active();
  710. break;
  711. case DRUPAL_BOOTSTRAP_SESSION:
  712. require_once './includes/session.inc';
  713. session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");
  714. session_start();
  715. break;
  716. case DRUPAL_BOOTSTRAP_PAGE_CACHE:
  717. require_once './includes/module.inc';
  718. // Start a page timer:
  719. timer_start('page');
  720. // deny access to hosts which were banned. t() is not yet available.
  721. if (drupal_is_denied('host', $_SERVER['REMOTE_ADDR'])) {
  722. header('HTTP/1.0 403 Forbidden');
  723. print 'Sorry, '. $_SERVER['REMOTE_ADDR']. ' has been banned.';
  724. exit();
  725. }
  726. // Initialize configuration variables, using values from conf.php if available.
  727. $conf = variable_init(isset($conf) ? $conf : array());
  728. drupal_page_header();
  729. break;
  730. case DRUPAL_BOOTSTRAP_PATH:
  731. require_once './includes/path.inc';
  732. // Initialize $_GET['q'] prior to loading modules and invoking hook_init().
  733. drupal_init_path();
  734. break;
  735. case DRUPAL_BOOTSTRAP_FULL:
  736. require_once './includes/common.inc';
  737. _drupal_bootstrap_full();
  738. break;
  739. }
  740. }
  741. /**
  742. * Enables use of the theme system without requiring database access. Since
  743. * there is not database access no theme will be enabled and the default
  744. * themeable functions will be called. Some themeable functions can not be used
  745. * without the full Drupal API loaded. For example, theme_page() is
  746. * unavailable and theme_maintenance_page() must be used in its place.
  747. */
  748. function drupal_maintenance_theme() {
  749. global $theme;
  750. require_once './includes/path.inc';
  751. require_once './includes/theme.inc';
  752. require_once './includes/common.inc';
  753. require_once './includes/unicode.inc';
  754. unicode_check();
  755. $theme = '';
  756. }
Login or register to post comments