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