Commit a0640e66 authored by Dries's avatar Dries

- Improved module loading when serving cached pages.  Moshe's bootstrap patch.

- Used legend and fieldset tags for the configuration page.
parent 7a2514e7
......@@ -2,6 +2,8 @@ Drupal x.x.x, xxxx-xx-xx
------------------------
- added support for the MetaWeblog API and MoveableType extensions.
- performance:
* improved module loading when serving cached pages.
- theme system:
* made all theme functions start with 'theme_'.
* made all theme functions return their output.
......
<?php
// $Id$
include_once "includes/bootstrap.inc";
include_once "includes/common.inc";
/*
......
......@@ -299,6 +299,7 @@ CREATE TABLE [dbo].[system] (
[type] [varchar] (255) NOT NULL ,
[description] [varchar] (255) NOT NULL ,
[status] [int] NOT NULL
[bootstrap] [int] NOT NULL
) ON [PRIMARY]
GO
......
......@@ -426,6 +426,7 @@ CREATE TABLE system (
type varchar(255) NOT NULL default '',
description varchar(255) NOT NULL default '',
status int(2) NOT NULL default '0',
bootstrap int(2) NOT NULL default '0',
PRIMARY KEY (filename)
) TYPE=MyISAM;
......
......@@ -422,6 +422,7 @@ CREATE TABLE system (
type varchar(255) NOT NULL default '',
description varchar(255) NOT NULL default '',
status integer NOT NULL default '0',
bootstrap integer NOT NULL default '0',
PRIMARY KEY (filename)
);
......
<?php
// $Id$
include_once "includes/bootstrap.inc";
include_once "includes/common.inc";
$errors = array(
......
<?php
function conf_init() {
/*
** Try finding a matching configuration file by stripping the website's
** URI from left to right. If no configuration file is found, return a
** default value 'conf'.
*/
$uri = $_SERVER["PHP_SELF"];
$file = strtolower(strtr($_SERVER["HTTP_HOST"] . substr($uri, 0, strrpos($uri, "/")), "/:", ".."));
while (strlen($file) > 4) {
if (file_exists("includes/$file.php")) {
return $file;
}
else {
$file = substr($file, strpos($file, ".") + 1);
}
}
return "conf";
}
function variable_init($conf = array()) {
$result = db_query("SELECT * FROM {variable} ");
while ($variable = db_fetch_object($result)) {
if (!isset($conf[$variable->name])) {
$conf[$variable->name] = unserialize($variable->value);
}
}
return $conf;
}
function variable_get($name, $default) {
global $conf;
return isset($conf[$name]) ? $conf[$name] : $default;
}
function variable_set($name, $value) {
global $conf;
db_query("DELETE FROM {variable} WHERE name = '%s'", $name);
db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", $name, serialize($value));
$conf[$name] = $value;
}
function variable_del($name) {
global $conf;
db_query("DELETE FROM {variable} WHERE name = '%s'", $name);
unset($conf[$name]);
}
function cache_get($key) {
$cache = db_fetch_object(db_query("SELECT data, created FROM {cache} WHERE cid = '%s'", $key));
return $cache->data ? $cache : 0;
}
function cache_set($cid, $data, $expire = 0) {
db_query("UPDATE {cache} SET data = '%s', created = %d, expire = %d WHERE cid = '%s'", $data, time(), $expire, $cid);
if (!db_affected_rows()) {
db_query("INSERT INTO {cache} (cid, data, created, expire) VALUES('%s', '%s', %d, %d)", $cid, $data, time(), $expire);
}
}
function cache_clear_all($cid = NULL) {
if (empty($cid)) {
db_query("DELETE FROM {cache} WHERE expire <> 0");
}
else {
db_query("DELETE FROM {cache} WHERE cid = '%s'", $cid);
}
}
function page_set_cache() {
global $user;
if (!$user->uid && $_SERVER["REQUEST_METHOD"] == "GET") {
if ($data = ob_get_contents()) {
cache_set(request_uri(), $data, 1);
}
}
}
function page_get_cache() {
global $user;
$cache = NULL;
if (!$user->uid && $_SERVER["REQUEST_METHOD"] == "GET") {
$cache = cache_get(request_uri());
if (empty($cache)) {
ob_start();
}
}
return $cache;
}
function drupal_page_header() {
if (variable_get("dev_timer", 0)) {
timer_start();
}
if (variable_get("cache", 0)) {
if ($cache = page_get_cache()) {
// Set default values:
$date = gmdate("D, d M Y H:i:s", $cache->created) ." GMT";
$etag = '"'. md5($date) .'"';
// Check http headers:
$modified_since = isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) ? $_SERVER["HTTP_IF_MODIFIED_SINCE"] == $date : NULL;
$none_match = isset($_SERVER["HTTP_IF_NONE_MATCH"]) ? $_SERVER["HTTP_IF_NONE_MATCH"] == $etag : NULL;
// The type checking here is very important, be careful when changing entries.
if (($modified_since !== NULL || $none_match !== NULL) && $modified_since !== false && $none_match !== false) {
header("HTTP/1.0 304 Not Modified");
exit();
}
// Send appropriate response:
header("Last-Modified: $date");
header("ETag: $etag");
print $cache->data;
/*
** call all init() and exit() hooks without including all modules
** only use those hooks for critical operations
*/
foreach (module_list(0, 1) as $module) {
if (is_array($module) && $module['bootstrap']) {
include_once $module['filename'];
foreach (bootstrap_hooks() as $hook) {
module_invoke($module['name'], $hook);
}
}
}
exit();
}
}
}
// critical hooks called even when serving a cached page
function bootstrap_hooks() {
return array('init', 'exit');
}
function referer_uri() {
if (isset($_SERVER["HTTP_REFERER"])) {
$uri = $_SERVER["HTTP_REFERER"];
return check_url($uri);
}
}
function arg($index) {
static $arguments;
if (empty($arguments)) {
$arguments = explode("/", $_GET["q"]);
}
return $arguments[$index];
}
function check_query($text) {
return addslashes($text);
}
function check_url($uri) {
$uri = htmlspecialchars($uri, ENT_QUOTES);
/*
** We replace ( and ) with their entity equivalents to prevent XSS
** attacks.
*/
$uri = strtr($uri, array("(" => "&040;", ")" => "&041;"));
return $uri;
}
function request_uri() {
/*
** Since request_uri() is only available on Apache, we generate
** equivalent using other environment vars.
*/
if (isset($_SERVER["REQUEST_URI"])) {
$uri = $_SERVER["REQUEST_URI"];
}
else {
$uri = $_SERVER["PHP_SELF"] ."?". $_SERVER["QUERY_STRING"];
}
return check_url($uri);
}
function timer_start() {
global $timer;
list($usec, $sec) = explode(" ", microtime());
$timer = (float)$usec + (float)$sec;
}
unset($conf);
$config = conf_init();
include_once "includes/$config.php";
include_once "includes/database.inc";
include_once "includes/session.inc";
include_once "includes/module.inc";
// initialize configuration variables, using values from conf.php if available:
$conf = variable_init(isset($conf) ? $conf : array());
?>
<?php
// $Id$
function conf_init() {
/*
** Try finding a matching configuration file by stripping the website's
** URI from left to right. If no configuration file is found, return a
** default value 'conf'.
*/
$uri = $_SERVER["PHP_SELF"];
$file = strtolower(strtr($_SERVER["HTTP_HOST"] . substr($uri, 0, strrpos($uri, "/")), "/:", ".."));
while (strlen($file) > 4) {
if (file_exists("includes/$file.php")) {
return $file;
}
else {
$file = substr($file, strpos($file, ".") + 1);
}
}
return "conf";
}
/**
* Build the alias/path array
*/
......@@ -100,17 +76,6 @@ function fix_gpc_magic() {
$fixed = true;
}
function arg($index) {
static $arguments;
if (empty($arguments)) {
$arguments = explode("/", $_GET["q"]);
}
return $arguments[$index];
}
function array2object($node) {
if (is_array($node)) {
......@@ -139,31 +104,6 @@ function object2array($node) {
return $array;
}
function referer_uri() {
if (isset($_SERVER["HTTP_REFERER"])) {
$uri = $_SERVER["HTTP_REFERER"];
return check_url($uri);
}
}
function request_uri() {
/*
** Since request_uri() is only available on Apache, we generate
** equivalent using other environment vars.
*/
if (isset($_SERVER["REQUEST_URI"])) {
$uri = $_SERVER["REQUEST_URI"];
}
else {
$uri = $_SERVER["PHP_SELF"] ."?". $_SERVER["QUERY_STRING"];
}
return check_url($uri);
}
function message_access() {
return t("You are not authorized to access this page.");
}
......@@ -210,40 +150,6 @@ function t($string, $args = 0) {
}
}
function variable_init($conf = array()) {
$result = db_query("SELECT * FROM {variable} ");
while ($variable = db_fetch_object($result)) {
if (!isset($conf[$variable->name])) {
$conf[$variable->name] = unserialize($variable->value);
}
}
return $conf;
}
function variable_get($name, $default) {
global $conf;
return isset($conf[$name]) ? $conf[$name] : $default;
}
function variable_set($name, $value) {
global $conf;
db_query("DELETE FROM {variable} WHERE name = '%s'", $name);
db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", $name, serialize($value));
$conf[$name] = $value;
}
function variable_del($name) {
global $conf;
db_query("DELETE FROM {variable} WHERE name = '%s'", $name);
unset($conf[$name]);
}
function drupal_specialchars($input, $quotes = ENT_NOQUOTES) {
/*
......@@ -476,27 +382,10 @@ function valid_input_data($data) {
return 1;
}
function check_url($uri) {
$uri = htmlspecialchars($uri, ENT_QUOTES);
/*
** We replace ( and ) with their entity equivalents to prevent XSS
** attacks.
*/
$uri = strtr($uri, array("(" => "&040;", ")" => "&041;"));
return $uri;
}
function check_form($text) {
return drupal_specialchars($text, ENT_QUOTES);
}
function check_query($text) {
return addslashes($text);
}
function filter($text) {
$modules = module_list();
......@@ -672,53 +561,6 @@ function format_size($size) {
return t("%size %suffix", array("%size" => $size, "%suffix" => $suffix));
}
function cache_get($key) {
$cache = db_fetch_object(db_query("SELECT data, created FROM {cache} WHERE cid = '%s'", $key));
return $cache->data ? $cache : 0;
}
function cache_set($cid, $data, $expire = 0) {
db_query("UPDATE {cache} SET data = '%s', created = %d, expire = %d WHERE cid = '%s'", $data, time(), $expire, $cid);
if (!db_affected_rows()) {
db_query("INSERT INTO {cache} (cid, data, created, expire) VALUES('%s', '%s', %d, %d)", $cid, $data, time(), $expire);
}
}
function cache_clear_all($cid = NULL) {
if (empty($cid)) {
db_query("DELETE FROM {cache} WHERE expire <> 0");
}
else {
db_query("DELETE FROM {cache} WHERE cid = '%s'", $cid);
}
}
function page_set_cache() {
global $user;
if (!$user->uid && $_SERVER["REQUEST_METHOD"] == "GET") {
if ($data = ob_get_contents()) {
cache_set(request_uri(), $data, 1);
}
}
}
function page_get_cache() {
global $user;
$cache = NULL;
if (!$user->uid && $_SERVER["REQUEST_METHOD"] == "GET") {
$cache = cache_get(request_uri());
if (empty($cache)) {
ob_start();
}
}
return $cache;
}
function format_interval($timestamp) {
$units = array("1 year|%count years" => 31536000, "1 week|%count weeks" => 604800, "1 day|%count days" => 86400, "1 hour|%count hours" => 3600, "1 min|%count min" => 60, "1 sec|%count sec" => 1);
foreach ($units as $key=>$value) {
......@@ -1005,64 +847,6 @@ function link_node($node, $main = 0) {
return module_invoke_all("link", "node", $node, $main);
}
function timer_start() {
global $timer;
list($usec, $sec) = explode(" ", microtime());
$timer = (float)$usec + (float)$sec;
}
function drupal_page_header() {
if (variable_get("dev_timer", 0)) {
timer_start();
}
if (variable_get("cache", 0)) {
if ($cache = page_get_cache()) {
// Set default values:
$date = gmdate("D, d M Y H:i:s", $cache->created) ." GMT";
$etag = '"'. md5($date) .'"';
// Check http headers:
$modified_since = isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) ? $_SERVER["HTTP_IF_MODIFIED_SINCE"] == $date : NULL;
$none_match = isset($_SERVER["HTTP_IF_NONE_MATCH"]) ? $_SERVER["HTTP_IF_NONE_MATCH"] == $etag : NULL;
// The type checking here is very important, be careful when changing entries.
if (($modified_since !== NULL || $none_match !== NULL) && $modified_since !== false && $none_match !== false) {
header("HTTP/1.0 304 Not Modified");
exit();
}
// Send appropriate response:
header("Last-Modified: $date");
header("ETag: $etag");
print $cache->data;
/*
** A hook for modules where modules may take action at the end of a
** request good uses include setting a cache, page logging, etc.
*/
module_invoke_all("exit");
exit();
}
}
/*
** Putting the check here avoids SQL query overhead in case we are
** serving cached pages. The downside, however, is that the init
** hooks might use unchecked data.
*/
if (!user_access("bypass input data check")) {
if (!valid_input_data($_REQUEST)) {
die("terminated request because of suspicious input data");
}
}
}
function drupal_page_footer() {
if (variable_get("cache", 0)) {
page_set_cache();
......@@ -1076,22 +860,12 @@ function drupal_page_footer() {
module_invoke_all("exit");
}
unset($conf);
$config = conf_init();
include_once "includes/$config.php";
include_once "includes/database.inc";
include_once "includes/module.inc";
include_once "includes/theme.inc";
include_once "includes/pager.inc";
include_once "includes/menu.inc";
include_once "includes/xmlrpc.inc";
include_once "includes/tablesort.inc";
// initialize configuration variables, using values from conf.php if available:
$conf = variable_init(isset($conf) ? $conf : array());
// set error handler:
set_error_handler("error_handler");
......@@ -1116,9 +890,16 @@ function drupal_page_footer() {
// initialize installed modules:
module_init();
if (!user_access("bypass input data check")) {
if (!valid_input_data($_REQUEST)) {
die("terminated request because of suspicious input data");
}
}
// initialize localization system:
$locale = locale_init();
// initialize theme:
$theme = init_theme();
?>
......@@ -40,8 +40,8 @@ function module_invoke_all($hook, $a1 = NULL, $a2 = NULL, $a3 = NULL, $a4 = NULL
return $return;
}
// return array of module names (includes lazy module loading):
function module_list($refresh = 0) {
// return array of module names (includes lazy module loading if not in bootstrap mode)
function module_list($refresh = 0, $bootstrap = 0) {
static $list;
if ($refresh) {
......@@ -50,16 +50,20 @@ function module_list($refresh = 0) {
if (!$list) {
$list = array("admin" => "admin", "system" => "system", "user" => "user", "watchdog" => "watchdog");
$result = db_query("SELECT name, filename FROM {system} WHERE type = 'module' AND status = '1' ORDER BY name");
$result = db_query("SELECT name, filename, bootstrap FROM {system} WHERE type = 'module' AND status = '1' ORDER BY name");
while ($module = db_fetch_object($result)) {
if (file_exists($module->filename)) {
$list[$module->name] = $module->name;
include_once $module->filename;
if ($bootstrap) {
$list[$module->name] = array("name"=> $module->name, "bootstrap" => $module->bootstrap, "filename" => $module->filename);
}
else {
$list[$module->name] = $module->name;
include_once $module->filename;
}
}
}
natcasesort($list);
}
return $list;
}
......
<?php
session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");
session_start();
/*** Session functions *****************************************************/
function sess_open($save_path, $session_name) {
return 1;
}
function sess_close() {
return 1;
}
function sess_read($key) {
global $user;
$result = db_query_range("SELECT u.*, s.*, r.name AS role FROM {users} u INNER JOIN {role} r ON u.rid = r.rid INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = '". check_query($key) ."' AND u.status < 3", 0, 1);
$user = db_fetch_object($result);
if ($user->data && $data = unserialize($user->data)) {
foreach ($data as $key => $value) {
if (!isset($user->$key)) {
$user->$key = $value;
}
}
}
return !empty($user->session) ? $user->session : '';
}
function sess_write($key, $value) {
global $user;