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