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