Project

General

Profile

Revision b0dc3a2e

Added by Julien Enselme over 7 years ago

Update to Drupal 7.52

View differences:

drupal7/includes/bootstrap.inc
8 8
/**
9 9
 * The current system version.
10 10
 */
11
define('VERSION', '7.44');
11
define('VERSION', '7.52');
12 12

  
13 13
/**
14 14
 * Core API compatibility.
......
828 828
 * @param $filename
829 829
 *   The filename of the item if it is to be set explicitly rather
830 830
 *   than by consulting the database.
831
 * @param bool $trigger_error
832
 *   Whether to trigger an error when a file is missing or has unexpectedly
833
 *   moved. This defaults to TRUE, but can be set to FALSE by calling code that
834
 *   merely wants to check whether an item exists in the filesystem.
831 835
 *
832 836
 * @return
833 837
 *   The filename of the requested item or NULL if the item is not found.
834 838
 */
835
function drupal_get_filename($type, $name, $filename = NULL) {
839
function drupal_get_filename($type, $name, $filename = NULL, $trigger_error = TRUE) {
840
  // The $files static variable will hold the locations of all requested files.
841
  // We can be sure that any file listed in this static variable actually
842
  // exists as all additions have gone through a file_exists() check.
836 843
  // The location of files will not change during the request, so do not use
837 844
  // drupal_static().
838
  static $files = array(), $dirs = array();
845
  static $files = array();
839 846

  
840 847
  // Profiles are a special case: they have a fixed location and naming.
841 848
  if ($type == 'profile') {
......
847 854
  }
848 855

  
849 856
  if (!empty($filename) && file_exists($filename)) {
857
    // Prime the static cache with the provided filename.
850 858
    $files[$type][$name] = $filename;
851 859
  }
852 860
  elseif (isset($files[$type][$name])) {
853
    // nothing
861
    // This item had already been found earlier in the request, either through
862
    // priming of the static cache (for example, in system_list()), through a
863
    // lookup in the {system} table, or through a file scan (cached or not). Do
864
    // nothing.
854 865
  }
855
  // Verify that we have an active database connection, before querying
856
  // the database. This is required because this function is called both
857
  // before we have a database connection (i.e. during installation) and
858
  // when a database connection fails.
859 866
  else {
867
    // Look for the filename listed in the {system} table. Verify that we have
868
    // an active database connection before doing so, since this function is
869
    // called both before we have a database connection (i.e. during
870
    // installation) and when a database connection fails.
871
    $database_unavailable = TRUE;
860 872
    try {
861 873
      if (function_exists('db_query')) {
862 874
        $file = db_query("SELECT filename FROM {system} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type))->fetchField();
863 875
        if ($file !== FALSE && file_exists(DRUPAL_ROOT . '/' . $file)) {
864 876
          $files[$type][$name] = $file;
865 877
        }
878
        $database_unavailable = FALSE;
866 879
      }
867 880
    }
868 881
    catch (Exception $e) {
869 882
      // The database table may not exist because Drupal is not yet installed,
870
      // or the database might be down. We have a fallback for this case so we
871
      // hide the error completely.
883
      // the database might be down, or we may have done a non-database cache
884
      // flush while $conf['page_cache_without_database'] = TRUE and
885
      // $conf['page_cache_invoke_hooks'] = TRUE. We have a fallback for these
886
      // cases so we hide the error completely.
872 887
    }
873
    // Fallback to searching the filesystem if the database could not find the
874
    // file or the file returned by the database is not found.
888
    // Fall back to searching the filesystem if the database could not find the
889
    // file or the file does not exist at the path returned by the database.
875 890
    if (!isset($files[$type][$name])) {
876
      // We have a consistent directory naming: modules, themes...
877
      $dir = $type . 's';
878
      if ($type == 'theme_engine') {
879
        $dir = 'themes/engines';
880
        $extension = 'engine';
881
      }
882
      elseif ($type == 'theme') {
883
        $extension = 'info';
884
      }
885
      else {
886
        $extension = $type;
887
      }
891
      $files[$type][$name] = _drupal_get_filename_fallback($type, $name, $trigger_error, $database_unavailable);
892
    }
893
  }
888 894

  
889
      if (!isset($dirs[$dir][$extension])) {
890
        $dirs[$dir][$extension] = TRUE;
891
        if (!function_exists('drupal_system_listing')) {
892
          require_once DRUPAL_ROOT . '/includes/common.inc';
893
        }
894
        // Scan the appropriate directories for all files with the requested
895
        // extension, not just the file we are currently looking for. This
896
        // prevents unnecessary scans from being repeated when this function is
897
        // called more than once in the same page request.
898
        $matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0);
899
        foreach ($matches as $matched_name => $file) {
900
          $files[$type][$matched_name] = $file->uri;
895
  if (isset($files[$type][$name])) {
896
    return $files[$type][$name];
897
  }
898
}
899

  
900
/**
901
 * Performs a cached file system scan as a fallback when searching for a file.
902
 *
903
 * This function looks for the requested file by triggering a file scan,
904
 * caching the new location if the file has moved and caching the miss
905
 * if the file is missing. If a file had been marked as missing in a previous
906
 * file scan, or if it has been marked as moved and is still in the last known
907
 * location, no new file scan will be performed.
908
 *
909
 * @param string $type
910
 *   The type of the item (theme, theme_engine, module, profile).
911
 * @param string $name
912
 *   The name of the item for which the filename is requested.
913
 * @param bool $trigger_error
914
 *   Whether to trigger an error when a file is missing or has unexpectedly
915
 *   moved.
916
 * @param bool $database_unavailable
917
 *   Whether this function is being called because the Drupal database could
918
 *   not be queried for the file's location.
919
 *
920
 * @return
921
 *   The filename of the requested item or NULL if the item is not found.
922
 *
923
 * @see drupal_get_filename()
924
 */
925
function _drupal_get_filename_fallback($type, $name, $trigger_error, $database_unavailable) {
926
  $file_scans = &_drupal_file_scan_cache();
927
  $filename = NULL;
928

  
929
  // If the cache indicates that the item is missing, or we can verify that the
930
  // item exists in the location the cache says it exists in, use that.
931
  if (isset($file_scans[$type][$name]) && ($file_scans[$type][$name] === FALSE || file_exists($file_scans[$type][$name]))) {
932
    $filename = $file_scans[$type][$name];
933
  }
934
  // Otherwise, perform a new file scan to find the item.
935
  else {
936
    $filename = _drupal_get_filename_perform_file_scan($type, $name);
937
    // Update the static cache, and mark the persistent cache for updating at
938
    // the end of the page request. See drupal_file_scan_write_cache().
939
    $file_scans[$type][$name] = $filename;
940
    $file_scans['#write_cache'] = TRUE;
941
  }
942

  
943
  // If requested, trigger a user-level warning about the missing or
944
  // unexpectedly moved file. If the database was unavailable, do not trigger a
945
  // warning in the latter case, though, since if the {system} table could not
946
  // be queried there is no way to know if the location found here was
947
  // "unexpected" or not.
948
  if ($trigger_error) {
949
    $error_type = $filename === FALSE ? 'missing' : 'moved';
950
    if ($error_type == 'missing' || !$database_unavailable) {
951
      _drupal_get_filename_fallback_trigger_error($type, $name, $error_type);
952
    }
953
  }
954

  
955
  // The cache stores FALSE for files that aren't found (to be able to
956
  // distinguish them from files that have not yet been searched for), but
957
  // drupal_get_filename() expects NULL for these instead, so convert to NULL
958
  // before returning.
959
  if ($filename === FALSE) {
960
    $filename = NULL;
961
  }
962
  return $filename;
963
}
964

  
965
/**
966
 * Returns the current list of cached file system scan results.
967
 *
968
 * @return
969
 *   An associative array tracking the most recent file scan results for all
970
 *   files that have had scans performed. The keys are the type and name of the
971
 *   item that was searched for, and the values can be either:
972
 *   - Boolean FALSE if the item was not found in the file system.
973
 *   - A string pointing to the location where the item was found.
974
 */
975
function &_drupal_file_scan_cache() {
976
  $file_scans = &drupal_static(__FUNCTION__, array());
977

  
978
  // The file scan results are stored in a persistent cache (in addition to the
979
  // static cache) but because this function can be called before the
980
  // persistent cache is available, we must merge any items that were found
981
  // earlier in the page request into the results from the persistent cache.
982
  if (!isset($file_scans['#cache_merge_done'])) {
983
    try {
984
      if (function_exists('cache_get')) {
985
        $cache = cache_get('_drupal_file_scan_cache', 'cache_bootstrap');
986
        if (!empty($cache->data)) {
987
          // File scan results from the current request should take precedence
988
          // over the results from the persistent cache, since they are newer.
989
          $file_scans = drupal_array_merge_deep($cache->data, $file_scans);
901 990
        }
991
        // Set a flag to indicate that the persistent cache does not need to be
992
        // merged again.
993
        $file_scans['#cache_merge_done'] = TRUE;
902 994
      }
903 995
    }
996
    catch (Exception $e) {
997
      // Hide the error.
998
    }
904 999
  }
905 1000

  
906
  if (isset($files[$type][$name])) {
907
    return $files[$type][$name];
1001
  return $file_scans;
1002
}
1003

  
1004
/**
1005
 * Performs a file system scan to search for a system resource.
1006
 *
1007
 * @param $type
1008
 *   The type of the item (theme, theme_engine, module, profile).
1009
 * @param $name
1010
 *   The name of the item for which the filename is requested.
1011
 *
1012
 * @return
1013
 *   The filename of the requested item or FALSE if the item is not found.
1014
 *
1015
 * @see drupal_get_filename()
1016
 * @see _drupal_get_filename_fallback()
1017
 */
1018
function _drupal_get_filename_perform_file_scan($type, $name) {
1019
  // The location of files will not change during the request, so do not use
1020
  // drupal_static().
1021
  static $dirs = array(), $files = array();
1022

  
1023
  // We have a consistent directory naming: modules, themes...
1024
  $dir = $type . 's';
1025
  if ($type == 'theme_engine') {
1026
    $dir = 'themes/engines';
1027
    $extension = 'engine';
1028
  }
1029
  elseif ($type == 'theme') {
1030
    $extension = 'info';
1031
  }
1032
  else {
1033
    $extension = $type;
1034
  }
1035

  
1036
  // Check if we had already scanned this directory/extension combination.
1037
  if (!isset($dirs[$dir][$extension])) {
1038
    // Log that we have now scanned this directory/extension combination
1039
    // into a static variable so as to prevent unnecessary file scans.
1040
    $dirs[$dir][$extension] = TRUE;
1041
    if (!function_exists('drupal_system_listing')) {
1042
      require_once DRUPAL_ROOT . '/includes/common.inc';
1043
    }
1044
    // Scan the appropriate directories for all files with the requested
1045
    // extension, not just the file we are currently looking for. This
1046
    // prevents unnecessary scans from being repeated when this function is
1047
    // called more than once in the same page request.
1048
    $matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0);
1049
    foreach ($matches as $matched_name => $file) {
1050
      // Log the locations found in the file scan into a static variable.
1051
      $files[$type][$matched_name] = $file->uri;
1052
    }
1053
  }
1054

  
1055
  // Return the results of the file system scan, or FALSE to indicate the file
1056
  // was not found.
1057
  return isset($files[$type][$name]) ? $files[$type][$name] : FALSE;
1058
}
1059

  
1060
/**
1061
 * Triggers a user-level warning for missing or unexpectedly moved files.
1062
 *
1063
 * @param $type
1064
 *   The type of the item (theme, theme_engine, module, profile).
1065
 * @param $name
1066
 *   The name of the item for which the filename is requested.
1067
 * @param $error_type
1068
 *   The type of the error ('missing' or 'moved').
1069
 *
1070
 * @see drupal_get_filename()
1071
 * @see _drupal_get_filename_fallback()
1072
 */
1073
function _drupal_get_filename_fallback_trigger_error($type, $name, $error_type) {
1074
  // Hide messages due to known bugs that will appear on a lot of sites.
1075
  // @todo Remove this in https://www.drupal.org/node/2383823
1076
  if (empty($name)) {
1077
    return;
1078
  }
1079

  
1080
  // Make sure we only show any missing or moved file errors only once per
1081
  // request.
1082
  static $errors_triggered = array();
1083
  if (empty($errors_triggered[$type][$name][$error_type])) {
1084
    // Use _drupal_trigger_error_with_delayed_logging() here since these are
1085
    // triggered during low-level operations that cannot necessarily be
1086
    // interrupted by a watchdog() call.
1087
    if ($error_type == 'missing') {
1088
      _drupal_trigger_error_with_delayed_logging(format_string('The following @type is missing from the file system: %name. For information about how to fix this, see <a href="@documentation">the documentation page</a>.', array('@type' => $type, '%name' => $name, '@documentation' => 'https://www.drupal.org/node/2487215')), E_USER_WARNING);
1089
    }
1090
    elseif ($error_type == 'moved') {
1091
      _drupal_trigger_error_with_delayed_logging(format_string('The following @type has moved within the file system: %name. In order to fix this, clear caches or put the @type back in its original location. For more information, see <a href="@documentation">the documentation page</a>.', array('@type' => $type, '%name' => $name, '@documentation' => 'https://www.drupal.org/node/2487215')), E_USER_WARNING);
1092
    }
1093
    $errors_triggered[$type][$name][$error_type] = TRUE;
1094
  }
1095
}
1096

  
1097
/**
1098
 * Invokes trigger_error() with logging delayed until the end of the request.
1099
 *
1100
 * This is an alternative to PHP's trigger_error() function which can be used
1101
 * during low-level Drupal core operations that need to avoid being interrupted
1102
 * by a watchdog() call.
1103
 *
1104
 * Normally, Drupal's error handler calls watchdog() in response to a
1105
 * trigger_error() call. However, this invokes hook_watchdog() which can run
1106
 * arbitrary code. If the trigger_error() happens in the middle of an
1107
 * operation such as a rebuild operation which should not be interrupted by
1108
 * arbitrary code, that could potentially break or trigger the rebuild again.
1109
 * This function protects against that by delaying the watchdog() call until
1110
 * the end of the current page request.
1111
 *
1112
 * This is an internal function which should only be called by low-level Drupal
1113
 * core functions. It may be removed in a future Drupal 7 release.
1114
 *
1115
 * @param string $error_msg
1116
 *   The error message to trigger. As with trigger_error() itself, this is
1117
 *   limited to 1024 bytes; additional characters beyond that will be removed.
1118
 * @param int $error_type
1119
 *   (optional) The type of error. This should be one of the E_USER family of
1120
 *   constants. As with trigger_error() itself, this defaults to E_USER_NOTICE
1121
 *   if not provided.
1122
 *
1123
 * @see _drupal_log_error()
1124
 */
1125
function _drupal_trigger_error_with_delayed_logging($error_msg, $error_type = E_USER_NOTICE) {
1126
  $delay_logging = &drupal_static(__FUNCTION__, FALSE);
1127
  $delay_logging = TRUE;
1128
  trigger_error($error_msg, $error_type);
1129
  $delay_logging = FALSE;
1130
}
1131

  
1132
/**
1133
 * Writes the file scan cache to the persistent cache.
1134
 *
1135
 * This cache stores all files marked as missing or moved after a file scan
1136
 * to prevent unnecessary file scans in subsequent requests. This cache is
1137
 * cleared in system_list_reset() (i.e. after a module/theme rebuild).
1138
 */
1139
function drupal_file_scan_write_cache() {
1140
  // Only write to the persistent cache if requested, and if we know that any
1141
  // data previously in the cache was successfully loaded and merged in by
1142
  // _drupal_file_scan_cache().
1143
  $file_scans = &_drupal_file_scan_cache();
1144
  if (isset($file_scans['#write_cache']) && isset($file_scans['#cache_merge_done'])) {
1145
    unset($file_scans['#write_cache']);
1146
    cache_set('_drupal_file_scan_cache', $file_scans, 'cache_bootstrap');
908 1147
  }
909 1148
}
910 1149

  
......
1261 1500

  
1262 1501
  $default_headers = array(
1263 1502
    'Expires' => 'Sun, 19 Nov 1978 05:00:00 GMT',
1264
    'Cache-Control' => 'no-cache, must-revalidate, post-check=0, pre-check=0',
1503
    'Cache-Control' => 'no-cache, must-revalidate',
1265 1504
    // Prevent browsers from sniffing a response and picking a MIME type
1266 1505
    // different from the declared content-type, since that can lead to
1267 1506
    // XSS and other vulnerabilities.
......
1439 1678
 * available to code that needs localization. See st() and get_t() for
1440 1679
 * alternatives.
1441 1680
 *
1681
 * @section sec_context String context
1682
 * Matching source strings are normally only translated once, and the same
1683
 * translation is used everywhere that has a matching string. However, in some
1684
 * cases, a certain English source string needs to have multiple translations.
1685
 * One example of this is the string "May", which could be used as either a
1686
 * full month name or a 3-letter abbreviated month. In other languages where
1687
 * the month name for May has more than 3 letters, you would need to provide
1688
 * two different translations (one for the full name and one abbreviated), and
1689
 * the correct form would need to be chosen, depending on how "May" is being
1690
 * used. To facilitate this, the "May" string should be provided with two
1691
 * different contexts in the $options parameter when calling t(). For example:
1692
 * @code
1693
 * t('May', array(), array('context' => 'Long month name')
1694
 * t('May', array(), array('context' => 'Abbreviated month name')
1695
 * @endcode
1696
 * See https://localize.drupal.org/node/2109 for more information.
1697
 *
1442 1698
 * @param $string
1443 1699
 *   A string containing the English string to translate.
1444 1700
 * @param $args
......
1449 1705
 *   An associative array of additional options, with the following elements:
1450 1706
 *   - 'langcode' (defaults to the current language): The language code to
1451 1707
 *     translate to a language other than what is used to display the page.
1452
 *   - 'context' (defaults to the empty context): The context the source string
1453
 *     belongs to.
1708
 *   - 'context' (defaults to the empty context): A string giving the context
1709
 *     that the source string belongs to. See @ref sec_context above for more
1710
 *     information.
1454 1711
 *
1455 1712
 * @return
1456 1713
 *   The translated string.
......
2945 3202
        // Eliminate all trusted IPs.
2946 3203
        $untrusted = array_diff($forwarded, $reverse_proxy_addresses);
2947 3204

  
2948
        // The right-most IP is the most specific we can trust.
2949
        $ip_address = array_pop($untrusted);
3205
        if (!empty($untrusted)) {
3206
          // The right-most IP is the most specific we can trust.
3207
          $ip_address = array_pop($untrusted);
3208
        }
3209
        else {
3210
          // All IP addresses in the forwarded array are configured proxy IPs
3211
          // (and thus trusted). We take the leftmost IP.
3212
          $ip_address = array_shift($forwarded);
3213
        }
2950 3214
      }
2951 3215
    }
2952 3216
  }
......
3187 3451
  $cache_key = $type[0] . $name;
3188 3452
  if (isset($lookup_cache[$cache_key])) {
3189 3453
    if ($lookup_cache[$cache_key]) {
3190
      require_once DRUPAL_ROOT . '/' . $lookup_cache[$cache_key];
3454
      include_once DRUPAL_ROOT . '/' . $lookup_cache[$cache_key];
3191 3455
    }
3192 3456
    return (bool) $lookup_cache[$cache_key];
3193 3457
  }
......
3212 3476
  $lookup_cache[$cache_key] = $file;
3213 3477

  
3214 3478
  if ($file) {
3215
    require_once DRUPAL_ROOT . '/' . $file;
3479
    include_once DRUPAL_ROOT . '/' . $file;
3216 3480
    return TRUE;
3217 3481
  }
3218 3482
  else {

Also available in: Unified diff