webmaster@1
|
1 <?php |
webmaster@13
|
2 // $Id: bootstrap.inc,v 1.206.2.6 2008/10/22 19:26:01 goba Exp $ |
webmaster@1
|
3 |
webmaster@1
|
4 /** |
webmaster@1
|
5 * @file |
webmaster@1
|
6 * Functions that need to be loaded on every Drupal request. |
webmaster@1
|
7 */ |
webmaster@1
|
8 |
webmaster@1
|
9 /** |
webmaster@1
|
10 * Indicates that the item should never be removed unless explicitly told to |
webmaster@1
|
11 * using cache_clear_all() with a cache ID. |
webmaster@1
|
12 */ |
webmaster@1
|
13 define('CACHE_PERMANENT', 0); |
webmaster@1
|
14 |
webmaster@1
|
15 /** |
webmaster@1
|
16 * Indicates that the item should be removed at the next general cache wipe. |
webmaster@1
|
17 */ |
webmaster@1
|
18 define('CACHE_TEMPORARY', -1); |
webmaster@1
|
19 |
webmaster@1
|
20 /** |
webmaster@1
|
21 * Indicates that page caching is disabled. |
webmaster@1
|
22 */ |
webmaster@1
|
23 define('CACHE_DISABLED', 0); |
webmaster@1
|
24 |
webmaster@1
|
25 /** |
webmaster@1
|
26 * Indicates that page caching is enabled, using "normal" mode. |
webmaster@1
|
27 */ |
webmaster@1
|
28 define('CACHE_NORMAL', 1); |
webmaster@1
|
29 |
webmaster@1
|
30 /** |
webmaster@1
|
31 * Indicates that page caching is using "aggressive" mode. This bypasses |
webmaster@1
|
32 * loading any modules for additional speed, which may break functionality in |
webmaster@1
|
33 * modules that expect to be run on each page load. |
webmaster@1
|
34 */ |
webmaster@1
|
35 define('CACHE_AGGRESSIVE', 2); |
webmaster@1
|
36 |
webmaster@1
|
37 /** |
webmaster@1
|
38 * |
webmaster@1
|
39 * Severity levels, as defined in RFC 3164 http://www.faqs.org/rfcs/rfc3164.html |
webmaster@1
|
40 * @see watchdog() |
webmaster@1
|
41 * @see watchdog_severity_levels() |
webmaster@1
|
42 */ |
webmaster@1
|
43 define('WATCHDOG_EMERG', 0); // Emergency: system is unusable |
webmaster@1
|
44 define('WATCHDOG_ALERT', 1); // Alert: action must be taken immediately |
webmaster@1
|
45 define('WATCHDOG_CRITICAL', 2); // Critical: critical conditions |
webmaster@1
|
46 define('WATCHDOG_ERROR', 3); // Error: error conditions |
webmaster@1
|
47 define('WATCHDOG_WARNING', 4); // Warning: warning conditions |
webmaster@1
|
48 define('WATCHDOG_NOTICE', 5); // Notice: normal but significant condition |
webmaster@1
|
49 define('WATCHDOG_INFO', 6); // Informational: informational messages |
webmaster@1
|
50 define('WATCHDOG_DEBUG', 7); // Debug: debug-level messages |
webmaster@1
|
51 |
webmaster@1
|
52 /** |
webmaster@1
|
53 * First bootstrap phase: initialize configuration. |
webmaster@1
|
54 */ |
webmaster@1
|
55 define('DRUPAL_BOOTSTRAP_CONFIGURATION', 0); |
webmaster@1
|
56 |
webmaster@1
|
57 /** |
webmaster@1
|
58 * Second bootstrap phase: try to call a non-database cache |
webmaster@1
|
59 * fetch routine. |
webmaster@1
|
60 */ |
webmaster@1
|
61 define('DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE', 1); |
webmaster@1
|
62 |
webmaster@1
|
63 /** |
webmaster@1
|
64 * Third bootstrap phase: initialize database layer. |
webmaster@1
|
65 */ |
webmaster@1
|
66 define('DRUPAL_BOOTSTRAP_DATABASE', 2); |
webmaster@1
|
67 |
webmaster@1
|
68 /** |
webmaster@1
|
69 * Fourth bootstrap phase: identify and reject banned hosts. |
webmaster@1
|
70 */ |
webmaster@1
|
71 define('DRUPAL_BOOTSTRAP_ACCESS', 3); |
webmaster@1
|
72 |
webmaster@1
|
73 /** |
webmaster@1
|
74 * Fifth bootstrap phase: initialize session handling. |
webmaster@1
|
75 */ |
webmaster@1
|
76 define('DRUPAL_BOOTSTRAP_SESSION', 4); |
webmaster@1
|
77 |
webmaster@1
|
78 /** |
webmaster@1
|
79 * Sixth bootstrap phase: load bootstrap.inc and module.inc, start |
webmaster@1
|
80 * the variable system and try to serve a page from the cache. |
webmaster@1
|
81 */ |
webmaster@1
|
82 define('DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE', 5); |
webmaster@1
|
83 |
webmaster@1
|
84 /** |
webmaster@1
|
85 * Seventh bootstrap phase: find out language of the page. |
webmaster@1
|
86 */ |
webmaster@1
|
87 define('DRUPAL_BOOTSTRAP_LANGUAGE', 6); |
webmaster@1
|
88 |
webmaster@1
|
89 /** |
webmaster@1
|
90 * Eighth bootstrap phase: set $_GET['q'] to Drupal path of request. |
webmaster@1
|
91 */ |
webmaster@1
|
92 define('DRUPAL_BOOTSTRAP_PATH', 7); |
webmaster@1
|
93 |
webmaster@1
|
94 /** |
webmaster@1
|
95 * Final bootstrap phase: Drupal is fully loaded; validate and fix |
webmaster@1
|
96 * input data. |
webmaster@1
|
97 */ |
webmaster@1
|
98 define('DRUPAL_BOOTSTRAP_FULL', 8); |
webmaster@1
|
99 |
webmaster@1
|
100 /** |
webmaster@1
|
101 * Role ID for anonymous users; should match what's in the "role" table. |
webmaster@1
|
102 */ |
webmaster@1
|
103 define('DRUPAL_ANONYMOUS_RID', 1); |
webmaster@1
|
104 |
webmaster@1
|
105 /** |
webmaster@1
|
106 * Role ID for authenticated users; should match what's in the "role" table. |
webmaster@1
|
107 */ |
webmaster@1
|
108 define('DRUPAL_AUTHENTICATED_RID', 2); |
webmaster@1
|
109 |
webmaster@1
|
110 /** |
webmaster@1
|
111 * No language negotiation. The default language is used. |
webmaster@1
|
112 */ |
webmaster@1
|
113 define('LANGUAGE_NEGOTIATION_NONE', 0); |
webmaster@1
|
114 |
webmaster@1
|
115 /** |
webmaster@1
|
116 * Path based negotiation with fallback to default language |
webmaster@1
|
117 * if no defined path prefix identified. |
webmaster@1
|
118 */ |
webmaster@1
|
119 define('LANGUAGE_NEGOTIATION_PATH_DEFAULT', 1); |
webmaster@1
|
120 |
webmaster@1
|
121 /** |
webmaster@1
|
122 * Path based negotiation with fallback to user preferences |
webmaster@1
|
123 * and browser language detection if no defined path prefix |
webmaster@1
|
124 * identified. |
webmaster@1
|
125 */ |
webmaster@1
|
126 define('LANGUAGE_NEGOTIATION_PATH', 2); |
webmaster@1
|
127 |
webmaster@1
|
128 /** |
webmaster@1
|
129 * Domain based negotiation with fallback to default language |
webmaster@1
|
130 * if no language identified by domain. |
webmaster@1
|
131 */ |
webmaster@1
|
132 define('LANGUAGE_NEGOTIATION_DOMAIN', 3); |
webmaster@1
|
133 |
webmaster@1
|
134 /** |
webmaster@1
|
135 * Start the timer with the specified name. If you start and stop |
webmaster@1
|
136 * the same timer multiple times, the measured intervals will be |
webmaster@1
|
137 * accumulated. |
webmaster@1
|
138 * |
webmaster@1
|
139 * @param name |
webmaster@1
|
140 * The name of the timer. |
webmaster@1
|
141 */ |
webmaster@1
|
142 function timer_start($name) { |
webmaster@1
|
143 global $timers; |
webmaster@1
|
144 |
webmaster@1
|
145 list($usec, $sec) = explode(' ', microtime()); |
webmaster@1
|
146 $timers[$name]['start'] = (float)$usec + (float)$sec; |
webmaster@1
|
147 $timers[$name]['count'] = isset($timers[$name]['count']) ? ++$timers[$name]['count'] : 1; |
webmaster@1
|
148 } |
webmaster@1
|
149 |
webmaster@1
|
150 /** |
webmaster@1
|
151 * Read the current timer value without stopping the timer. |
webmaster@1
|
152 * |
webmaster@1
|
153 * @param name |
webmaster@1
|
154 * The name of the timer. |
webmaster@1
|
155 * @return |
webmaster@1
|
156 * The current timer value in ms. |
webmaster@1
|
157 */ |
webmaster@1
|
158 function timer_read($name) { |
webmaster@1
|
159 global $timers; |
webmaster@1
|
160 |
webmaster@1
|
161 if (isset($timers[$name]['start'])) { |
webmaster@1
|
162 list($usec, $sec) = explode(' ', microtime()); |
webmaster@1
|
163 $stop = (float)$usec + (float)$sec; |
webmaster@1
|
164 $diff = round(($stop - $timers[$name]['start']) * 1000, 2); |
webmaster@1
|
165 |
webmaster@1
|
166 if (isset($timers[$name]['time'])) { |
webmaster@1
|
167 $diff += $timers[$name]['time']; |
webmaster@1
|
168 } |
webmaster@1
|
169 return $diff; |
webmaster@1
|
170 } |
webmaster@1
|
171 } |
webmaster@1
|
172 |
webmaster@1
|
173 /** |
webmaster@1
|
174 * Stop the timer with the specified name. |
webmaster@1
|
175 * |
webmaster@1
|
176 * @param name |
webmaster@1
|
177 * The name of the timer. |
webmaster@1
|
178 * @return |
webmaster@1
|
179 * A timer array. The array contains the number of times the |
webmaster@1
|
180 * timer has been started and stopped (count) and the accumulated |
webmaster@1
|
181 * timer value in ms (time). |
webmaster@1
|
182 */ |
webmaster@1
|
183 function timer_stop($name) { |
webmaster@1
|
184 global $timers; |
webmaster@1
|
185 |
webmaster@1
|
186 $timers[$name]['time'] = timer_read($name); |
webmaster@1
|
187 unset($timers[$name]['start']); |
webmaster@1
|
188 |
webmaster@1
|
189 return $timers[$name]; |
webmaster@1
|
190 } |
webmaster@1
|
191 |
webmaster@1
|
192 /** |
webmaster@1
|
193 * Find the appropriate configuration directory. |
webmaster@1
|
194 * |
webmaster@1
|
195 * Try finding a matching configuration directory by stripping the website's |
webmaster@1
|
196 * hostname from left to right and pathname from right to left. The first |
webmaster@1
|
197 * configuration file found will be used; the remaining will ignored. If no |
webmaster@1
|
198 * configuration file is found, return a default value '$confdir/default'. |
webmaster@1
|
199 * |
webmaster@1
|
200 * Example for a fictitious site installed at |
webmaster@1
|
201 * http://www.drupal.org:8080/mysite/test/ the 'settings.php' is searched in |
webmaster@1
|
202 * the following directories: |
webmaster@1
|
203 * |
webmaster@1
|
204 * 1. $confdir/8080.www.drupal.org.mysite.test |
webmaster@1
|
205 * 2. $confdir/www.drupal.org.mysite.test |
webmaster@1
|
206 * 3. $confdir/drupal.org.mysite.test |
webmaster@1
|
207 * 4. $confdir/org.mysite.test |
webmaster@1
|
208 * |
webmaster@1
|
209 * 5. $confdir/8080.www.drupal.org.mysite |
webmaster@1
|
210 * 6. $confdir/www.drupal.org.mysite |
webmaster@1
|
211 * 7. $confdir/drupal.org.mysite |
webmaster@1
|
212 * 8. $confdir/org.mysite |
webmaster@1
|
213 * |
webmaster@1
|
214 * 9. $confdir/8080.www.drupal.org |
webmaster@1
|
215 * 10. $confdir/www.drupal.org |
webmaster@1
|
216 * 11. $confdir/drupal.org |
webmaster@1
|
217 * 12. $confdir/org |
webmaster@1
|
218 * |
webmaster@1
|
219 * 13. $confdir/default |
webmaster@1
|
220 * |
webmaster@1
|
221 * @param $require_settings |
webmaster@1
|
222 * Only configuration directories with an existing settings.php file |
webmaster@1
|
223 * will be recognized. Defaults to TRUE. During initial installation, |
webmaster@1
|
224 * this is set to FALSE so that Drupal can detect a matching directory, |
webmaster@1
|
225 * then create a new settings.php file in it. |
webmaster@1
|
226 * @param reset |
webmaster@1
|
227 * Force a full search for matching directories even if one had been |
webmaster@1
|
228 * found previously. |
webmaster@1
|
229 * @return |
webmaster@1
|
230 * The path of the matching directory. |
webmaster@1
|
231 */ |
webmaster@1
|
232 function conf_path($require_settings = TRUE, $reset = FALSE) { |
webmaster@1
|
233 static $conf = ''; |
webmaster@1
|
234 |
webmaster@1
|
235 if ($conf && !$reset) { |
webmaster@1
|
236 return $conf; |
webmaster@1
|
237 } |
webmaster@1
|
238 |
webmaster@1
|
239 $confdir = 'sites'; |
webmaster@1
|
240 $uri = explode('/', $_SERVER['SCRIPT_NAME'] ? $_SERVER['SCRIPT_NAME'] : $_SERVER['SCRIPT_FILENAME']); |
webmaster@13
|
241 if (strpos($_SERVER['HTTP_HOST'], '/') !== FALSE) { |
webmaster@13
|
242 // A HTTP_HOST containing slashes may be an attack and is invalid. |
webmaster@13
|
243 header('HTTP/1.1 400 Bad Request'); |
webmaster@13
|
244 exit; |
webmaster@13
|
245 } |
webmaster@1
|
246 $server = explode('.', implode('.', array_reverse(explode(':', rtrim($_SERVER['HTTP_HOST'], '.'))))); |
webmaster@1
|
247 for ($i = count($uri) - 1; $i > 0; $i--) { |
webmaster@1
|
248 for ($j = count($server); $j > 0; $j--) { |
webmaster@1
|
249 $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i)); |
webmaster@1
|
250 if (file_exists("$confdir/$dir/settings.php") || (!$require_settings && file_exists("$confdir/$dir"))) { |
webmaster@1
|
251 $conf = "$confdir/$dir"; |
webmaster@1
|
252 return $conf; |
webmaster@1
|
253 } |
webmaster@1
|
254 } |
webmaster@1
|
255 } |
webmaster@1
|
256 $conf = "$confdir/default"; |
webmaster@1
|
257 return $conf; |
webmaster@1
|
258 } |
webmaster@1
|
259 |
webmaster@1
|
260 /** |
webmaster@1
|
261 * Unsets all disallowed global variables. See $allowed for what's allowed. |
webmaster@1
|
262 */ |
webmaster@1
|
263 function drupal_unset_globals() { |
webmaster@1
|
264 if (ini_get('register_globals')) { |
webmaster@1
|
265 $allowed = array('_ENV' => 1, '_GET' => 1, '_POST' => 1, '_COOKIE' => 1, '_FILES' => 1, '_SERVER' => 1, '_REQUEST' => 1, 'GLOBALS' => 1); |
webmaster@1
|
266 foreach ($GLOBALS as $key => $value) { |
webmaster@1
|
267 if (!isset($allowed[$key])) { |
webmaster@1
|
268 unset($GLOBALS[$key]); |
webmaster@1
|
269 } |
webmaster@1
|
270 } |
webmaster@1
|
271 } |
webmaster@1
|
272 } |
webmaster@1
|
273 |
webmaster@1
|
274 /** |
webmaster@1
|
275 * Loads the configuration and sets the base URL, cookie domain, and |
webmaster@1
|
276 * session name correctly. |
webmaster@1
|
277 */ |
webmaster@1
|
278 function conf_init() { |
webmaster@1
|
279 global $base_url, $base_path, $base_root; |
webmaster@1
|
280 |
webmaster@1
|
281 // Export the following settings.php variables to the global namespace |
webmaster@1
|
282 global $db_url, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access; |
webmaster@1
|
283 $conf = array(); |
webmaster@1
|
284 |
webmaster@1
|
285 if (file_exists('./'. conf_path() .'/settings.php')) { |
webmaster@1
|
286 include_once './'. conf_path() .'/settings.php'; |
webmaster@1
|
287 } |
webmaster@1
|
288 |
webmaster@7
|
289 // Ignore the placeholder url from default.settings.php. |
webmaster@7
|
290 if (isset($db_url) && $db_url == 'mysql://username:password@localhost/databasename') { |
webmaster@7
|
291 $db_url = ''; |
webmaster@7
|
292 } |
webmaster@7
|
293 |
webmaster@1
|
294 if (isset($base_url)) { |
webmaster@1
|
295 // Parse fixed base URL from settings.php. |
webmaster@1
|
296 $parts = parse_url($base_url); |
webmaster@1
|
297 if (!isset($parts['path'])) { |
webmaster@1
|
298 $parts['path'] = ''; |
webmaster@1
|
299 } |
webmaster@1
|
300 $base_path = $parts['path'] .'/'; |
webmaster@1
|
301 // Build $base_root (everything until first slash after "scheme://"). |
webmaster@1
|
302 $base_root = substr($base_url, 0, strlen($base_url) - strlen($parts['path'])); |
webmaster@1
|
303 } |
webmaster@1
|
304 else { |
webmaster@1
|
305 // Create base URL |
webmaster@1
|
306 $base_root = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http'; |
webmaster@1
|
307 |
webmaster@1
|
308 // As $_SERVER['HTTP_HOST'] is user input, ensure it only contains |
webmaster@1
|
309 // characters allowed in hostnames. |
webmaster@1
|
310 $base_url = $base_root .= '://'. preg_replace('/[^a-z0-9-:._]/i', '', $_SERVER['HTTP_HOST']); |
webmaster@1
|
311 |
webmaster@1
|
312 // $_SERVER['SCRIPT_NAME'] can, in contrast to $_SERVER['PHP_SELF'], not |
webmaster@1
|
313 // be modified by a visitor. |
webmaster@1
|
314 if ($dir = trim(dirname($_SERVER['SCRIPT_NAME']), '\,/')) { |
webmaster@1
|
315 $base_path = "/$dir"; |
webmaster@1
|
316 $base_url .= $base_path; |
webmaster@1
|
317 $base_path .= '/'; |
webmaster@1
|
318 } |
webmaster@1
|
319 else { |
webmaster@1
|
320 $base_path = '/'; |
webmaster@1
|
321 } |
webmaster@1
|
322 } |
webmaster@1
|
323 |
webmaster@1
|
324 if ($cookie_domain) { |
webmaster@1
|
325 // If the user specifies the cookie domain, also use it for session name. |
webmaster@1
|
326 $session_name = $cookie_domain; |
webmaster@1
|
327 } |
webmaster@1
|
328 else { |
webmaster@1
|
329 // Otherwise use $base_url as session name, without the protocol |
webmaster@1
|
330 // to use the same session identifiers across http and https. |
webmaster@1
|
331 list( , $session_name) = explode('://', $base_url, 2); |
webmaster@1
|
332 // We escape the hostname because it can be modified by a visitor. |
webmaster@1
|
333 if (!empty($_SERVER['HTTP_HOST'])) { |
webmaster@1
|
334 $cookie_domain = check_plain($_SERVER['HTTP_HOST']); |
webmaster@1
|
335 } |
webmaster@1
|
336 } |
webmaster@11
|
337 // To prevent session cookies from being hijacked, a user can configure the |
webmaster@11
|
338 // SSL version of their website to only transfer session cookies via SSL by |
webmaster@11
|
339 // using PHP's session.cookie_secure setting. The browser will then use two |
webmaster@11
|
340 // separate session cookies for the HTTPS and HTTP versions of the site. So we |
webmaster@11
|
341 // must use different session identifiers for HTTPS and HTTP to prevent a |
webmaster@11
|
342 // cookie collision. |
webmaster@11
|
343 if (ini_get('session.cookie_secure')) { |
webmaster@11
|
344 $session_name .= 'SSL'; |
webmaster@11
|
345 } |
webmaster@1
|
346 // Strip leading periods, www., and port numbers from cookie domain. |
webmaster@1
|
347 $cookie_domain = ltrim($cookie_domain, '.'); |
webmaster@1
|
348 if (strpos($cookie_domain, 'www.') === 0) { |
webmaster@1
|
349 $cookie_domain = substr($cookie_domain, 4); |
webmaster@1
|
350 } |
webmaster@1
|
351 $cookie_domain = explode(':', $cookie_domain); |
webmaster@1
|
352 $cookie_domain = '.'. $cookie_domain[0]; |
webmaster@1
|
353 // Per RFC 2109, cookie domains must contain at least one dot other than the |
webmaster@1
|
354 // first. For hosts such as 'localhost' or IP Addresses we don't set a cookie domain. |
webmaster@1
|
355 if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) { |
webmaster@1
|
356 ini_set('session.cookie_domain', $cookie_domain); |
webmaster@1
|
357 } |
webmaster@1
|
358 session_name('SESS'. md5($session_name)); |
webmaster@1
|
359 } |
webmaster@1
|
360 |
webmaster@1
|
361 /** |
webmaster@1
|
362 * Returns and optionally sets the filename for a system item (module, |
webmaster@1
|
363 * theme, etc.). The filename, whether provided, cached, or retrieved |
webmaster@1
|
364 * from the database, is only returned if the file exists. |
webmaster@1
|
365 * |
webmaster@1
|
366 * This function plays a key role in allowing Drupal's resources (modules |
webmaster@1
|
367 * and themes) to be located in different places depending on a site's |
webmaster@1
|
368 * configuration. For example, a module 'foo' may legally be be located |
webmaster@1
|
369 * in any of these three places: |
webmaster@1
|
370 * |
webmaster@1
|
371 * modules/foo/foo.module |
webmaster@1
|
372 * sites/all/modules/foo/foo.module |
webmaster@1
|
373 * sites/example.com/modules/foo/foo.module |
webmaster@1
|
374 * |
webmaster@1
|
375 * Calling drupal_get_filename('module', 'foo') will give you one of |
webmaster@1
|
376 * the above, depending on where the module is located. |
webmaster@1
|
377 * |
webmaster@1
|
378 * @param $type |
webmaster@1
|
379 * The type of the item (i.e. theme, theme_engine, module). |
webmaster@1
|
380 * @param $name |
webmaster@1
|
381 * The name of the item for which the filename is requested. |
webmaster@1
|
382 * @param $filename |
webmaster@1
|
383 * The filename of the item if it is to be set explicitly rather |
webmaster@1
|
384 * than by consulting the database. |
webmaster@1
|
385 * |
webmaster@1
|
386 * @return |
webmaster@1
|
387 * The filename of the requested item. |
webmaster@1
|
388 */ |
webmaster@1
|
389 function drupal_get_filename($type, $name, $filename = NULL) { |
webmaster@1
|
390 static $files = array(); |
webmaster@1
|
391 |
webmaster@1
|
392 if (!isset($files[$type])) { |
webmaster@1
|
393 $files[$type] = array(); |
webmaster@1
|
394 } |
webmaster@1
|
395 |
webmaster@1
|
396 if (!empty($filename) && file_exists($filename)) { |
webmaster@1
|
397 $files[$type][$name] = $filename; |
webmaster@1
|
398 } |
webmaster@1
|
399 elseif (isset($files[$type][$name])) { |
webmaster@1
|
400 // nothing |
webmaster@1
|
401 } |
webmaster@1
|
402 // Verify that we have an active database connection, before querying |
webmaster@1
|
403 // the database. This is required because this function is called both |
webmaster@1
|
404 // before we have a database connection (i.e. during installation) and |
webmaster@1
|
405 // when a database connection fails. |
webmaster@1
|
406 elseif (db_is_active() && (($file = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s' AND type = '%s'", $name, $type))) && file_exists($file))) { |
webmaster@1
|
407 $files[$type][$name] = $file; |
webmaster@1
|
408 } |
webmaster@1
|
409 else { |
webmaster@1
|
410 // Fallback to searching the filesystem if the database connection is |
webmaster@1
|
411 // not established or the requested file is not found. |
webmaster@1
|
412 $config = conf_path(); |
webmaster@1
|
413 $dir = (($type == 'theme_engine') ? 'themes/engines' : "${type}s"); |
webmaster@1
|
414 $file = (($type == 'theme_engine') ? "$name.engine" : "$name.$type"); |
webmaster@1
|
415 |
webmaster@1
|
416 foreach (array("$config/$dir/$file", "$config/$dir/$name/$file", "$dir/$file", "$dir/$name/$file") as $file) { |
webmaster@1
|
417 if (file_exists($file)) { |
webmaster@1
|
418 $files[$type][$name] = $file; |
webmaster@1
|
419 break; |
webmaster@1
|
420 } |
webmaster@1
|
421 } |
webmaster@1
|
422 } |
webmaster@1
|
423 |
webmaster@1
|
424 if (isset($files[$type][$name])) { |
webmaster@1
|
425 return $files[$type][$name]; |
webmaster@1
|
426 } |
webmaster@1
|
427 } |
webmaster@1
|
428 |
webmaster@1
|
429 /** |
webmaster@1
|
430 * Load the persistent variable table. |
webmaster@1
|
431 * |
webmaster@1
|
432 * The variable table is composed of values that have been saved in the table |
webmaster@1
|
433 * with variable_set() as well as those explicitly specified in the configuration |
webmaster@1
|
434 * file. |
webmaster@1
|
435 */ |
webmaster@1
|
436 function variable_init($conf = array()) { |
webmaster@1
|
437 // NOTE: caching the variables improves performance by 20% when serving cached pages. |
webmaster@1
|
438 if ($cached = cache_get('variables', 'cache')) { |
webmaster@1
|
439 $variables = $cached->data; |
webmaster@1
|
440 } |
webmaster@1
|
441 else { |
webmaster@1
|
442 $result = db_query('SELECT * FROM {variable}'); |
webmaster@1
|
443 while ($variable = db_fetch_object($result)) { |
webmaster@1
|
444 $variables[$variable->name] = unserialize($variable->value); |
webmaster@1
|
445 } |
webmaster@1
|
446 cache_set('variables', $variables); |
webmaster@1
|
447 } |
webmaster@1
|
448 |
webmaster@1
|
449 foreach ($conf as $name => $value) { |
webmaster@1
|
450 $variables[$name] = $value; |
webmaster@1
|
451 } |
webmaster@1
|
452 |
webmaster@1
|
453 return $variables; |
webmaster@1
|
454 } |
webmaster@1
|
455 |
webmaster@1
|
456 /** |
webmaster@1
|
457 * Return a persistent variable. |
webmaster@1
|
458 * |
webmaster@1
|
459 * @param $name |
webmaster@1
|
460 * The name of the variable to return. |
webmaster@1
|
461 * @param $default |
webmaster@1
|
462 * The default value to use if this variable has never been set. |
webmaster@1
|
463 * @return |
webmaster@1
|
464 * The value of the variable. |
webmaster@1
|
465 */ |
webmaster@1
|
466 function variable_get($name, $default) { |
webmaster@1
|
467 global $conf; |
webmaster@1
|
468 |
webmaster@1
|
469 return isset($conf[$name]) ? $conf[$name] : $default; |
webmaster@1
|
470 } |
webmaster@1
|
471 |
webmaster@1
|
472 /** |
webmaster@1
|
473 * Set a persistent variable. |
webmaster@1
|
474 * |
webmaster@1
|
475 * @param $name |
webmaster@1
|
476 * The name of the variable to set. |
webmaster@1
|
477 * @param $value |
webmaster@1
|
478 * The value to set. This can be any PHP data type; these functions take care |
webmaster@1
|
479 * of serialization as necessary. |
webmaster@1
|
480 */ |
webmaster@1
|
481 function variable_set($name, $value) { |
webmaster@1
|
482 global $conf; |
webmaster@1
|
483 |
webmaster@1
|
484 $serialized_value = serialize($value); |
webmaster@1
|
485 db_query("UPDATE {variable} SET value = '%s' WHERE name = '%s'", $serialized_value, $name); |
webmaster@1
|
486 if (!db_affected_rows()) { |
webmaster@1
|
487 @db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", $name, $serialized_value); |
webmaster@1
|
488 } |
webmaster@1
|
489 |
webmaster@1
|
490 cache_clear_all('variables', 'cache'); |
webmaster@1
|
491 |
webmaster@1
|
492 $conf[$name] = $value; |
webmaster@1
|
493 } |
webmaster@1
|
494 |
webmaster@1
|
495 /** |
webmaster@1
|
496 * Unset a persistent variable. |
webmaster@1
|
497 * |
webmaster@1
|
498 * @param $name |
webmaster@1
|
499 * The name of the variable to undefine. |
webmaster@1
|
500 */ |
webmaster@1
|
501 function variable_del($name) { |
webmaster@1
|
502 global $conf; |
webmaster@1
|
503 |
webmaster@1
|
504 db_query("DELETE FROM {variable} WHERE name = '%s'", $name); |
webmaster@1
|
505 cache_clear_all('variables', 'cache'); |
webmaster@1
|
506 |
webmaster@1
|
507 unset($conf[$name]); |
webmaster@1
|
508 } |
webmaster@1
|
509 |
webmaster@1
|
510 |
webmaster@1
|
511 /** |
webmaster@1
|
512 * Retrieve the current page from the cache. |
webmaster@1
|
513 * |
webmaster@1
|
514 * Note: we do not serve cached pages when status messages are waiting (from |
webmaster@1
|
515 * a redirected form submission which was completed). |
webmaster@1
|
516 * |
webmaster@1
|
517 * @param $status_only |
webmaster@1
|
518 * When set to TRUE, retrieve the status of the page cache only |
webmaster@1
|
519 * (whether it was started in this request or not). |
webmaster@1
|
520 */ |
webmaster@1
|
521 function page_get_cache($status_only = FALSE) { |
webmaster@1
|
522 static $status = FALSE; |
webmaster@1
|
523 global $user, $base_root; |
webmaster@1
|
524 |
webmaster@1
|
525 if ($status_only) { |
webmaster@1
|
526 return $status; |
webmaster@1
|
527 } |
webmaster@1
|
528 $cache = NULL; |
webmaster@1
|
529 |
webmaster@1
|
530 if (!$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET' && count(drupal_set_message()) == 0) { |
webmaster@1
|
531 $cache = cache_get($base_root . request_uri(), 'cache_page'); |
webmaster@1
|
532 |
webmaster@1
|
533 if (empty($cache)) { |
webmaster@1
|
534 ob_start(); |
webmaster@1
|
535 $status = TRUE; |
webmaster@1
|
536 } |
webmaster@1
|
537 } |
webmaster@1
|
538 |
webmaster@1
|
539 return $cache; |
webmaster@1
|
540 } |
webmaster@1
|
541 |
webmaster@1
|
542 /** |
webmaster@1
|
543 * Call all init or exit hooks without including all modules. |
webmaster@1
|
544 * |
webmaster@1
|
545 * @param $hook |
webmaster@1
|
546 * The name of the bootstrap hook we wish to invoke. |
webmaster@1
|
547 */ |
webmaster@1
|
548 function bootstrap_invoke_all($hook) { |
webmaster@1
|
549 foreach (module_list(TRUE, TRUE) as $module) { |
webmaster@1
|
550 drupal_load('module', $module); |
webmaster@1
|
551 module_invoke($module, $hook); |
webmaster@1
|
552 } |
webmaster@1
|
553 } |
webmaster@1
|
554 |
webmaster@1
|
555 /** |
webmaster@1
|
556 * Includes a file with the provided type and name. This prevents |
webmaster@1
|
557 * including a theme, engine, module, etc., more than once. |
webmaster@1
|
558 * |
webmaster@1
|
559 * @param $type |
webmaster@1
|
560 * The type of item to load (i.e. theme, theme_engine, module). |
webmaster@1
|
561 * @param $name |
webmaster@1
|
562 * The name of the item to load. |
webmaster@1
|
563 * |
webmaster@1
|
564 * @return |
webmaster@1
|
565 * TRUE if the item is loaded or has already been loaded. |
webmaster@1
|
566 */ |
webmaster@1
|
567 function drupal_load($type, $name) { |
webmaster@1
|
568 static $files = array(); |
webmaster@1
|
569 |
webmaster@1
|
570 if (isset($files[$type][$name])) { |
webmaster@1
|
571 return TRUE; |
webmaster@1
|
572 } |
webmaster@1
|
573 |
webmaster@1
|
574 $filename = drupal_get_filename($type, $name); |
webmaster@1
|
575 |
webmaster@1
|
576 if ($filename) { |
webmaster@1
|
577 include_once "./$filename"; |
webmaster@1
|
578 $files[$type][$name] = TRUE; |
webmaster@1
|
579 |
webmaster@1
|
580 return TRUE; |
webmaster@1
|
581 } |
webmaster@1
|
582 |
webmaster@1
|
583 return FALSE; |
webmaster@1
|
584 } |
webmaster@1
|
585 |
webmaster@1
|
586 /** |
webmaster@1
|
587 * Set HTTP headers in preparation for a page response. |
webmaster@1
|
588 * |
webmaster@1
|
589 * Authenticated users are always given a 'no-cache' header, and will |
webmaster@1
|
590 * fetch a fresh page on every request. This prevents authenticated |
webmaster@1
|
591 * users seeing locally cached pages that show them as logged out. |
webmaster@1
|
592 * |
webmaster@1
|
593 * @see page_set_cache() |
webmaster@1
|
594 */ |
webmaster@1
|
595 function drupal_page_header() { |
webmaster@1
|
596 header("Expires: Sun, 19 Nov 1978 05:00:00 GMT"); |
webmaster@1
|
597 header("Last-Modified: ". gmdate("D, d M Y H:i:s") ." GMT"); |
webmaster@1
|
598 header("Cache-Control: store, no-cache, must-revalidate"); |
webmaster@1
|
599 header("Cache-Control: post-check=0, pre-check=0", FALSE); |
webmaster@1
|
600 } |
webmaster@1
|
601 |
webmaster@1
|
602 /** |
webmaster@1
|
603 * Set HTTP headers in preparation for a cached page response. |
webmaster@1
|
604 * |
webmaster@1
|
605 * The general approach here is that anonymous users can keep a local |
webmaster@1
|
606 * cache of the page, but must revalidate it on every request. Then, |
webmaster@1
|
607 * they are given a '304 Not Modified' response as long as they stay |
webmaster@1
|
608 * logged out and the page has not been modified. |
webmaster@1
|
609 * |
webmaster@1
|
610 */ |
webmaster@1
|
611 function drupal_page_cache_header($cache) { |
webmaster@1
|
612 // Set default values: |
webmaster@1
|
613 $last_modified = gmdate('D, d M Y H:i:s', $cache->created) .' GMT'; |
webmaster@1
|
614 $etag = '"'. md5($last_modified) .'"'; |
webmaster@1
|
615 |
webmaster@1
|
616 // See if the client has provided the required HTTP headers: |
webmaster@1
|
617 $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : FALSE; |
webmaster@1
|
618 $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE; |
webmaster@1
|
619 |
webmaster@1
|
620 if ($if_modified_since && $if_none_match |
webmaster@1
|
621 && $if_none_match == $etag // etag must match |
webmaster@1
|
622 && $if_modified_since == $last_modified) { // if-modified-since must match |
webmaster@1
|
623 header('HTTP/1.1 304 Not Modified'); |
webmaster@1
|
624 // All 304 responses must send an etag if the 200 response for the same object contained an etag |
webmaster@1
|
625 header("Etag: $etag"); |
webmaster@13
|
626 return; |
webmaster@1
|
627 } |
webmaster@1
|
628 |
webmaster@1
|
629 // Send appropriate response: |
webmaster@1
|
630 header("Last-Modified: $last_modified"); |
webmaster@1
|
631 header("ETag: $etag"); |
webmaster@1
|
632 |
webmaster@1
|
633 // The following headers force validation of cache: |
webmaster@1
|
634 header("Expires: Sun, 19 Nov 1978 05:00:00 GMT"); |
webmaster@1
|
635 header("Cache-Control: must-revalidate"); |
webmaster@1
|
636 |
webmaster@1
|
637 if (variable_get('page_compression', TRUE)) { |
webmaster@1
|
638 // Determine if the browser accepts gzipped data. |
webmaster@1
|
639 if (@strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === FALSE && function_exists('gzencode')) { |
webmaster@1
|
640 // Strip the gzip header and run uncompress. |
webmaster@1
|
641 $cache->data = gzinflate(substr(substr($cache->data, 10), 0, -8)); |
webmaster@1
|
642 } |
webmaster@1
|
643 elseif (function_exists('gzencode')) { |
webmaster@1
|
644 header('Content-Encoding: gzip'); |
webmaster@1
|
645 } |
webmaster@1
|
646 } |
webmaster@1
|
647 |
webmaster@1
|
648 // Send the original request's headers. We send them one after |
webmaster@1
|
649 // another so PHP's header() function can deal with duplicate |
webmaster@1
|
650 // headers. |
webmaster@1
|
651 $headers = explode("\n", $cache->headers); |
webmaster@1
|
652 foreach ($headers as $header) { |
webmaster@1
|
653 header($header); |
webmaster@1
|
654 } |
webmaster@1
|
655 |
webmaster@1
|
656 print $cache->data; |
webmaster@1
|
657 } |
webmaster@1
|
658 |
webmaster@1
|
659 /** |
webmaster@1
|
660 * Define the critical hooks that force modules to always be loaded. |
webmaster@1
|
661 */ |
webmaster@1
|
662 function bootstrap_hooks() { |
webmaster@1
|
663 return array('boot', 'exit'); |
webmaster@1
|
664 } |
webmaster@1
|
665 |
webmaster@1
|
666 /** |
webmaster@1
|
667 * Unserializes and appends elements from a serialized string. |
webmaster@1
|
668 * |
webmaster@1
|
669 * @param $obj |
webmaster@1
|
670 * The object to which the elements are appended. |
webmaster@1
|
671 * @param $field |
webmaster@1
|
672 * The attribute of $obj whose value should be unserialized. |
webmaster@1
|
673 */ |
webmaster@1
|
674 function drupal_unpack($obj, $field = 'data') { |
webmaster@1
|
675 if ($obj->$field && $data = unserialize($obj->$field)) { |
webmaster@1
|
676 foreach ($data as $key => $value) { |
webmaster@1
|
677 if (!isset($obj->$key)) { |
webmaster@1
|
678 $obj->$key = $value; |
webmaster@1
|
679 } |
webmaster@1
|
680 } |
webmaster@1
|
681 } |
webmaster@1
|
682 return $obj; |
webmaster@1
|
683 } |
webmaster@1
|
684 |
webmaster@1
|
685 /** |
webmaster@1
|
686 * Return the URI of the referring page. |
webmaster@1
|
687 */ |
webmaster@1
|
688 function referer_uri() { |
webmaster@1
|
689 if (isset($_SERVER['HTTP_REFERER'])) { |
webmaster@1
|
690 return $_SERVER['HTTP_REFERER']; |
webmaster@1
|
691 } |
webmaster@1
|
692 } |
webmaster@1
|
693 |
webmaster@1
|
694 /** |
webmaster@1
|
695 * Encode special characters in a plain-text string for display as HTML. |
webmaster@1
|
696 * |
webmaster@1
|
697 * Uses drupal_validate_utf8 to prevent cross site scripting attacks on |
webmaster@1
|
698 * Internet Explorer 6. |
webmaster@1
|
699 */ |
webmaster@1
|
700 function check_plain($text) { |
webmaster@1
|
701 return drupal_validate_utf8($text) ? htmlspecialchars($text, ENT_QUOTES) : ''; |
webmaster@1
|
702 } |
webmaster@1
|
703 |
webmaster@1
|
704 /** |
webmaster@1
|
705 * Checks whether a string is valid UTF-8. |
webmaster@1
|
706 * |
webmaster@1
|
707 * All functions designed to filter input should use drupal_validate_utf8 |
webmaster@1
|
708 * to ensure they operate on valid UTF-8 strings to prevent bypass of the |
webmaster@1
|
709 * filter. |
webmaster@1
|
710 * |
webmaster@1
|
711 * When text containing an invalid UTF-8 lead byte (0xC0 - 0xFF) is presented |
webmaster@1
|
712 * as UTF-8 to Internet Explorer 6, the program may misinterpret subsequent |
webmaster@1
|
713 * bytes. When these subsequent bytes are HTML control characters such as |
webmaster@1
|
714 * quotes or angle brackets, parts of the text that were deemed safe by filters |
webmaster@1
|
715 * end up in locations that are potentially unsafe; An onerror attribute that |
webmaster@1
|
716 * is outside of a tag, and thus deemed safe by a filter, can be interpreted |
webmaster@1
|
717 * by the browser as if it were inside the tag. |
webmaster@1
|
718 * |
webmaster@1
|
719 * This function exploits preg_match behaviour (since PHP 4.3.5) when used |
webmaster@1
|
720 * with the u modifier, as a fast way to find invalid UTF-8. When the matched |
webmaster@1
|
721 * string contains an invalid byte sequence, it will fail silently. |
webmaster@1
|
722 * |
webmaster@1
|
723 * preg_match may not fail on 4 and 5 octet sequences, even though they |
webmaster@1
|
724 * are not supported by the specification. |
webmaster@1
|
725 * |
webmaster@1
|
726 * The specific preg_match behaviour is present since PHP 4.3.5. |
webmaster@1
|
727 * |
webmaster@1
|
728 * @param $text |
webmaster@1
|
729 * The text to check. |
webmaster@1
|
730 * @return |
webmaster@1
|
731 * TRUE if the text is valid UTF-8, FALSE if not. |
webmaster@1
|
732 */ |
webmaster@1
|
733 function drupal_validate_utf8($text) { |
webmaster@1
|
734 if (strlen($text) == 0) { |
webmaster@1
|
735 return TRUE; |
webmaster@1
|
736 } |
webmaster@1
|
737 return (preg_match('/^./us', $text) == 1); |
webmaster@1
|
738 } |
webmaster@1
|
739 |
webmaster@1
|
740 /** |
webmaster@1
|
741 * Since $_SERVER['REQUEST_URI'] is only available on Apache, we |
webmaster@1
|
742 * generate an equivalent using other environment variables. |
webmaster@1
|
743 */ |
webmaster@1
|
744 function request_uri() { |
webmaster@1
|
745 |
webmaster@1
|
746 if (isset($_SERVER['REQUEST_URI'])) { |
webmaster@1
|
747 $uri = $_SERVER['REQUEST_URI']; |
webmaster@1
|
748 } |
webmaster@1
|
749 else { |
webmaster@1
|
750 if (isset($_SERVER['argv'])) { |
webmaster@1
|
751 $uri = $_SERVER['SCRIPT_NAME'] .'?'. $_SERVER['argv'][0]; |
webmaster@1
|
752 } |
webmaster@1
|
753 elseif (isset($_SERVER['QUERY_STRING'])) { |
webmaster@1
|
754 $uri = $_SERVER['SCRIPT_NAME'] .'?'. $_SERVER['QUERY_STRING']; |
webmaster@1
|
755 } |
webmaster@1
|
756 else { |
webmaster@1
|
757 $uri = $_SERVER['SCRIPT_NAME']; |
webmaster@1
|
758 } |
webmaster@1
|
759 } |
webmaster@1
|
760 |
webmaster@1
|
761 return $uri; |
webmaster@1
|
762 } |
webmaster@1
|
763 |
webmaster@1
|
764 /** |
webmaster@1
|
765 * Log a system message. |
webmaster@1
|
766 * |
webmaster@1
|
767 * @param $type |
webmaster@1
|
768 * The category to which this message belongs. |
webmaster@1
|
769 * @param $message |
webmaster@1
|
770 * The message to store in the log. See t() for documentation |
webmaster@1
|
771 * on how $message and $variables interact. Keep $message |
webmaster@1
|
772 * translatable by not concatenating dynamic values into it! |
webmaster@1
|
773 * @param $variables |
webmaster@1
|
774 * Array of variables to replace in the message on display or |
webmaster@1
|
775 * NULL if message is already translated or not possible to |
webmaster@1
|
776 * translate. |
webmaster@1
|
777 * @param $severity |
webmaster@1
|
778 * The severity of the message, as per RFC 3164 |
webmaster@1
|
779 * @param $link |
webmaster@1
|
780 * A link to associate with the message. |
webmaster@1
|
781 * |
webmaster@1
|
782 * @see watchdog_severity_levels() |
webmaster@1
|
783 */ |
webmaster@1
|
784 function watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL) { |
webmaster@1
|
785 global $user, $base_root; |
webmaster@1
|
786 |
webmaster@1
|
787 // Prepare the fields to be logged |
webmaster@1
|
788 $log_message = array( |
webmaster@1
|
789 'type' => $type, |
webmaster@1
|
790 'message' => $message, |
webmaster@1
|
791 'variables' => $variables, |
webmaster@1
|
792 'severity' => $severity, |
webmaster@1
|
793 'link' => $link, |
webmaster@1
|
794 'user' => $user, |
webmaster@1
|
795 'request_uri' => $base_root . request_uri(), |
webmaster@1
|
796 'referer' => referer_uri(), |
webmaster@1
|
797 'ip' => ip_address(), |
webmaster@1
|
798 'timestamp' => time(), |
webmaster@1
|
799 ); |
webmaster@1
|
800 |
webmaster@1
|
801 // Call the logging hooks to log/process the message |
webmaster@1
|
802 foreach (module_implements('watchdog', TRUE) as $module) { |
webmaster@1
|
803 module_invoke($module, 'watchdog', $log_message); |
webmaster@1
|
804 } |
webmaster@1
|
805 } |
webmaster@1
|
806 |
webmaster@1
|
807 /** |
webmaster@1
|
808 * Set a message which reflects the status of the performed operation. |
webmaster@1
|
809 * |
webmaster@1
|
810 * If the function is called with no arguments, this function returns all set |
webmaster@1
|
811 * messages without clearing them. |
webmaster@1
|
812 * |
webmaster@1
|
813 * @param $message |
webmaster@1
|
814 * The message should begin with a capital letter and always ends with a |
webmaster@1
|
815 * period '.'. |
webmaster@1
|
816 * @param $type |
webmaster@1
|
817 * The type of the message. One of the following values are possible: |
webmaster@1
|
818 * - 'status' |
webmaster@1
|
819 * - 'warning' |
webmaster@1
|
820 * - 'error' |
webmaster@1
|
821 * @param $repeat |
webmaster@1
|
822 * If this is FALSE and the message is already set, then the message won't |
webmaster@1
|
823 * be repeated. |
webmaster@1
|
824 */ |
webmaster@1
|
825 function drupal_set_message($message = NULL, $type = 'status', $repeat = TRUE) { |
webmaster@1
|
826 if ($message) { |
webmaster@1
|
827 if (!isset($_SESSION['messages'])) { |
webmaster@1
|
828 $_SESSION['messages'] = array(); |
webmaster@1
|
829 } |
webmaster@1
|
830 |
webmaster@1
|
831 if (!isset($_SESSION['messages'][$type])) { |
webmaster@1
|
832 $_SESSION['messages'][$type] = array(); |
webmaster@1
|
833 } |
webmaster@1
|
834 |
webmaster@1
|
835 if ($repeat || !in_array($message, $_SESSION['messages'][$type])) { |
webmaster@1
|
836 $_SESSION['messages'][$type][] = $message; |
webmaster@1
|
837 } |
webmaster@1
|
838 } |
webmaster@1
|
839 |
webmaster@1
|
840 // messages not set when DB connection fails |
webmaster@1
|
841 return isset($_SESSION['messages']) ? $_SESSION['messages'] : NULL; |
webmaster@1
|
842 } |
webmaster@1
|
843 |
webmaster@1
|
844 /** |
webmaster@1
|
845 * Return all messages that have been set. |
webmaster@1
|
846 * |
webmaster@1
|
847 * @param $type |
webmaster@1
|
848 * (optional) Only return messages of this type. |
webmaster@1
|
849 * @param $clear_queue |
webmaster@1
|
850 * (optional) Set to FALSE if you do not want to clear the messages queue |
webmaster@1
|
851 * @return |
webmaster@1
|
852 * An associative array, the key is the message type, the value an array |
webmaster@1
|
853 * of messages. If the $type parameter is passed, you get only that type, |
webmaster@1
|
854 * or an empty array if there are no such messages. If $type is not passed, |
webmaster@1
|
855 * all message types are returned, or an empty array if none exist. |
webmaster@1
|
856 */ |
webmaster@1
|
857 function drupal_get_messages($type = NULL, $clear_queue = TRUE) { |
webmaster@1
|
858 if ($messages = drupal_set_message()) { |
webmaster@1
|
859 if ($type) { |
webmaster@1
|
860 if ($clear_queue) { |
webmaster@1
|
861 unset($_SESSION['messages'][$type]); |
webmaster@1
|
862 } |
webmaster@1
|
863 if (isset($messages[$type])) { |
webmaster@1
|
864 return array($type => $messages[$type]); |
webmaster@1
|
865 } |
webmaster@1
|
866 } |
webmaster@1
|
867 else { |
webmaster@1
|
868 if ($clear_queue) { |
webmaster@1
|
869 unset($_SESSION['messages']); |
webmaster@1
|
870 } |
webmaster@1
|
871 return $messages; |
webmaster@1
|
872 } |
webmaster@1
|
873 } |
webmaster@1
|
874 return array(); |
webmaster@1
|
875 } |
webmaster@1
|
876 |
webmaster@1
|
877 /** |
webmaster@1
|
878 * Perform an access check for a given mask and rule type. Rules are usually |
webmaster@1
|
879 * created via admin/user/rules page. |
webmaster@1
|
880 * |
webmaster@1
|
881 * If any allow rule matches, access is allowed. Otherwise, if any deny rule |
webmaster@1
|
882 * matches, access is denied. If no rule matches, access is allowed. |
webmaster@1
|
883 * |
webmaster@1
|
884 * @param $type string |
webmaster@1
|
885 * Type of access to check: Allowed values are: |
webmaster@1
|
886 * - 'host': host name or IP address |
webmaster@1
|
887 * - 'mail': e-mail address |
webmaster@1
|
888 * - 'user': username |
webmaster@1
|
889 * @param $mask string |
webmaster@1
|
890 * String or mask to test: '_' matches any character, '%' matches any |
webmaster@1
|
891 * number of characters. |
webmaster@1
|
892 * @return bool |
webmaster@1
|
893 * TRUE if access is denied, FALSE if access is allowed. |
webmaster@1
|
894 */ |
webmaster@1
|
895 function drupal_is_denied($type, $mask) { |
webmaster@1
|
896 // Because this function is called for every page request, both cached |
webmaster@1
|
897 // and non-cached pages, we tried to optimize it as much as possible. |
webmaster@1
|
898 // We deny access if the only matching records in the {access} table have |
webmaster@1
|
899 // status 0 (deny). If any have status 1 (allow), or if there are no |
webmaster@1
|
900 // matching records, we allow access. |
webmaster@1
|
901 $sql = "SELECT 1 FROM {access} WHERE type = '%s' AND LOWER('%s') LIKE LOWER(mask) AND status = %d"; |
webmaster@1
|
902 return db_result(db_query_range($sql, $type, $mask, 0, 0, 1)) && !db_result(db_query_range($sql, $type, $mask, 1, 0, 1)); |
webmaster@1
|
903 } |
webmaster@1
|
904 |
webmaster@1
|
905 /** |
webmaster@1
|
906 * Generates a default anonymous $user object. |
webmaster@1
|
907 * |
webmaster@1
|
908 * @return Object - the user object. |
webmaster@1
|
909 */ |
webmaster@1
|
910 function drupal_anonymous_user($session = '') { |
webmaster@1
|
911 $user = new stdClass(); |
webmaster@1
|
912 $user->uid = 0; |
webmaster@1
|
913 $user->hostname = ip_address(); |
webmaster@1
|
914 $user->roles = array(); |
webmaster@1
|
915 $user->roles[DRUPAL_ANONYMOUS_RID] = 'anonymous user'; |
webmaster@1
|
916 $user->session = $session; |
webmaster@1
|
917 $user->cache = 0; |
webmaster@1
|
918 return $user; |
webmaster@1
|
919 } |
webmaster@1
|
920 |
webmaster@1
|
921 /** |
webmaster@1
|
922 * A string describing a phase of Drupal to load. Each phase adds to the |
webmaster@1
|
923 * previous one, so invoking a later phase automatically runs the earlier |
webmaster@1
|
924 * phases too. The most important usage is that if you want to access the |
webmaster@1
|
925 * Drupal database from a script without loading anything else, you can |
webmaster@1
|
926 * include bootstrap.inc, and call drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE). |
webmaster@1
|
927 * |
webmaster@1
|
928 * @param $phase |
webmaster@1
|
929 * A constant. Allowed values are: |
webmaster@1
|
930 * DRUPAL_BOOTSTRAP_CONFIGURATION: initialize configuration. |
webmaster@1
|
931 * DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE: try to call a non-database cache fetch routine. |
webmaster@1
|
932 * DRUPAL_BOOTSTRAP_DATABASE: initialize database layer. |
webmaster@1
|
933 * DRUPAL_BOOTSTRAP_ACCESS: identify and reject banned hosts. |
webmaster@1
|
934 * DRUPAL_BOOTSTRAP_SESSION: initialize session handling. |
webmaster@1
|
935 * DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE: load bootstrap.inc and module.inc, start |
webmaster@1
|
936 * the variable system and try to serve a page from the cache. |
webmaster@1
|
937 * DRUPAL_BOOTSTRAP_LANGUAGE: identify the language used on the page. |
webmaster@1
|
938 * DRUPAL_BOOTSTRAP_PATH: set $_GET['q'] to Drupal path of request. |
webmaster@1
|
939 * DRUPAL_BOOTSTRAP_FULL: Drupal is fully loaded, validate and fix input data. |
webmaster@1
|
940 */ |
webmaster@1
|
941 function drupal_bootstrap($phase) { |
webmaster@1
|
942 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), $phase_index = 0; |
webmaster@1
|
943 |
webmaster@1
|
944 while ($phase >= $phase_index && isset($phases[$phase_index])) { |
webmaster@1
|
945 $current_phase = $phases[$phase_index]; |
webmaster@1
|
946 unset($phases[$phase_index++]); |
webmaster@1
|
947 _drupal_bootstrap($current_phase); |
webmaster@1
|
948 } |
webmaster@1
|
949 } |
webmaster@1
|
950 |
webmaster@1
|
951 function _drupal_bootstrap($phase) { |
webmaster@1
|
952 global $conf; |
webmaster@1
|
953 |
webmaster@1
|
954 switch ($phase) { |
webmaster@1
|
955 |
webmaster@1
|
956 case DRUPAL_BOOTSTRAP_CONFIGURATION: |
webmaster@1
|
957 drupal_unset_globals(); |
webmaster@1
|
958 // Start a page timer: |
webmaster@1
|
959 timer_start('page'); |
webmaster@1
|
960 // Initialize the configuration |
webmaster@1
|
961 conf_init(); |
webmaster@1
|
962 break; |
webmaster@1
|
963 |
webmaster@1
|
964 case DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE: |
webmaster@1
|
965 // Allow specifying special cache handlers in settings.php, like |
webmaster@1
|
966 // using memcached or files for storing cache information. |
webmaster@1
|
967 require_once variable_get('cache_inc', './includes/cache.inc'); |
webmaster@1
|
968 // If the page_cache_fastpath is set to TRUE in settings.php and |
webmaster@1
|
969 // page_cache_fastpath (implemented in the special implementation of |
webmaster@1
|
970 // cache.inc) printed the page and indicated this with a returned TRUE |
webmaster@1
|
971 // then we are done. |
webmaster@1
|
972 if (variable_get('page_cache_fastpath', FALSE) && page_cache_fastpath()) { |
webmaster@1
|
973 exit; |
webmaster@1
|
974 } |
webmaster@1
|
975 break; |
webmaster@1
|
976 |
webmaster@1
|
977 case DRUPAL_BOOTSTRAP_DATABASE: |
webmaster@1
|
978 // Initialize the default database. |
webmaster@1
|
979 require_once './includes/database.inc'; |
webmaster@1
|
980 db_set_active(); |
webmaster@1
|
981 break; |
webmaster@1
|
982 |
webmaster@1
|
983 case DRUPAL_BOOTSTRAP_ACCESS: |
webmaster@1
|
984 // Deny access to hosts which were banned - t() is not yet available. |
webmaster@1
|
985 if (drupal_is_denied('host', ip_address())) { |
webmaster@1
|
986 header('HTTP/1.1 403 Forbidden'); |
webmaster@1
|
987 print 'Sorry, '. check_plain(ip_address()) .' has been banned.'; |
webmaster@1
|
988 exit(); |
webmaster@1
|
989 } |
webmaster@1
|
990 break; |
webmaster@1
|
991 |
webmaster@1
|
992 case DRUPAL_BOOTSTRAP_SESSION: |
webmaster@1
|
993 require_once variable_get('session_inc', './includes/session.inc'); |
webmaster@1
|
994 session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy_sid', 'sess_gc'); |
webmaster@1
|
995 session_start(); |
webmaster@1
|
996 break; |
webmaster@1
|
997 |
webmaster@1
|
998 case DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE: |
webmaster@1
|
999 // Initialize configuration variables, using values from settings.php if available. |
webmaster@1
|
1000 $conf = variable_init(isset($conf) ? $conf : array()); |
webmaster@1
|
1001 // Load module handling. |
webmaster@1
|
1002 require_once './includes/module.inc'; |
webmaster@1
|
1003 $cache_mode = variable_get('cache', CACHE_DISABLED); |
webmaster@1
|
1004 // Get the page from the cache. |
webmaster@1
|
1005 $cache = $cache_mode == CACHE_DISABLED ? '' : page_get_cache(); |
webmaster@1
|
1006 // If the skipping of the bootstrap hooks is not enforced, call hook_boot. |
webmaster@1
|
1007 if ($cache_mode != CACHE_AGGRESSIVE) { |
webmaster@1
|
1008 bootstrap_invoke_all('boot'); |
webmaster@1
|
1009 } |
webmaster@1
|
1010 // If there is a cached page, display it. |
webmaster@1
|
1011 if ($cache) { |
webmaster@1
|
1012 drupal_page_cache_header($cache); |
webmaster@1
|
1013 // If the skipping of the bootstrap hooks is not enforced, call hook_exit. |
webmaster@1
|
1014 if ($cache_mode != CACHE_AGGRESSIVE) { |
webmaster@1
|
1015 bootstrap_invoke_all('exit'); |
webmaster@1
|
1016 } |
webmaster@1
|
1017 // We are done. |
webmaster@1
|
1018 exit; |
webmaster@1
|
1019 } |
webmaster@1
|
1020 // Prepare for non-cached page workflow. |
webmaster@1
|
1021 drupal_page_header(); |
webmaster@1
|
1022 break; |
webmaster@1
|
1023 |
webmaster@1
|
1024 case DRUPAL_BOOTSTRAP_LANGUAGE: |
webmaster@1
|
1025 drupal_init_language(); |
webmaster@1
|
1026 break; |
webmaster@1
|
1027 |
webmaster@1
|
1028 case DRUPAL_BOOTSTRAP_PATH: |
webmaster@1
|
1029 require_once './includes/path.inc'; |
webmaster@1
|
1030 // Initialize $_GET['q'] prior to loading modules and invoking hook_init(). |
webmaster@1
|
1031 drupal_init_path(); |
webmaster@1
|
1032 break; |
webmaster@1
|
1033 |
webmaster@1
|
1034 case DRUPAL_BOOTSTRAP_FULL: |
webmaster@1
|
1035 require_once './includes/common.inc'; |
webmaster@1
|
1036 _drupal_bootstrap_full(); |
webmaster@1
|
1037 break; |
webmaster@1
|
1038 } |
webmaster@1
|
1039 } |
webmaster@1
|
1040 |
webmaster@1
|
1041 /** |
webmaster@1
|
1042 * Enables use of the theme system without requiring database access. |
webmaster@1
|
1043 * |
webmaster@1
|
1044 * Loads and initializes the theme system for site installs, updates and when |
webmaster@1
|
1045 * the site is in off-line mode. This also applies when the database fails. |
webmaster@1
|
1046 * |
webmaster@1
|
1047 * @see _drupal_maintenance_theme() |
webmaster@1
|
1048 */ |
webmaster@1
|
1049 function drupal_maintenance_theme() { |
webmaster@1
|
1050 require_once './includes/theme.maintenance.inc'; |
webmaster@1
|
1051 _drupal_maintenance_theme(); |
webmaster@1
|
1052 } |
webmaster@1
|
1053 |
webmaster@1
|
1054 /** |
webmaster@1
|
1055 * Return the name of the localisation function. Use in code that needs to |
webmaster@1
|
1056 * run both during installation and normal operation. |
webmaster@1
|
1057 */ |
webmaster@1
|
1058 function get_t() { |
webmaster@1
|
1059 static $t; |
webmaster@1
|
1060 if (is_null($t)) { |
webmaster@1
|
1061 $t = function_exists('install_main') ? 'st' : 't'; |
webmaster@1
|
1062 } |
webmaster@1
|
1063 return $t; |
webmaster@1
|
1064 } |
webmaster@1
|
1065 |
webmaster@1
|
1066 /** |
webmaster@1
|
1067 * Choose a language for the current page, based on site and user preferences. |
webmaster@1
|
1068 */ |
webmaster@1
|
1069 function drupal_init_language() { |
webmaster@1
|
1070 global $language, $user; |
webmaster@1
|
1071 |
webmaster@1
|
1072 // Ensure the language is correctly returned, even without multilanguage support. |
webmaster@1
|
1073 // Useful for eg. XML/HTML 'lang' attributes. |
webmaster@1
|
1074 if (variable_get('language_count', 1) == 1) { |
webmaster@1
|
1075 $language = language_default(); |
webmaster@1
|
1076 } |
webmaster@1
|
1077 else { |
webmaster@1
|
1078 include_once './includes/language.inc'; |
webmaster@1
|
1079 $language = language_initialize(); |
webmaster@1
|
1080 } |
webmaster@1
|
1081 } |
webmaster@1
|
1082 |
webmaster@1
|
1083 /** |
webmaster@1
|
1084 * Get a list of languages set up indexed by the specified key |
webmaster@1
|
1085 * |
webmaster@1
|
1086 * @param $field The field to index the list with. |
webmaster@1
|
1087 * @param $reset Boolean to request a reset of the list. |
webmaster@1
|
1088 */ |
webmaster@1
|
1089 function language_list($field = 'language', $reset = FALSE) { |
webmaster@1
|
1090 static $languages = NULL; |
webmaster@1
|
1091 |
webmaster@1
|
1092 // Reset language list |
webmaster@1
|
1093 if ($reset) { |
webmaster@1
|
1094 $languages = NULL; |
webmaster@1
|
1095 } |
webmaster@1
|
1096 |
webmaster@1
|
1097 // Init language list |
webmaster@1
|
1098 if (!isset($languages)) { |
webmaster@1
|
1099 if (variable_get('language_count', 1) > 1 || module_exists('locale')) { |
webmaster@1
|
1100 $result = db_query('SELECT * FROM {languages} ORDER BY weight ASC, name ASC'); |
webmaster@1
|
1101 while ($row = db_fetch_object($result)) { |
webmaster@1
|
1102 $languages['language'][$row->language] = $row; |
webmaster@1
|
1103 } |
webmaster@1
|
1104 } |
webmaster@1
|
1105 else { |
webmaster@1
|
1106 // No locale module, so use the default language only. |
webmaster@1
|
1107 $default = language_default(); |
webmaster@1
|
1108 $languages['language'][$default->language] = $default; |
webmaster@1
|
1109 } |
webmaster@1
|
1110 } |
webmaster@1
|
1111 |
webmaster@1
|
1112 // Return the array indexed by the right field |
webmaster@1
|
1113 if (!isset($languages[$field])) { |
webmaster@1
|
1114 $languages[$field] = array(); |
webmaster@1
|
1115 foreach ($languages['language'] as $lang) { |
webmaster@1
|
1116 // Some values should be collected into an array |
webmaster@1
|
1117 if (in_array($field, array('enabled', 'weight'))) { |
webmaster@1
|
1118 $languages[$field][$lang->$field][$lang->language] = $lang; |
webmaster@1
|
1119 } |
webmaster@1
|
1120 else { |
webmaster@1
|
1121 $languages[$field][$lang->$field] = $lang; |
webmaster@1
|
1122 } |
webmaster@1
|
1123 } |
webmaster@1
|
1124 } |
webmaster@1
|
1125 return $languages[$field]; |
webmaster@1
|
1126 } |
webmaster@1
|
1127 |
webmaster@1
|
1128 /** |
webmaster@1
|
1129 * Default language used on the site |
webmaster@1
|
1130 * |
webmaster@1
|
1131 * @param $property |
webmaster@1
|
1132 * Optional property of the language object to return |
webmaster@1
|
1133 */ |
webmaster@1
|
1134 function language_default($property = NULL) { |
webmaster@1
|
1135 $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' => '')); |
webmaster@1
|
1136 return $property ? $language->$property : $language; |
webmaster@1
|
1137 } |
webmaster@1
|
1138 |
webmaster@1
|
1139 /** |
webmaster@1
|
1140 * If Drupal is behind a reverse proxy, we use the X-Forwarded-For header |
webmaster@1
|
1141 * instead of $_SERVER['REMOTE_ADDR'], which would be the IP address |
webmaster@1
|
1142 * of the proxy server, and not the client's. |
webmaster@1
|
1143 * |
webmaster@1
|
1144 * @return |
webmaster@1
|
1145 * IP address of client machine, adjusted for reverse proxy. |
webmaster@1
|
1146 */ |
webmaster@1
|
1147 function ip_address() { |
webmaster@1
|
1148 static $ip_address = NULL; |
webmaster@1
|
1149 |
webmaster@1
|
1150 if (!isset($ip_address)) { |
webmaster@1
|
1151 $ip_address = $_SERVER['REMOTE_ADDR']; |
webmaster@1
|
1152 if (variable_get('reverse_proxy', 0) && array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) { |
webmaster@1
|
1153 // If an array of known reverse proxy IPs is provided, then trust |
webmaster@1
|
1154 // the XFF header if request really comes from one of them. |
webmaster@1
|
1155 $reverse_proxy_addresses = variable_get('reverse_proxy_addresses', array()); |
webmaster@1
|
1156 if (!empty($reverse_proxy_addresses) && in_array($ip_address, $reverse_proxy_addresses, TRUE)) { |
webmaster@1
|
1157 // If there are several arguments, we need to check the most |
webmaster@1
|
1158 // recently added one, i.e. the last one. |
webmaster@1
|
1159 $ip_address = array_pop(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])); |
webmaster@1
|
1160 } |
webmaster@1
|
1161 } |
webmaster@1
|
1162 } |
webmaster@1
|
1163 |
webmaster@1
|
1164 return $ip_address; |
webmaster@1
|
1165 } |