diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 799b8003..68fc5bae 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,7 +1,62 @@
+Drupal 7.xx, xxxx-xx-xx (development version)
+-----------------------
+
+Drupal 7.66, 2019-04-17
+-----------------------
+- Fixed security issues:
+ - SA-CORE-2019-006
+
+Drupal 7.65, 2019-03-20
+-----------------------
+- Fixed security issues:
+ - SA-CORE-2019-004
+
+Drupal 7.64, 2019-02-06
+-----------------------
+- [regression] Unset the 'host' header in drupal_http_request() during redirect
+- Fixed: 7.x does not have Phar protection and Phar tests are failing on Drupal 7
+- Fixed: Notice: Undefined index: display_field in file_field_widget_value() (line 582 of /module/file/file.field.inc)
+- Performance improvement: Registry rebuild should not parse the same file twice in the same request
+- Fixed _registry_update() to clear caches after transaction is committed
+
+Drupal 7.63, 2019-01-16
+-----------------------
+- Fixed a fatal error for some Drush users introduced by SA-CORE-2019-002.
+
+Drupal 7.62, 2019-01-15
+-----------------------
+- Fixed security issues:
+ - SA-CORE-2019-001
+ - SA-CORE-2019-002
+
+Drupal 7.61, 2018-11-07
+-----------------------
+- File upload validation functions and hook_file_validate() implementations are
+ now always passed the correct file URI.
+- The default form cache expiration of 6 hours is now configurable (API
+ addition: https://www.drupal.org/node/2857751).
+- Allowed callers of drupal_http_request() to optionally specify an explicit
+ Host header.
+- Allowed the + character to appear in usernames.
+- PHP 7.2: Fixed Archive_Tar incompatibility.
+- PHP 7.2: Removed deprecated function each().
+- PHP 7.2: Avoid count() calls on uncountable variables.
+- PHP 7.2: Removed deprecated create_function() call.
+- PHP 7.2: Make sure variables are arrays in theme_links().
+- Fixed theme-settings.php not being loaded on cached forms
+- Fixed problem with IE11 & Chrome(PointerEvents enabled) & some Firefox scroll to the top of the page after dragging the bottom item with jquery 1.5 <-> 1.11
+
+Drupal 7.60, 2018-10-18
+------------------------
+- Fixed security issues. See SA-CORE-2018-006.
+
+Drupal 7.59, 2018-04-25
+-----------------------
+- Fixed security issues (remote code execution). See SA-CORE-2018-004.
Drupal 7.58, 2018-03-28
-----------------------
-- Fixed security issues (multiple vulnerabilities). See SA-CORE-2018-002.
+- Fixed security issues (remote code execution). See SA-CORE-2018-002.
Drupal 7.57, 2018-02-21
-----------------------
diff --git a/MAINTAINERS.txt b/MAINTAINERS.txt
index 5603a432..460658c1 100644
--- a/MAINTAINERS.txt
+++ b/MAINTAINERS.txt
@@ -15,6 +15,7 @@ The branch maintainers for Drupal 7 are:
- Fabian Franz 'Fabianx' https://www.drupal.org/u/fabianx
- David Rothstein 'David_Rothstein' https://www.drupal.org/u/david_rothstein
- Stefan Ruijsenaars 'stefan.r' https://www.drupal.org/u/stefanr-0
+- (provisional) Pol Dellaiera 'Pol' https://www.drupal.org/u/pol
Component maintainers
@@ -44,10 +45,9 @@ Cron system
- Derek Wright 'dww' https://www.drupal.org/u/dww
Database system
-- Larry Garfield 'Crell' https://www.drupal.org/u/crell
+- ?
- MySQL driver
- - Larry Garfield 'Crell' https://www.drupal.org/u/crell
- David Strauss 'David Strauss' https://www.drupal.org/u/david-strauss
- PostgreSQL driver
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index 06acf935..98c31ad3 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -8,7 +8,7 @@
/**
* The current system version.
*/
-define('VERSION', '7.58');
+define('VERSION', '7.66');
/**
* Core API compatibility.
@@ -704,6 +704,19 @@ function drupal_environment_initialize() {
// Set sane locale settings, to ensure consistent string, dates, times and
// numbers handling.
setlocale(LC_ALL, 'C');
+
+ // PHP's built-in phar:// stream wrapper is not sufficiently secure. Override
+ // it with a more secure one, which requires PHP 5.3.3. For lower versions,
+ // unregister the built-in one without replacing it. Sites needing phar
+ // support for lower PHP versions must implement hook_stream_wrappers() to
+ // register their desired implementation.
+ if (in_array('phar', stream_get_wrappers(), TRUE)) {
+ stream_wrapper_unregister('phar');
+ if (version_compare(PHP_VERSION, '5.3.3', '>=')) {
+ include_once DRUPAL_ROOT . '/includes/file.phar.inc';
+ file_register_phar_wrapper();
+ }
+ }
}
/**
@@ -2778,6 +2791,11 @@ function _drupal_bootstrap_variables() {
unset($_GET['destination']);
unset($_REQUEST['destination']);
}
+ // Use the DrupalRequestSanitizer to ensure that the destination's query
+ // parameters are not dangerous.
+ if (isset($_GET['destination'])) {
+ DrupalRequestSanitizer::cleanDestination();
+ }
// If there's still something in $_REQUEST['destination'] that didn't come
// from $_GET, check it too.
if (isset($_REQUEST['destination']) && (!isset($_GET['destination']) || $_REQUEST['destination'] != $_GET['destination']) && url_is_external($_REQUEST['destination'])) {
@@ -3780,8 +3798,12 @@ function _drupal_shutdown_function() {
chdir(DRUPAL_ROOT);
try {
- while (list($key, $callback) = each($callbacks)) {
+ // Manually iterate over the array instead of using a foreach loop.
+ // A foreach operates on a copy of the array, so any shutdown functions that
+ // were added from other shutdown functions would never be called.
+ while ($callback = current($callbacks)) {
call_user_func_array($callback['callback'], $callback['arguments']);
+ next($callbacks);
}
}
catch (Exception $exception) {
diff --git a/includes/common.inc b/includes/common.inc
index d7dc47f2..44ff4607 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -611,8 +611,9 @@ function drupal_parse_url($url) {
}
// The 'q' parameter contains the path of the current page if clean URLs are
// disabled. It overrides the 'path' of the URL when present, even if clean
- // URLs are enabled, due to how Apache rewriting rules work.
- if (isset($options['query']['q'])) {
+ // URLs are enabled, due to how Apache rewriting rules work. The path
+ // parameter must be a string.
+ if (isset($options['query']['q']) && is_string($options['query']['q'])) {
$options['path'] = $options['query']['q'];
unset($options['query']['q']);
}
@@ -866,8 +867,10 @@ function drupal_http_request($url, array $options = array()) {
// Make the socket connection to a proxy server.
$socket = 'tcp://' . $proxy_server . ':' . variable_get('proxy_port', 8080);
// The Host header still needs to match the real request.
- $options['headers']['Host'] = $uri['host'];
- $options['headers']['Host'] .= isset($uri['port']) && $uri['port'] != 80 ? ':' . $uri['port'] : '';
+ if (!isset($options['headers']['Host'])) {
+ $options['headers']['Host'] = $uri['host'];
+ $options['headers']['Host'] .= isset($uri['port']) && $uri['port'] != 80 ? ':' . $uri['port'] : '';
+ }
break;
case 'http':
@@ -877,14 +880,18 @@ function drupal_http_request($url, array $options = array()) {
// RFC 2616: "non-standard ports MUST, default ports MAY be included".
// We don't add the standard port to prevent from breaking rewrite rules
// checking the host that do not take into account the port number.
- $options['headers']['Host'] = $uri['host'] . ($port != 80 ? ':' . $port : '');
+ if (!isset($options['headers']['Host'])) {
+ $options['headers']['Host'] = $uri['host'] . ($port != 80 ? ':' . $port : '');
+ }
break;
case 'https':
// Note: Only works when PHP is compiled with OpenSSL support.
$port = isset($uri['port']) ? $uri['port'] : 443;
$socket = 'ssl://' . $uri['host'] . ':' . $port;
- $options['headers']['Host'] = $uri['host'] . ($port != 443 ? ':' . $port : '');
+ if (!isset($options['headers']['Host'])) {
+ $options['headers']['Host'] = $uri['host'] . ($port != 443 ? ':' . $port : '');
+ }
break;
default:
@@ -1087,6 +1094,11 @@ function drupal_http_request($url, array $options = array()) {
elseif ($options['max_redirects']) {
// Redirect to the new location.
$options['max_redirects']--;
+
+ // We need to unset the 'Host' header
+ // as we are redirecting to a new location.
+ unset($options['headers']['Host']);
+
$result = drupal_http_request($location, $options);
$result->redirect_code = $code;
}
@@ -2310,7 +2322,10 @@ function url($path = NULL, array $options = array()) {
$language = isset($options['language']) && isset($options['language']->language) ? $options['language']->language : '';
$alias = drupal_get_path_alias($original_path, $language);
if ($alias != $original_path) {
- $path = $alias;
+ // Strip leading slashes from internal path aliases to prevent them
+ // becoming external URLs without protocol. /example.com should not be
+ // turned into //example.com.
+ $path = ltrim($alias, '/');
}
}
diff --git a/includes/file.inc b/includes/file.inc
index fa7f5eb5..95bb6584 100644
--- a/includes/file.inc
+++ b/includes/file.inc
@@ -993,8 +993,15 @@ function file_build_uri($path) {
* @return
* The destination filepath, or FALSE if the file already exists
* and FILE_EXISTS_ERROR is specified.
+ *
+ * @throws RuntimeException
+ * Thrown if the filename contains invalid UTF-8.
*/
function file_destination($destination, $replace) {
+ $basename = drupal_basename($destination);
+ if (!drupal_validate_utf8($basename)) {
+ throw new RuntimeException(sprintf("Invalid filename '%s'", $basename));
+ }
if (file_exists($destination)) {
switch ($replace) {
case FILE_EXISTS_REPLACE:
@@ -1002,7 +1009,6 @@ function file_destination($destination, $replace) {
break;
case FILE_EXISTS_RENAME:
- $basename = drupal_basename($destination);
$directory = drupal_dirname($destination);
$destination = file_create_filename($basename, $directory);
break;
@@ -1218,11 +1224,20 @@ function file_unmunge_filename($filename) {
* @return
* File path consisting of $directory and a unique filename based off
* of $basename.
+ *
+ * @throws RuntimeException
+ * Thrown if the $basename is not valid UTF-8 or another error occurs
+ * stripping control characters.
*/
function file_create_filename($basename, $directory) {
+ $original = $basename;
// Strip control characters (ASCII value < 32). Though these are allowed in
// some filesystems, not many applications handle them well.
$basename = preg_replace('/[\x00-\x1F]/u', '_', $basename);
+ if (preg_last_error() !== PREG_NO_ERROR) {
+ throw new RuntimeException(sprintf("Invalid filename '%s'", $original));
+ }
+
if (substr(PHP_OS, 0, 3) == 'WIN') {
// These characters are not allowed in Windows filenames
$basename = str_replace(array(':', '*', '?', '"', '<', '>', '|'), '_', $basename);
@@ -1534,9 +1549,9 @@ function file_save_upload($form_field_name, $validators = array(), $destination
// rename filename.php.foo and filename.php to filename.php.foo.txt and
// filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads'
// evaluates to TRUE.
- if (!variable_get('allow_insecure_uploads', 0) && preg_match('/\.(php|pl|py|cgi|asp|js)(\.|$)/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
+ if (!variable_get('allow_insecure_uploads', 0) && preg_match('/\.(php|phar|pl|py|cgi|asp|js)(\.|$)/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
$file->filemime = 'text/plain';
- $file->uri .= '.txt';
+ // The destination filename will also later be used to create the URI.
$file->filename .= '.txt';
// The .txt extension may not be in the allowed list of extensions. We have
// to add it here or else the file upload will fail.
@@ -1563,7 +1578,13 @@ function file_save_upload($form_field_name, $validators = array(), $destination
if (substr($destination, -1) != '/') {
$destination .= '/';
}
- $file->destination = file_destination($destination . $file->filename, $replace);
+ try {
+ $file->destination = file_destination($destination . $file->filename, $replace);
+ }
+ catch (RuntimeException $e) {
+ drupal_set_message(t('The file %source could not be uploaded because the name is invalid.', array('%source' => $form_field_name)), 'error');
+ return FALSE;
+ }
// If file_destination() returns FALSE then $replace == FILE_EXISTS_ERROR and
// there's an existing file so we need to bail.
if ($file->destination === FALSE) {
@@ -2130,9 +2151,33 @@ function file_download_access($uri) {
* 'filename', and 'name' members corresponding to the matching files.
*/
function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
+ // Default nomask option.
+ $nomask = '/(\.\.?|CVS)$/';
+
+ // Overrides the $nomask variable accordingly if $options['nomask'] is set.
+ //
+ // Allow directories specified in settings.php to be ignored. You can use this
+ // to not check for files in common special-purpose directories. For example,
+ // node_modules and bower_components. Ignoring irrelevant directories is a
+ // performance boost.
+ if (!isset($options['nomask'])) {
+ $ignore_directories = variable_get(
+ 'file_scan_ignore_directories',
+ array()
+ );
+
+ foreach ($ignore_directories as $index => $ignore_directory) {
+ $ignore_directories[$index] = preg_quote($ignore_directory, '/');
+ }
+
+ if (!empty($ignore_directories)) {
+ $nomask = '/^(\.\.?)|CVS|' . implode('|', $ignore_directories) . '$/';
+ }
+ }
+
// Merge in defaults.
$options += array(
- 'nomask' => '/(\.\.?|CVS)$/',
+ 'nomask' => $nomask,
'callback' => 0,
'recurse' => TRUE,
'key' => 'uri',
diff --git a/includes/file.phar.inc b/includes/file.phar.inc
new file mode 100644
index 00000000..3d7ba01d
--- /dev/null
+++ b/includes/file.phar.inc
@@ -0,0 +1,41 @@
+withAssertion(new PharExtensionInterceptor())
+ );
+ }
+ catch (\LogicException $e) {
+ // Continue if the PharStreamWrapperManager is already initialized.
+ // For example, this occurs following a drupal_static_reset(), such
+ // as during tests.
+ };
+
+ // To prevent file_stream_wrapper_valid_scheme() treating "phar" as a valid
+ // scheme, this is registered with PHP only, not with hook_stream_wrappers()
+ // or the internal storage of file_get_stream_wrappers().
+ stream_wrapper_register('phar', '\\TYPO3\\PharStreamWrapper\\PharStreamWrapper');
+}
diff --git a/includes/form.inc b/includes/form.inc
index e749239e..6c33de7f 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -555,8 +555,10 @@ function form_get_cache($form_build_id, &$form_state) {
* Stores a form in the cache.
*/
function form_set_cache($form_build_id, $form, $form_state) {
- // 6 hours cache life time for forms should be plenty.
- $expire = 21600;
+ // The default cache_form expiration is 6 hours. On busy sites, the cache_form
+ // table can become very large. A shorter cache lifetime can help to keep the
+ // table's size under control.
+ $expire = variable_get('form_cache_expiration', 21600);
// Ensure that the form build_id embedded in the form structure is the same as
// the one passed in as a parameter. This is an additional safety measure to
@@ -1438,10 +1440,12 @@ function _form_validate(&$elements, &$form_state, $form_id = NULL) {
// length if it's a string, and the item count if it's an array.
// An unchecked checkbox has a #value of integer 0, different than string
// '0', which could be a valid value.
- $is_empty_multiple = (!count($elements['#value']));
+ $is_countable = is_array($elements['#value']) || $elements['#value'] instanceof Countable;
+ $is_empty_multiple = $is_countable && count($elements['#value']) == 0;
$is_empty_string = (is_string($elements['#value']) && drupal_strlen(trim($elements['#value'])) == 0);
$is_empty_value = ($elements['#value'] === 0);
- if ($is_empty_multiple || $is_empty_string || $is_empty_value) {
+ $is_empty_null = is_null($elements['#value']);
+ if ($is_empty_multiple || $is_empty_string || $is_empty_value || $is_empty_null) {
// Although discouraged, a #title is not mandatory for form elements. In
// case there is no #title, we cannot set a form error message.
// Instead of setting no #title, form constructors are encouraged to set
diff --git a/includes/install.inc b/includes/install.inc
index 5e1d3c63..b7db7835 100644
--- a/includes/install.inc
+++ b/includes/install.inc
@@ -779,7 +779,7 @@ function drupal_uninstall_modules($module_list = array(), $uninstall_dependents
$module_list = array_flip(array_values($module_list));
$profile = drupal_get_profile();
- while (list($module) = each($module_list)) {
+ foreach (array_keys($module_list) as $module) {
if (!isset($module_data[$module]) || drupal_get_installed_schema_version($module) == SCHEMA_UNINSTALLED) {
// This module doesn't exist or is already uninstalled. Skip it.
unset($module_list[$module]);
diff --git a/includes/menu.inc b/includes/menu.inc
index 4664d27e..ca37ba50 100644
--- a/includes/menu.inc
+++ b/includes/menu.inc
@@ -576,7 +576,8 @@ function _menu_load_objects(&$item, &$map) {
// 'load arguments' in the hook_menu() entry, but they need
// some processing. In this case the $function is the key to the
// load_function array, and the value is the list of arguments.
- list($function, $args) = each($function);
+ $args = current($function);
+ $function = key($function);
$load_functions[$index] = $function;
// Some arguments are placeholders for dynamic items to process.
@@ -2402,7 +2403,8 @@ function menu_set_active_trail($new_trail = NULL) {
// a stripped down menu tree containing the active trail only, in case
// the given menu has not been built in this request yet.
$tree = menu_tree_page_data($preferred_link['menu_name'], NULL, TRUE);
- list($key, $curr) = each($tree);
+ $curr = current($tree);
+ next($tree);
}
// There is no link for the current path.
else {
@@ -2432,7 +2434,8 @@ function menu_set_active_trail($new_trail = NULL) {
}
$tree = $curr['below'] ? $curr['below'] : array();
}
- list($key, $curr) = each($tree);
+ $curr = current($tree);
+ next($tree);
}
// Make sure the current page is in the trail to build the page title, by
// appending either the preferred link or the menu router item for the
diff --git a/includes/module.inc b/includes/module.inc
index 2e251080..4c2b3fbe 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -404,7 +404,11 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
// Create an associative array with weights as values.
$module_list = array_flip(array_values($module_list));
- while (list($module) = each($module_list)) {
+ // The array is iterated over manually (instead of using a foreach) because
+ // modules may be added to the list within the loop and we need to process
+ // them.
+ while ($module = key($module_list)) {
+ next($module_list);
if (!isset($module_data[$module])) {
// This module is not found in the filesystem, abort.
return FALSE;
@@ -540,7 +544,11 @@ function module_disable($module_list, $disable_dependents = TRUE) {
$module_list = array_flip(array_values($module_list));
$profile = drupal_get_profile();
- while (list($module) = each($module_list)) {
+ // The array is iterated over manually (instead of using a foreach) because
+ // modules may be added to the list within the loop and we need to process
+ // them.
+ while ($module = key($module_list)) {
+ next($module_list);
if (!isset($module_data[$module]) || !$module_data[$module]->status) {
// This module doesn't exist or is already disabled, skip it.
unset($module_list[$module]);
diff --git a/includes/registry.inc b/includes/registry.inc
index 29a1fca8..ee678e89 100644
--- a/includes/registry.inc
+++ b/includes/registry.inc
@@ -19,7 +19,6 @@
* Does the work for registry_update().
*/
function _registry_update() {
-
// The registry serves as a central autoloader for all classes, including
// the database query builders. However, the registry rebuild process
// requires write ability to the database, which means having access to the
@@ -33,6 +32,11 @@ function _registry_update() {
require_once DRUPAL_ROOT . '/includes/database/select.inc';
require_once DRUPAL_ROOT . '/includes/database/' . $driver . '/query.inc';
+ // During the first registry rebuild in a request, we check all the files.
+ // During subsequent rebuilds, we only add new files. It makes the rebuilding
+ // process faster during installation of modules.
+ static $check_existing_files = TRUE;
+
// Get current list of modules and their files.
$modules = db_query("SELECT * FROM {system} WHERE type = 'module'")->fetchAll();
// Get the list of files we are going to parse.
@@ -55,6 +59,9 @@ function _registry_update() {
$files["$filename"] = array('module' => '', 'weight' => 0);
}
+ // Initialize an empty array for the unchanged files.
+ $unchanged_files = array();
+
$transaction = db_transaction();
try {
// Allow modules to manually modify the list of files before the registry
@@ -63,10 +70,19 @@ function _registry_update() {
// list can then be added to the list of files that the registry will parse,
// or modify attributes of a file.
drupal_alter('registry_files', $files, $modules);
+
foreach (registry_get_parsed_files() as $filename => $file) {
// Add the hash for those files we have already parsed.
if (isset($files[$filename])) {
- $files[$filename]['hash'] = $file['hash'];
+ if ($check_existing_files === TRUE) {
+ $files[$filename]['hash'] = $file['hash'];
+ }
+ else {
+ // Ignore that file for this request, it has been parsed previously
+ // and it is unlikely it has changed.
+ unset($files[$filename]);
+ $unchanged_files[$filename] = $file;
+ }
}
else {
// Flush the registry of resources in files that are no longer on disc
@@ -79,8 +95,12 @@ function _registry_update() {
->execute();
}
}
+
$parsed_files = _registry_parse_files($files);
+ // Add unchanged files to the files.
+ $files += $unchanged_files;
+
$unchanged_resources = array();
$lookup_cache = array();
if ($cache = cache_get('lookup_cache', 'cache_bootstrap')) {
@@ -89,12 +109,10 @@ function _registry_update() {
foreach ($lookup_cache as $key => $file) {
// If the file for this cached resource is carried over unchanged from
// the last registry build, then we can safely re-cache it.
- if ($file && in_array($file, array_keys($files)) && !in_array($file, $parsed_files)) {
+ if ($file && isset($files[$file]) && !in_array($file, $parsed_files, TRUE)) {
$unchanged_resources[$key] = $file;
}
}
- module_implements('', FALSE, TRUE);
- _registry_check_code(REGISTRY_RESET_LOOKUP_CACHE);
}
catch (Exception $e) {
$transaction->rollback();
@@ -102,6 +120,13 @@ function _registry_update() {
throw $e;
}
+ module_implements('', FALSE, TRUE);
+ _registry_check_code(REGISTRY_RESET_LOOKUP_CACHE);
+
+ // During the next run in this request, don't bother re-checking existing
+ // files.
+ $check_existing_files = FALSE;
+
// We have some unchanged resources, warm up the cache - no need to pay
// for looking them up again.
if (count($unchanged_resources) > 0) {
diff --git a/includes/request-sanitizer.inc b/includes/request-sanitizer.inc
index 1daa6b53..7214436b 100644
--- a/includes/request-sanitizer.inc
+++ b/includes/request-sanitizer.inc
@@ -51,6 +51,38 @@ class DrupalRequestSanitizer {
}
}
+ /**
+ * Removes the destination if it is dangerous.
+ *
+ * Note this can only be called after common.inc has been included.
+ *
+ * @return bool
+ * TRUE if the destination has been removed from $_GET, FALSE if not.
+ */
+ public static function cleanDestination() {
+ $dangerous_keys = array();
+ $log_sanitized_keys = variable_get('sanitize_input_logging', FALSE);
+
+ $parts = drupal_parse_url($_GET['destination']);
+ // If there is a query string, check its query parameters.
+ if (!empty($parts['query'])) {
+ $whitelist = variable_get('sanitize_input_whitelist', array());
+
+ self::stripDangerousValues($parts['query'], $whitelist, $dangerous_keys);
+ if (!empty($dangerous_keys)) {
+ // The destination is removed rather than sanitized to mirror the
+ // handling of external destinations.
+ unset($_GET['destination']);
+ unset($_REQUEST['destination']);
+ if ($log_sanitized_keys) {
+ trigger_error(format_string('Potentially unsafe destination removed from query string parameters (GET) because it contained the following keys: @keys', array('@keys' => implode(', ', $dangerous_keys))));
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+
/**
* Strips dangerous keys from the provided input.
*
diff --git a/includes/theme.inc b/includes/theme.inc
index 9b606e9f..a926b764 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -1776,13 +1776,13 @@ function theme_link($variables) {
* http://www.w3.org/TR/WCAG-TECHS/H42.html for more information.
*/
function theme_links($variables) {
- $links = $variables['links'];
- $attributes = $variables['attributes'];
+ $links = (array) $variables['links'];
+ $attributes = (array) $variables['attributes'];
$heading = $variables['heading'];
global $language_url;
$output = '';
- if (count($links) > 0) {
+ if (!empty($links)) {
// Treat the heading first if it is present to prepend it to the
// list of links.
if (!empty($heading)) {
@@ -1995,7 +1995,7 @@ function theme_table($variables) {
$empty = $variables['empty'];
// Add sticky headers, if applicable.
- if (count($header) && $sticky) {
+ if (!empty($header) && $sticky) {
drupal_add_js('misc/tableheader.js');
// Add 'sticky-enabled' class to the table to identify it for JS.
// This is needed to target tables constructed by this function.
@@ -2009,7 +2009,7 @@ function theme_table($variables) {
}
// Format the table columns:
- if (count($colgroups)) {
+ if (!empty($colgroups)) {
foreach ($colgroups as $number => $colgroup) {
$attributes = array();
@@ -2044,38 +2044,40 @@ function theme_table($variables) {
}
// Add the 'empty' row message if available.
- if (!count($rows) && $empty) {
+ if (empty($rows) && $empty) {
$header_count = 0;
- foreach ($header as $header_cell) {
- if (is_array($header_cell)) {
- $header_count += isset($header_cell['colspan']) ? $header_cell['colspan'] : 1;
- }
- else {
- $header_count++;
+ if (!empty($header)) {
+ foreach ($header as $header_cell) {
+ if (is_array($header_cell)) {
+ $header_count += isset($header_cell['colspan']) ? $header_cell['colspan'] : 1;
+ }
+ else {
+ $header_count++;
+ }
}
}
$rows[] = array(array('data' => $empty, 'colspan' => $header_count, 'class' => array('empty', 'message')));
}
// Format the table header:
- if (count($header)) {
+ if (!empty($header)) {
$ts = tablesort_init($header);
// HTML requires that the thead tag has tr tags in it followed by tbody
// tags. Using ternary operator to check and see if we have any rows.
- $output .= (count($rows) ? ' ' : '
');
+ $output .= (!empty($rows) ? ' ' : '
');
foreach ($header as $cell) {
$cell = tablesort_header($cell, $header, $ts);
$output .= _theme_table_cell($cell, TRUE);
}
// Using ternary operator to close the tags based on whether or not there are rows
- $output .= (count($rows) ? "
\n" : "
\n");
+ $output .= (!empty($rows) ? " \n" : "\n");
}
else {
$ts = array();
}
// Format the table rows:
- if (count($rows)) {
+ if (!empty($rows)) {
$output .= "
\n";
$flip = array('even' => 'odd', 'odd' => 'even');
$class = 'even';
@@ -2095,7 +2097,7 @@ function theme_table($variables) {
$attributes = array();
$no_striping = FALSE;
}
- if (count($cells)) {
+ if (!empty($cells)) {
// Add odd/even class
if (!$no_striping) {
$class = $flip[$class];
diff --git a/misc/jquery-extend-3.4.0.js b/misc/jquery-extend-3.4.0.js
new file mode 100644
index 00000000..97591094
--- /dev/null
+++ b/misc/jquery-extend-3.4.0.js
@@ -0,0 +1,112 @@
+/**
+ * For jQuery versions less than 3.4.0, this replaces the jQuery.extend
+ * function with the one from jQuery 3.4.0, slightly modified (documented
+ * below) to be compatible with older jQuery versions and browsers.
+ *
+ * This provides the Object.prototype pollution vulnerability fix to Drupal
+ * installations running older jQuery versions, including the versions shipped
+ * with Drupal core and https://www.drupal.org/project/jquery_update.
+ *
+ * @see https://github.com/jquery/jquery/pull/4333
+ */
+
+(function (jQuery) {
+
+// Do not override jQuery.extend() if the jQuery version is already >=3.4.0.
+var versionParts = jQuery.fn.jquery.split('.');
+var majorVersion = parseInt(versionParts[0]);
+var minorVersion = parseInt(versionParts[1]);
+var patchVersion = parseInt(versionParts[2]);
+var isPreReleaseVersion = (patchVersion.toString() !== versionParts[2]);
+if (
+ (majorVersion > 3) ||
+ (majorVersion === 3 && minorVersion > 4) ||
+ (majorVersion === 3 && minorVersion === 4 && patchVersion > 0) ||
+ (majorVersion === 3 && minorVersion === 4 && patchVersion === 0 && !isPreReleaseVersion)
+) {
+ return;
+}
+
+/**
+ * This is almost verbatim copied from jQuery 3.4.0.
+ *
+ * Only two minor changes have been made:
+ * - The call to isFunction() is changed to jQuery.isFunction().
+ * - The two calls to Array.isArray() is changed to jQuery.isArray().
+ *
+ * The above two changes ensure compatibility with all older jQuery versions
+ * (1.4.4 - 3.3.1) and older browser versions (e.g., IE8).
+ */
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[ 0 ] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+
+ // Skip the boolean and the target
+ target = arguments[ i ] || {};
+ i++;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
+ target = {};
+ }
+
+ // Extend jQuery itself if only one argument is passed
+ if ( i === length ) {
+ target = this;
+ i--;
+ }
+
+ for ( ; i < length; i++ ) {
+
+ // Only deal with non-null/undefined values
+ if ( ( options = arguments[ i ] ) != null ) {
+
+ // Extend the base object
+ for ( name in options ) {
+ copy = options[ name ];
+
+ // Prevent Object.prototype pollution
+ // Prevent never-ending loop
+ if ( name === "__proto__" || target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
+ ( copyIsArray = jQuery.isArray( copy ) ) ) ) {
+ src = target[ name ];
+
+ // Ensure proper type for the source value
+ if ( copyIsArray && !jQuery.isArray( src ) ) {
+ clone = [];
+ } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
+ clone = {};
+ } else {
+ clone = src;
+ }
+ copyIsArray = false;
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+})(jQuery);
diff --git a/misc/tabledrag.js b/misc/tabledrag.js
index 7ea88b60..836568f5 100644
--- a/misc/tabledrag.js
+++ b/misc/tabledrag.js
@@ -580,21 +580,43 @@ Drupal.tableDrag.prototype.dropRow = function (event, self) {
* Get the mouse coordinates from the event (allowing for browser differences).
*/
Drupal.tableDrag.prototype.mouseCoords = function (event) {
- // Complete support for pointer events was only introduced to jQuery in
- // version 1.11.1; between versions 1.7 and 1.11.0 pointer events have the
- // clientX and clientY properties undefined. In those cases, the properties
- // must be retrieved from the event.originalEvent object instead.
- var clientX = event.clientX || event.originalEvent.clientX;
- var clientY = event.clientY || event.originalEvent.clientY;
- if (event.pageX || event.pageY) {
- return { x: event.pageX, y: event.pageY };
+ // Match both null and undefined, but not zero, by using != null.
+ // See https://stackoverflow.com/questions/2647867/how-to-determine-if-variable-is-undefined-or-null
+ if (event.pageX != null && event.pageY != null) {
+ return {x: event.pageX, y: event.pageY};
}
- return {
- x: clientX + document.body.scrollLeft - document.body.clientLeft,
- y: clientY + document.body.scrollTop - document.body.clientTop
- };
+ // Complete support for pointer events was only introduced to jQuery in
+ // version 1.11.1; between versions 1.7 and 1.11.0 pointer events have the
+ // pageX and pageY properties undefined. In those cases, the properties must
+ // be retrieved from the event.originalEvent object instead.
+ if (event.originalEvent && event.originalEvent.pageX != null && event.originalEvent.pageY != null) {
+ return {x: event.originalEvent.pageX, y: event.originalEvent.pageY};
+ }
+
+ // Some old browsers do not support MouseEvent.pageX and *.pageY at all.
+ // See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageY
+ // For those, we look at event.clientX and event.clientY instead.
+ if (event.clientX == null || event.clientY == null) {
+ // In some jQuery versions, some events created by jQuery do not have
+ // clientX and clientY. But the original event might have.
+ if (!event.originalEvent) {
+ throw new Error("The event has no coordinates, and no event.originalEvent.");
+ }
+ event = event.originalEvent;
+ if (event.clientX == null || event.clientY == null) {
+ throw new Error("The original event has no coordinates.");
+ }
+ }
+
+ // Copied from jQuery.event.fix() in jQuery 1.4.1.
+ // In newer jQuery versions, this code is in jQuery.event.mouseHooks.filter().
+ var doc = document.documentElement, body = document.body;
+ var pageX = event.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ var pageY = event.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+
+ return {x: pageX, y: pageY};
};
/**
diff --git a/misc/typo3/drupal-security/PharExtensionInterceptor.php b/misc/typo3/drupal-security/PharExtensionInterceptor.php
new file mode 100644
index 00000000..2e1a0cbc
--- /dev/null
+++ b/misc/typo3/drupal-security/PharExtensionInterceptor.php
@@ -0,0 +1,79 @@
+baseFileContainsPharExtension($path)) {
+ return TRUE;
+ }
+ throw new Exception(
+ sprintf(
+ 'Unexpected file extension in "%s"',
+ $path
+ ),
+ 1535198703
+ );
+ }
+
+ /**
+ * Determines if a path has a .phar extension or invoked execution.
+ *
+ * @param string $path
+ * The path of the phar file to check.
+ *
+ * @return bool
+ * TRUE if the file has a .phar extension or if the execution has been
+ * invoked by the phar file.
+ */
+ private function baseFileContainsPharExtension($path) {
+ $baseFile = Helper::determineBaseFile($path);
+ if ($baseFile === NULL) {
+ return FALSE;
+ }
+ // If the stream wrapper is registered by invoking a phar file that does
+ // not not have .phar extension then this should be allowed. For
+ // example, some CLI tools recommend removing the extension.
+ $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+ // Find the last entry in the backtrace containing a 'file' key as
+ // sometimes the last caller is executed outside the scope of a file. For
+ // example, this occurs with shutdown functions.
+ do {
+ $caller = array_pop($backtrace);
+ } while (empty($caller['file']) && !empty($backtrace));
+ if (isset($caller['file']) && $baseFile === Helper::determineBaseFile($caller['file'])) {
+ return TRUE;
+ }
+ $fileExtension = pathinfo($baseFile, PATHINFO_EXTENSION);
+ return strtolower($fileExtension) === 'phar';
+ }
+
+}
diff --git a/misc/typo3/phar-stream-wrapper/LICENSE b/misc/typo3/phar-stream-wrapper/LICENSE
new file mode 100644
index 00000000..d71267a1
--- /dev/null
+++ b/misc/typo3/phar-stream-wrapper/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 TYPO3 project - https://typo3.org/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/misc/typo3/phar-stream-wrapper/README.md b/misc/typo3/phar-stream-wrapper/README.md
new file mode 100644
index 00000000..b632784b
--- /dev/null
+++ b/misc/typo3/phar-stream-wrapper/README.md
@@ -0,0 +1,155 @@
+[](https://scrutinizer-ci.com/g/TYPO3/phar-stream-wrapper/?branch=v2)
+[](https://travis-ci.org/TYPO3/phar-stream-wrapper)
+
+# PHP Phar Stream Wrapper
+
+## Abstract & History
+
+Based on Sam Thomas' findings concerning
+[insecure deserialization in combination with obfuscation strategies](https://blog.secarma.co.uk/labs/near-phar-dangerous-unserialization-wherever-you-are)
+allowing to hide Phar files inside valid image resources, the TYPO3 project
+decided back then to introduce a `PharStreamWrapper` to intercept invocations
+of the `phar://` stream in PHP and only allow usage for defined locations in
+the file system.
+
+Since the TYPO3 mission statement is **inspiring people to share**, we thought
+it would be helpful for others to release our `PharStreamWrapper` as standalone
+package to the PHP community.
+
+The mentioned security issue was reported to TYPO3 on 10th June 2018 by Sam Thomas
+and has been addressed concerning the specific attack vector and for this generic
+`PharStreamWrapper` in TYPO3 versions 7.6.30 LTS, 8.7.17 LTS and 9.3.1 on 12th
+July 2018.
+
+* https://typo3.org/security/advisory/typo3-core-sa-2018-002/
+* https://blog.secarma.co.uk/labs/near-phar-dangerous-unserialization-wherever-you-are
+* https://youtu.be/GePBmsNJw6Y
+
+## License
+
+In general the TYPO3 core is released under the GNU General Public License version
+2 or any later version (`GPL-2.0-or-later`). In order to avoid licensing issues and
+incompatibilities this `PharStreamWrapper` is licenced under the MIT License. In case
+you duplicate or modify source code, credits are not required but really appreciated.
+
+## Credits
+
+Thanks to [Alex Pott](https://github.com/alexpott), Drupal for creating
+back-ports of all sources in order to provide compatibility with PHP v5.3.
+
+## Installation
+
+The `PharStreamWrapper` is provided as composer package `typo3/phar-stream-wrapper`
+and has minimum requirements of PHP v5.3 ([`v2`](https://github.com/TYPO3/phar-stream-wrapper/tree/v2) branch) and PHP v7.0 ([`master`](https://github.com/TYPO3/phar-stream-wrapper) branch).
+
+### Installation for PHP v7.0
+
+```
+composer require typo3/phar-stream-wrapper ^3.0
+```
+
+### Installation for PHP v5.3
+
+```
+composer require typo3/phar-stream-wrapper ^2.0
+```
+
+## Example
+
+The following example is bundled within this package, the shown
+`PharExtensionInterceptor` denies all stream wrapper invocations files
+not having the `.phar` suffix. Interceptor logic has to be individual and
+adjusted to according requirements.
+
+```
+$behavior = new \TYPO3\PharStreamWrapper\Behavior();
+Manager::initialize(
+ $behavior->withAssertion(new PharExtensionInterceptor())
+);
+
+if (in_array('phar', stream_get_wrappers())) {
+ stream_wrapper_unregister('phar');
+ stream_wrapper_register('phar', 'TYPO3\\PharStreamWrapper\\PharStreamWrapper');
+}
+```
+
+* `PharStreamWrapper` defined as class reference will be instantiated each time
+ `phar://` streams shall be processed.
+* `Manager` as singleton pattern being called by `PharStreamWrapper` instances
+ in order to retrieve individual behavior and settings.
+* `Behavior` holds reference to interceptor(s) that shall assert correct/allowed
+ invocation of a given `$path` for a given `$command`. Interceptors implement
+ the interface `Assertable`. Interceptors can act individually on following
+ commands or handle all of them in case not defined specifically:
+ + `COMMAND_DIR_OPENDIR`
+ + `COMMAND_MKDIR`
+ + `COMMAND_RENAME`
+ + `COMMAND_RMDIR`
+ + `COMMAND_STEAM_METADATA`
+ + `COMMAND_STREAM_OPEN`
+ + `COMMAND_UNLINK`
+ + `COMMAND_URL_STAT`
+
+## Interceptor
+
+The following interceptor is shipped with the package and ready to use in order
+to block any Phar invocation of files not having a `.phar` suffix. Besides that
+individual interceptors are possible of course.
+
+```
+class PharExtensionInterceptor implements Assertable
+{
+ /**
+ * Determines whether the base file name has a ".phar" suffix.
+ *
+ * @param string $path
+ * @param string $command
+ * @return bool
+ * @throws Exception
+ */
+ public function assert($path, $command)
+ {
+ if ($this->baseFileContainsPharExtension($path)) {
+ return true;
+ }
+ throw new Exception(
+ sprintf(
+ 'Unexpected file extension in "%s"',
+ $path
+ ),
+ 1535198703
+ );
+ }
+
+ /**
+ * @param string $path
+ * @return bool
+ */
+ private function baseFileContainsPharExtension($path)
+ {
+ $baseFile = Helper::determineBaseFile($path);
+ if ($baseFile === null) {
+ return false;
+ }
+ $fileExtension = pathinfo($baseFile, PATHINFO_EXTENSION);
+ return strtolower($fileExtension) === 'phar';
+ }
+}
+```
+
+## Helper
+
+* `Helper::determineBaseFile(string $path)`: Determines base file that can be
+ accessed using the regular file system. For instance the following path
+ `phar:///home/user/bundle.phar/content.txt` would be resolved to
+ `/home/user/bundle.phar`.
+* `Helper::resetOpCache()`: Resets PHP's OPcache if enabled as work-around for
+ issues in `include()` or `require()` calls and OPcache delivering wrong
+ results. More details can be found in PHP's bug tracker, for instance like
+ https://bugs.php.net/bug.php?id=66569
+
+## Security Contact
+
+In case of finding additional security issues in the TYPO3 project or in this
+`PharStreamWrapper` package in particular, please get in touch with the
+[TYPO3 Security Team](mailto:security@typo3.org).
diff --git a/misc/typo3/phar-stream-wrapper/composer.json b/misc/typo3/phar-stream-wrapper/composer.json
new file mode 100644
index 00000000..d308f8c8
--- /dev/null
+++ b/misc/typo3/phar-stream-wrapper/composer.json
@@ -0,0 +1,24 @@
+{
+ "name": "typo3/phar-stream-wrapper",
+ "description": "Interceptors for PHP's native phar:// stream handling",
+ "type": "library",
+ "license": "MIT",
+ "homepage": "https://typo3.org/",
+ "keywords": ["php", "phar", "stream-wrapper", "security"],
+ "require": {
+ "php": "^5.3.3|^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.36"
+ },
+ "autoload": {
+ "psr-4": {
+ "TYPO3\\PharStreamWrapper\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "TYPO3\\PharStreamWrapper\\Tests\\": "tests/"
+ }
+ }
+}
diff --git a/misc/typo3/phar-stream-wrapper/src/Assertable.php b/misc/typo3/phar-stream-wrapper/src/Assertable.php
new file mode 100644
index 00000000..a21b1da2
--- /dev/null
+++ b/misc/typo3/phar-stream-wrapper/src/Assertable.php
@@ -0,0 +1,22 @@
+assertCommands($commands);
+ $commands = $commands ?: $this->availableCommands;
+
+ $target = clone $this;
+ foreach ($commands as $command) {
+ $target->assertions[$command] = $assertable;
+ }
+ return $target;
+ }
+
+ /**
+ * @param string $path
+ * @param string $command
+ * @return bool
+ */
+ public function assert($path, $command)
+ {
+ $this->assertCommand($command);
+ $this->assertAssertionCompleteness();
+
+ return $this->assertions[$command]->assert($path, $command);
+ }
+
+ /**
+ * @param array $commands
+ */
+ private function assertCommands(array $commands)
+ {
+ $unknownCommands = array_diff($commands, $this->availableCommands);
+ if (empty($unknownCommands)) {
+ return;
+ }
+ throw new \LogicException(
+ sprintf(
+ 'Unknown commands: %s',
+ implode(', ', $unknownCommands)
+ ),
+ 1535189881
+ );
+ }
+
+ private function assertCommand($command)
+ {
+ if (in_array($command, $this->availableCommands, true)) {
+ return;
+ }
+ throw new \LogicException(
+ sprintf(
+ 'Unknown command "%s"',
+ $command
+ ),
+ 1535189882
+ );
+ }
+
+ private function assertAssertionCompleteness()
+ {
+ $undefinedAssertions = array_diff(
+ $this->availableCommands,
+ array_keys($this->assertions)
+ );
+ if (empty($undefinedAssertions)) {
+ return;
+ }
+ throw new \LogicException(
+ sprintf(
+ 'Missing assertions for commands: %s',
+ implode(', ', $undefinedAssertions)
+ ),
+ 1535189883
+ );
+ }
+}
diff --git a/misc/typo3/phar-stream-wrapper/src/Exception.php b/misc/typo3/phar-stream-wrapper/src/Exception.php
new file mode 100644
index 00000000..690121a9
--- /dev/null
+++ b/misc/typo3/phar-stream-wrapper/src/Exception.php
@@ -0,0 +1,16 @@
+= 1) {
+ // Rremove this and previous element
+ array_splice($pathParts, $partCount - 1, 2);
+ $partCount -= 2;
+ $pathPartsLength -= 2;
+ } elseif ($absolutePathPrefix) {
+ // can't go higher than root dir
+ // simply remove this part and continue
+ array_splice($pathParts, $partCount, 1);
+ $partCount--;
+ $pathPartsLength--;
+ }
+ }
+ }
+
+ return $absolutePathPrefix . implode('/', $pathParts);
+ }
+
+ /**
+ * Checks if the $path is absolute or relative (detecting either '/' or
+ * 'x:/' as first part of string) and returns TRUE if so.
+ *
+ * @param string $path File path to evaluate
+ * @return bool
+ */
+ private static function isAbsolutePath($path)
+ {
+ // Path starting with a / is always absolute, on every system
+ // On Windows also a path starting with a drive letter is absolute: X:/
+ return (isset($path[0]) ? $path[0] : null) === '/'
+ || static::isWindows() && (
+ strpos($path, ':/') === 1
+ || strpos($path, ':\\') === 1
+ );
+ }
+
+ /**
+ * @return bool
+ */
+ private static function isWindows()
+ {
+ return stripos(PHP_OS, 'WIN') === 0;
+ }
+}
\ No newline at end of file
diff --git a/misc/typo3/phar-stream-wrapper/src/Interceptor/PharExtensionInterceptor.php b/misc/typo3/phar-stream-wrapper/src/Interceptor/PharExtensionInterceptor.php
new file mode 100644
index 00000000..db500afc
--- /dev/null
+++ b/misc/typo3/phar-stream-wrapper/src/Interceptor/PharExtensionInterceptor.php
@@ -0,0 +1,55 @@
+baseFileContainsPharExtension($path)) {
+ return true;
+ }
+ throw new Exception(
+ sprintf(
+ 'Unexpected file extension in "%s"',
+ $path
+ ),
+ 1535198703
+ );
+ }
+
+ /**
+ * @param string $path
+ * @return bool
+ */
+ private function baseFileContainsPharExtension($path)
+ {
+ $baseFile = Helper::determineBaseFile($path);
+ if ($baseFile === null) {
+ return false;
+ }
+ $fileExtension = pathinfo($baseFile, PATHINFO_EXTENSION);
+ return strtolower($fileExtension) === 'phar';
+ }
+}
diff --git a/misc/typo3/phar-stream-wrapper/src/Manager.php b/misc/typo3/phar-stream-wrapper/src/Manager.php
new file mode 100644
index 00000000..1eb9735d
--- /dev/null
+++ b/misc/typo3/phar-stream-wrapper/src/Manager.php
@@ -0,0 +1,85 @@
+behavior = $behaviour;
+ }
+
+ /**
+ * @param string $path
+ * @param string $command
+ * @return bool
+ */
+ public function assert($path, $command)
+ {
+ return $this->behavior->assert($path, $command);
+ }
+}
diff --git a/misc/typo3/phar-stream-wrapper/src/PharStreamWrapper.php b/misc/typo3/phar-stream-wrapper/src/PharStreamWrapper.php
new file mode 100644
index 00000000..5a924e4c
--- /dev/null
+++ b/misc/typo3/phar-stream-wrapper/src/PharStreamWrapper.php
@@ -0,0 +1,477 @@
+internalResource)) {
+ return false;
+ }
+
+ $this->invokeInternalStreamWrapper(
+ 'closedir',
+ $this->internalResource
+ );
+ return !is_resource($this->internalResource);
+ }
+
+ /**
+ * @param string $path
+ * @param int $options
+ * @return bool
+ */
+ public function dir_opendir($path, $options)
+ {
+ $this->assert($path, Behavior::COMMAND_DIR_OPENDIR);
+ $this->internalResource = $this->invokeInternalStreamWrapper(
+ 'opendir',
+ $path,
+ $this->context
+ );
+ return is_resource($this->internalResource);
+ }
+
+ /**
+ * @return string|false
+ */
+ public function dir_readdir()
+ {
+ return $this->invokeInternalStreamWrapper(
+ 'readdir',
+ $this->internalResource
+ );
+ }
+
+ /**
+ * @return bool
+ */
+ public function dir_rewinddir()
+ {
+ if (!is_resource($this->internalResource)) {
+ return false;
+ }
+
+ $this->invokeInternalStreamWrapper(
+ 'rewinddir',
+ $this->internalResource
+ );
+ return is_resource($this->internalResource);
+ }
+
+ /**
+ * @param string $path
+ * @param int $mode
+ * @param int $options
+ * @return bool
+ */
+ public function mkdir($path, $mode, $options)
+ {
+ $this->assert($path, Behavior::COMMAND_MKDIR);
+ return $this->invokeInternalStreamWrapper(
+ 'mkdir',
+ $path,
+ $mode,
+ (bool) ($options & STREAM_MKDIR_RECURSIVE),
+ $this->context
+ );
+ }
+
+ /**
+ * @param string $path_from
+ * @param string $path_to
+ * @return bool
+ */
+ public function rename($path_from, $path_to)
+ {
+ $this->assert($path_from, Behavior::COMMAND_RENAME);
+ $this->assert($path_to, Behavior::COMMAND_RENAME);
+ return $this->invokeInternalStreamWrapper(
+ 'rename',
+ $path_from,
+ $path_to,
+ $this->context
+ );
+ }
+
+ /**
+ * @param string $path
+ * @param int $options
+ * @return bool
+ */
+ public function rmdir($path, $options)
+ {
+ $this->assert($path, Behavior::COMMAND_RMDIR);
+ return $this->invokeInternalStreamWrapper(
+ 'rmdir',
+ $path,
+ $this->context
+ );
+ }
+
+ /**
+ * @param int $cast_as
+ */
+ public function stream_cast($cast_as)
+ {
+ throw new Exception(
+ 'Method stream_select() cannot be used',
+ 1530103999
+ );
+ }
+
+ public function stream_close()
+ {
+ $this->invokeInternalStreamWrapper(
+ 'fclose',
+ $this->internalResource
+ );
+ }
+
+ /**
+ * @return bool
+ */
+ public function stream_eof()
+ {
+ return $this->invokeInternalStreamWrapper(
+ 'feof',
+ $this->internalResource
+ );
+ }
+
+ /**
+ * @return bool
+ */
+ public function stream_flush()
+ {
+ return $this->invokeInternalStreamWrapper(
+ 'fflush',
+ $this->internalResource
+ );
+ }
+
+ /**
+ * @param int $operation
+ * @return bool
+ */
+ public function stream_lock($operation)
+ {
+ return $this->invokeInternalStreamWrapper(
+ 'flock',
+ $this->internalResource,
+ $operation
+ );
+ }
+
+ /**
+ * @param string $path
+ * @param int $option
+ * @param string|int $value
+ * @return bool
+ */
+ public function stream_metadata($path, $option, $value)
+ {
+ $this->assert($path, Behavior::COMMAND_STEAM_METADATA);
+ if ($option === STREAM_META_TOUCH) {
+ return call_user_func_array(
+ array($this, 'invokeInternalStreamWrapper'),
+ array_merge(array('touch', $path), (array) $value)
+ );
+ }
+ if ($option === STREAM_META_OWNER_NAME || $option === STREAM_META_OWNER) {
+ return $this->invokeInternalStreamWrapper(
+ 'chown',
+ $path,
+ $value
+ );
+ }
+ if ($option === STREAM_META_GROUP_NAME || $option === STREAM_META_GROUP) {
+ return $this->invokeInternalStreamWrapper(
+ 'chgrp',
+ $path,
+ $value
+ );
+ }
+ if ($option === STREAM_META_ACCESS) {
+ return $this->invokeInternalStreamWrapper(
+ 'chmod',
+ $path,
+ $value
+ );
+ }
+ return false;
+ }
+
+ /**
+ * @param string $path
+ * @param string $mode
+ * @param int $options
+ * @param string|null $opened_path
+ * @return bool
+ */
+ public function stream_open(
+ $path,
+ $mode,
+ $options,
+ &$opened_path = null
+ ) {
+ $this->assert($path, Behavior::COMMAND_STREAM_OPEN);
+ $arguments = array($path, $mode, (bool) ($options & STREAM_USE_PATH));
+ // only add stream context for non include/require calls
+ if (!($options & static::STREAM_OPEN_FOR_INCLUDE)) {
+ $arguments[] = $this->context;
+ // work around https://bugs.php.net/bug.php?id=66569
+ // for including files from Phar stream with OPcache enabled
+ } else {
+ Helper::resetOpCache();
+ }
+ $this->internalResource = call_user_func_array(
+ array($this, 'invokeInternalStreamWrapper'),
+ array_merge(array('fopen'), $arguments)
+ );
+ if (!is_resource($this->internalResource)) {
+ return false;
+ }
+ if ($opened_path !== null) {
+ $metaData = stream_get_meta_data($this->internalResource);
+ $opened_path = $metaData['uri'];
+ }
+ return true;
+ }
+
+ /**
+ * @param int $count
+ * @return string
+ */
+ public function stream_read($count)
+ {
+ return $this->invokeInternalStreamWrapper(
+ 'fread',
+ $this->internalResource,
+ $count
+ );
+ }
+
+ /**
+ * @param int $offset
+ * @param int $whence
+ * @return bool
+ */
+ public function stream_seek($offset, $whence = SEEK_SET)
+ {
+ return $this->invokeInternalStreamWrapper(
+ 'fseek',
+ $this->internalResource,
+ $offset,
+ $whence
+ ) !== -1;
+ }
+
+ /**
+ * @param int $option
+ * @param int $arg1
+ * @param int $arg2
+ * @return bool
+ */
+ public function stream_set_option($option, $arg1, $arg2)
+ {
+ if ($option === STREAM_OPTION_BLOCKING) {
+ return $this->invokeInternalStreamWrapper(
+ 'stream_set_blocking',
+ $this->internalResource,
+ $arg1
+ );
+ }
+ if ($option === STREAM_OPTION_READ_TIMEOUT) {
+ return $this->invokeInternalStreamWrapper(
+ 'stream_set_timeout',
+ $this->internalResource,
+ $arg1,
+ $arg2
+ );
+ }
+ if ($option === STREAM_OPTION_WRITE_BUFFER) {
+ return $this->invokeInternalStreamWrapper(
+ 'stream_set_write_buffer',
+ $this->internalResource,
+ $arg2
+ ) === 0;
+ }
+ return false;
+ }
+
+ /**
+ * @return array
+ */
+ public function stream_stat()
+ {
+ return $this->invokeInternalStreamWrapper(
+ 'fstat',
+ $this->internalResource
+ );
+ }
+
+ /**
+ * @return int
+ */
+ public function stream_tell()
+ {
+ return $this->invokeInternalStreamWrapper(
+ 'ftell',
+ $this->internalResource
+ );
+ }
+
+ /**
+ * @param int $new_size
+ * @return bool
+ */
+ public function stream_truncate($new_size)
+ {
+ return $this->invokeInternalStreamWrapper(
+ 'ftruncate',
+ $this->internalResource,
+ $new_size
+ );
+ }
+
+ /**
+ * @param string $data
+ * @return int
+ */
+ public function stream_write($data)
+ {
+ return $this->invokeInternalStreamWrapper(
+ 'fwrite',
+ $this->internalResource,
+ $data
+ );
+ }
+
+ /**
+ * @param string $path
+ * @return bool
+ */
+ public function unlink($path)
+ {
+ $this->assert($path, Behavior::COMMAND_UNLINK);
+ return $this->invokeInternalStreamWrapper(
+ 'unlink',
+ $path,
+ $this->context
+ );
+ }
+
+ /**
+ * @param string $path
+ * @param int $flags
+ * @return array|false
+ */
+ public function url_stat($path, $flags)
+ {
+ $this->assert($path, Behavior::COMMAND_URL_STAT);
+ $functionName = $flags & STREAM_URL_STAT_QUIET ? '@stat' : 'stat';
+ return $this->invokeInternalStreamWrapper($functionName, $path);
+ }
+
+ /**
+ * @param string $path
+ * @param string $command
+ */
+ protected function assert($path, $command)
+ {
+ if ($this->resolveAssertable()->assert($path, $command) === true) {
+ return;
+ }
+
+ throw new Exception(
+ sprintf(
+ 'Denied invocation of "%s" for command "%s"',
+ $path,
+ $command
+ ),
+ 1535189880
+ );
+ }
+
+ /**
+ * @return Assertable
+ */
+ protected function resolveAssertable()
+ {
+ return Manager::instance();
+ }
+
+ /**
+ * Invokes commands on the native PHP Phar stream wrapper.
+ *
+ * @param string $functionName
+ * @param mixed ...$arguments
+ * @return mixed
+ */
+ private function invokeInternalStreamWrapper($functionName)
+ {
+ $arguments = func_get_args();
+ array_shift($arguments);
+ $silentExecution = $functionName{0} === '@';
+ $functionName = ltrim($functionName, '@');
+ $this->restoreInternalSteamWrapper();
+
+ try {
+ if ($silentExecution) {
+ $result = @call_user_func_array($functionName, $arguments);
+ } else {
+ $result = call_user_func_array($functionName, $arguments);
+ }
+ } catch (\Exception $exception) {
+ $this->registerStreamWrapper();
+ throw $exception;
+ } catch (\Throwable $throwable) {
+ $this->registerStreamWrapper();
+ throw $throwable;
+ }
+
+ $this->registerStreamWrapper();
+ return $result;
+ }
+
+ private function restoreInternalSteamWrapper()
+ {
+ stream_wrapper_restore('phar');
+ }
+
+ private function registerStreamWrapper()
+ {
+ stream_wrapper_unregister('phar');
+ stream_wrapper_register('phar', get_class($this));
+ }
+}
diff --git a/modules/aggregator/aggregator.info b/modules/aggregator/aggregator.info
index e8645d1f..9f05dcf4 100644
--- a/modules/aggregator/aggregator.info
+++ b/modules/aggregator/aggregator.info
@@ -7,8 +7,7 @@ files[] = aggregator.test
configure = admin/config/services/aggregator/settings
stylesheets[all][] = aggregator.css
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/aggregator/tests/aggregator_test.info b/modules/aggregator/tests/aggregator_test.info
index e6d5a0a7..64c3fe42 100644
--- a/modules/aggregator/tests/aggregator_test.info
+++ b/modules/aggregator/tests/aggregator_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/block/block.info b/modules/block/block.info
index 934bfdea..a2e05b16 100644
--- a/modules/block/block.info
+++ b/modules/block/block.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = block.test
configure = admin/structure/block
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/block/tests/block_test.info b/modules/block/tests/block_test.info
index d7e22203..6b140b50 100644
--- a/modules/block/tests/block_test.info
+++ b/modules/block/tests/block_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/block/tests/themes/block_test_theme/block_test_theme.info b/modules/block/tests/themes/block_test_theme/block_test_theme.info
index 31b43824..b7f49ff8 100644
--- a/modules/block/tests/themes/block_test_theme/block_test_theme.info
+++ b/modules/block/tests/themes/block_test_theme/block_test_theme.info
@@ -13,8 +13,7 @@ regions[footer] = Footer
regions[highlighted] = Highlighted
regions[help] = Help
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/blog/blog.info b/modules/blog/blog.info
index 84ad946d..953836c6 100644
--- a/modules/blog/blog.info
+++ b/modules/blog/blog.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
files[] = blog.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/book/book.info b/modules/book/book.info
index 53e454bf..071f910e 100644
--- a/modules/book/book.info
+++ b/modules/book/book.info
@@ -7,8 +7,7 @@ files[] = book.test
configure = admin/content/book/settings
stylesheets[all][] = book.css
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/book/book.module b/modules/book/book.module
index 7afed9ae..32047f93 100644
--- a/modules/book/book.module
+++ b/modules/book/book.module
@@ -768,11 +768,13 @@ function book_prev($book_link) {
return NULL;
}
$flat = book_get_flat_menu($book_link);
- // Assigning the array to $flat resets the array pointer for use with each().
+ reset($flat);
$curr = NULL;
do {
$prev = $curr;
- list($key, $curr) = each($flat);
+ $curr = current($flat);
+ $key = key($flat);
+ next($flat);
} while ($key && $key != $book_link['mlid']);
if ($key == $book_link['mlid']) {
@@ -806,9 +808,10 @@ function book_prev($book_link) {
*/
function book_next($book_link) {
$flat = book_get_flat_menu($book_link);
- // Assigning the array to $flat resets the array pointer for use with each().
+ reset($flat);
do {
- list($key, $curr) = each($flat);
+ $key = key($flat);
+ next($flat);
}
while ($key && $key != $book_link['mlid']);
diff --git a/modules/color/color.info b/modules/color/color.info
index 0d17ce11..0ea9bcf5 100644
--- a/modules/color/color.info
+++ b/modules/color/color.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
files[] = color.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/comment/comment.info b/modules/comment/comment.info
index 5d5abbf4..601c769e 100644
--- a/modules/comment/comment.info
+++ b/modules/comment/comment.info
@@ -9,8 +9,7 @@ files[] = comment.test
configure = admin/content/comment
stylesheets[all][] = comment.css
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/contact/contact.info b/modules/contact/contact.info
index b365daf9..af662b64 100644
--- a/modules/contact/contact.info
+++ b/modules/contact/contact.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = contact.test
configure = admin/structure/contact
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/contextual/contextual.info b/modules/contextual/contextual.info
index ba47a4cb..5a79fb6d 100644
--- a/modules/contextual/contextual.info
+++ b/modules/contextual/contextual.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
files[] = contextual.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/dashboard/dashboard.info b/modules/dashboard/dashboard.info
index d6e98660..850c896b 100644
--- a/modules/dashboard/dashboard.info
+++ b/modules/dashboard/dashboard.info
@@ -7,8 +7,7 @@ files[] = dashboard.test
dependencies[] = block
configure = admin/dashboard/customize
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/dblog/dblog.info b/modules/dblog/dblog.info
index cb85f811..345995b3 100644
--- a/modules/dblog/dblog.info
+++ b/modules/dblog/dblog.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
files[] = dblog.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/field/field.info b/modules/field/field.info
index e05108ec..0c2a5a90 100644
--- a/modules/field/field.info
+++ b/modules/field/field.info
@@ -11,8 +11,7 @@ dependencies[] = field_sql_storage
required = TRUE
stylesheets[all][] = theme/field.css
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.info b/modules/field/modules/field_sql_storage/field_sql_storage.info
index 05434613..50ffa0ea 100644
--- a/modules/field/modules/field_sql_storage/field_sql_storage.info
+++ b/modules/field/modules/field_sql_storage/field_sql_storage.info
@@ -7,8 +7,7 @@ dependencies[] = field
files[] = field_sql_storage.test
required = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/field/modules/list/list.info b/modules/field/modules/list/list.info
index bef7e4a2..03a93407 100644
--- a/modules/field/modules/list/list.info
+++ b/modules/field/modules/list/list.info
@@ -7,8 +7,7 @@ dependencies[] = field
dependencies[] = options
files[] = tests/list.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/field/modules/list/list.install b/modules/field/modules/list/list.install
index 2386f048..c10fbc84 100644
--- a/modules/field/modules/list/list.install
+++ b/modules/field/modules/list/list.install
@@ -61,7 +61,7 @@ function list_update_7001() {
// Additionally, float keys need to be disambiguated ('.5' is '0.5').
if ($field['type'] == 'list_number' && !empty($allowed_values)) {
- $keys = array_map(create_function('$a', 'return (string) (float) $a;'), array_keys($allowed_values));
+ $keys = array_map('_list_update_7001_float_string_cast', array_keys($allowed_values));
$allowed_values = array_combine($keys, array_values($allowed_values));
}
@@ -88,6 +88,13 @@ function list_update_7001() {
}
}
+/**
+ * Helper callback function to cast the array element.
+ */
+function _list_update_7001_float_string_cast($element) {
+ return (string) (float) $element;
+}
+
/**
* Helper function for list_update_7001: extract allowed values from a string.
*
diff --git a/modules/field/modules/list/tests/list_test.info b/modules/field/modules/list/tests/list_test.info
index 2d4d6cce..e4417a93 100644
--- a/modules/field/modules/list/tests/list_test.info
+++ b/modules/field/modules/list/tests/list_test.info
@@ -5,8 +5,7 @@ package = Testing
version = VERSION
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/field/modules/number/number.info b/modules/field/modules/number/number.info
index c65d94ae..97f5a7c8 100644
--- a/modules/field/modules/number/number.info
+++ b/modules/field/modules/number/number.info
@@ -6,8 +6,7 @@ core = 7.x
dependencies[] = field
files[] = number.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/field/modules/number/number.test b/modules/field/modules/number/number.test
index 839da36c..db225855 100644
--- a/modules/field/modules/number/number.test
+++ b/modules/field/modules/number/number.test
@@ -69,7 +69,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
$id = $match[1];
$this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
- $this->assertRaw(round($value, 2), 'Value is displayed.');
+ $this->assertRaw($value, 'Value is displayed.');
// Try to create entries with more than one decimal separator; assert fail.
$wrong_entries = array(
diff --git a/modules/field/modules/options/options.info b/modules/field/modules/options/options.info
index 632ca24f..b7d068d9 100644
--- a/modules/field/modules/options/options.info
+++ b/modules/field/modules/options/options.info
@@ -6,8 +6,7 @@ core = 7.x
dependencies[] = field
files[] = options.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/field/modules/text/text.info b/modules/field/modules/text/text.info
index fe93a35a..6ed7fad4 100644
--- a/modules/field/modules/text/text.info
+++ b/modules/field/modules/text/text.info
@@ -7,8 +7,7 @@ dependencies[] = field
files[] = text.test
required = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/field/tests/field_test.info b/modules/field/tests/field_test.info
index ce3c7251..6066d769 100644
--- a/modules/field/tests/field_test.info
+++ b/modules/field/tests/field_test.info
@@ -6,8 +6,7 @@ files[] = field_test.entity.inc
version = VERSION
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/field_ui/field_ui.info b/modules/field_ui/field_ui.info
index a415ae99..76df6f33 100644
--- a/modules/field_ui/field_ui.info
+++ b/modules/field_ui/field_ui.info
@@ -6,8 +6,7 @@ core = 7.x
dependencies[] = field
files[] = field_ui.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/file/file.field.inc b/modules/file/file.field.inc
index d592381b..fc1a1df2 100644
--- a/modules/file/file.field.inc
+++ b/modules/file/file.field.inc
@@ -599,7 +599,7 @@ function file_field_widget_value($element, $input = FALSE, $form_state) {
// If the display field is present make sure its unchecked value is saved.
$field = field_widget_field($element, $form_state);
if (empty($input['display'])) {
- $input['display'] = $field['settings']['display_field'] ? 0 : 1;
+ $input['display'] = !empty($field['settings']['display_field']) ? 0 : 1;
}
}
diff --git a/modules/file/file.info b/modules/file/file.info
index 7269b4ad..03781304 100644
--- a/modules/file/file.info
+++ b/modules/file/file.info
@@ -6,8 +6,7 @@ core = 7.x
dependencies[] = field
files[] = tests/file.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/file/file.module b/modules/file/file.module
index 1e98f11b..eea58470 100644
--- a/modules/file/file.module
+++ b/modules/file/file.module
@@ -239,6 +239,9 @@ function file_ajax_upload() {
$form_parents = func_get_args();
$form_build_id = (string) array_pop($form_parents);
+ // Sanitize form parents before using them.
+ $form_parents = array_filter($form_parents, 'element_child');
+
if (empty($_POST['form_build_id']) || $form_build_id != $_POST['form_build_id']) {
// Invalid request.
drupal_set_message(t('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (@size) that this server supports.', array('@size' => format_size(file_upload_max_size()))), 'error');
diff --git a/modules/file/tests/file.test b/modules/file/tests/file.test
index f764a903..849451a5 100644
--- a/modules/file/tests/file.test
+++ b/modules/file/tests/file.test
@@ -1875,3 +1875,60 @@ class FileFieldAnonymousSubmission extends FileFieldTestCase {
}
}
+
+/**
+ * Tests the file_scan_directory() function.
+ */
+class FileScanDirectory extends FileFieldTestCase {
+
+ /**
+ * @var string
+ */
+ protected $path;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getInfo() {
+ return array(
+ 'name' => 'File ScanDirectory',
+ 'description' => 'Tests the file_scan_directory() function.',
+ 'group' => 'File',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ function setUp() {
+ parent::setUp();
+
+ $this->path = 'modules/file/tests/fixtures/file_scan_ignore';
+ }
+
+ /**
+ * Tests file_scan_directory() obeys 'file_scan_ignore_directories' setting.
+ * If nomask is not passed as argument, it should use the default settings.
+ * If nomask is passed as argument, it should obey this rule.
+ */
+ public function testNoMask() {
+ $files = file_scan_directory($this->path, '/\.txt$/');
+ $this->assertEqual(3, count($files), '3 text files found when not ignoring directories.');
+
+ global $conf;
+ $conf['file_scan_ignore_directories'] = array('frontend_framework');
+
+ $files = file_scan_directory($this->path, '/\.txt$/');
+ $this->assertEqual(1, count($files), '1 text files found when ignoring directories called "frontend_framework".');
+
+ // Make that directories specified by default still work when a new nomask is provided.
+ $files = file_scan_directory($this->path, '/\.txt$/', array('nomask' => '/^c.txt/'));
+ $this->assertEqual(2, count($files), '2 text files found when an "nomask" option is passed in.');
+
+ // Ensure that the directories in file_scan_ignore_directories are escaped using preg_quote.
+ $conf['file_scan_ignore_directories'] = array('frontend.*');
+ $files = file_scan_directory($this->path, '/\.txt$/');
+ $this->assertEqual(3, count($files), '2 text files found when ignoring a directory that is not there.');
+ }
+
+}
diff --git a/modules/file/tests/file_module_test.info b/modules/file/tests/file_module_test.info
index 958bf660..6593ab29 100644
--- a/modules/file/tests/file_module_test.info
+++ b/modules/file/tests/file_module_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/file/tests/fixtures/file_scan_ignore/a.txt b/modules/file/tests/fixtures/file_scan_ignore/a.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/modules/file/tests/fixtures/file_scan_ignore/frontend_framework/b.txt b/modules/file/tests/fixtures/file_scan_ignore/frontend_framework/b.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/modules/file/tests/fixtures/file_scan_ignore/frontend_framework/c.txt b/modules/file/tests/fixtures/file_scan_ignore/frontend_framework/c.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/modules/filter/filter.info b/modules/filter/filter.info
index 4a46c85c..b8a07447 100644
--- a/modules/filter/filter.info
+++ b/modules/filter/filter.info
@@ -7,8 +7,7 @@ files[] = filter.test
required = TRUE
configure = admin/config/content/formats
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/forum/forum.info b/modules/forum/forum.info
index d5b1c769..859b4a7b 100644
--- a/modules/forum/forum.info
+++ b/modules/forum/forum.info
@@ -9,8 +9,7 @@ files[] = forum.test
configure = admin/structure/forum
stylesheets[all][] = forum.css
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/help/help.info b/modules/help/help.info
index 2c851ea9..90d05b81 100644
--- a/modules/help/help.info
+++ b/modules/help/help.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
files[] = help.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/image/image.admin.inc b/modules/image/image.admin.inc
index cebe8940..0fbdc0b7 100644
--- a/modules/image/image.admin.inc
+++ b/modules/image/image.admin.inc
@@ -736,7 +736,8 @@ function theme_image_style_effects($variables) {
if (!isset($form[$key]['#access']) || $form[$key]['#access']) {
$rows[] = array(
'data' => $row,
- 'class' => !empty($form[$key]['weight']['#access']) || $key == 'new' ? array('draggable') : array(),
+ // Use a strict (===) comparison since $key can be 0.
+ 'class' => !empty($form[$key]['weight']['#access']) || $key === 'new' ? array('draggable') : array(),
);
}
}
diff --git a/modules/image/image.info b/modules/image/image.info
index dd1200c6..ff15f3b9 100644
--- a/modules/image/image.info
+++ b/modules/image/image.info
@@ -7,8 +7,7 @@ dependencies[] = file
files[] = image.test
configure = admin/config/media/image-styles
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/image/tests/image_module_test.info b/modules/image/tests/image_module_test.info
index c6b3a6ab..4226c34f 100644
--- a/modules/image/tests/image_module_test.info
+++ b/modules/image/tests/image_module_test.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = image_module_test.module
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/locale/locale.info b/modules/locale/locale.info
index 674d1f56..9fff4fe0 100644
--- a/modules/locale/locale.info
+++ b/modules/locale/locale.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = locale.test
configure = admin/config/regional/language
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/locale/locale.test b/modules/locale/locale.test
index db87e055..b890b061 100644
--- a/modules/locale/locale.test
+++ b/modules/locale/locale.test
@@ -3188,11 +3188,7 @@ class LocaleLanguageNegotiationInfoFunctionalTest extends DrupalWebTestCase {
foreach (language_types_info() as $type => $info) {
if (isset($info['fixed'])) {
$negotiation = variable_get("language_negotiation_$type", array());
- $equal = count($info['fixed']) == count($negotiation);
- while ($equal && list($id) = each($negotiation)) {
- list(, $info_id) = each($info['fixed']);
- $equal = $info_id == $id;
- }
+ $equal = array_keys($negotiation) === array_values($info['fixed']);
$this->assertTrue($equal, format_string('language negotiation for %type is properly set up', array('%type' => $type)));
}
}
diff --git a/modules/locale/tests/locale_test.info b/modules/locale/tests/locale_test.info
index 49da5e51..bb4cbaa0 100644
--- a/modules/locale/tests/locale_test.info
+++ b/modules/locale/tests/locale_test.info
@@ -5,8 +5,7 @@ package = Testing
version = VERSION
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/menu/menu.info b/modules/menu/menu.info
index 9b7ef57b..1d8fd3d8 100644
--- a/modules/menu/menu.info
+++ b/modules/menu/menu.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = menu.test
configure = admin/structure/menu
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/node/node.info b/modules/node/node.info
index 11ae2cd3..9a267fc9 100644
--- a/modules/node/node.info
+++ b/modules/node/node.info
@@ -9,8 +9,7 @@ required = TRUE
configure = admin/structure/types
stylesheets[all][] = node.css
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/node/tests/node_access_test.info b/modules/node/tests/node_access_test.info
index 00792901..1ba891b8 100644
--- a/modules/node/tests/node_access_test.info
+++ b/modules/node/tests/node_access_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/node/tests/node_test.info b/modules/node/tests/node_test.info
index f56e2e51..a46165f3 100644
--- a/modules/node/tests/node_test.info
+++ b/modules/node/tests/node_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/node/tests/node_test_exception.info b/modules/node/tests/node_test_exception.info
index a4c11859..5b51ffff 100644
--- a/modules/node/tests/node_test_exception.info
+++ b/modules/node/tests/node_test_exception.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/openid/openid.info b/modules/openid/openid.info
index 69d26632..11574a73 100644
--- a/modules/openid/openid.info
+++ b/modules/openid/openid.info
@@ -5,8 +5,7 @@ package = Core
core = 7.x
files[] = openid.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/openid/tests/openid_test.info b/modules/openid/tests/openid_test.info
index 7186198b..4e385bdb 100644
--- a/modules/openid/tests/openid_test.info
+++ b/modules/openid/tests/openid_test.info
@@ -6,8 +6,7 @@ core = 7.x
dependencies[] = openid
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/overlay/overlay.info b/modules/overlay/overlay.info
index 1bf7e9ef..18f69083 100644
--- a/modules/overlay/overlay.info
+++ b/modules/overlay/overlay.info
@@ -4,8 +4,7 @@ package = Core
version = VERSION
core = 7.x
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/path/path.info b/modules/path/path.info
index b5b0eb9b..61578133 100644
--- a/modules/path/path.info
+++ b/modules/path/path.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = path.test
configure = admin/config/search/path
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/path/path.test b/modules/path/path.test
index edecff5c..f6131ce6 100644
--- a/modules/path/path.test
+++ b/modules/path/path.test
@@ -21,7 +21,7 @@ class PathTestCase extends DrupalWebTestCase {
parent::setUp('path');
// Create test user and login.
- $web_user = $this->drupalCreateUser(array('create page content', 'edit own page content', 'administer url aliases', 'create url aliases'));
+ $web_user = $this->drupalCreateUser(array('create page content', 'edit own page content', 'administer url aliases', 'create url aliases', 'access content overview'));
$this->drupalLogin($web_user);
}
@@ -160,6 +160,34 @@ class PathTestCase extends DrupalWebTestCase {
$this->drupalGet($edit['path[alias]']);
$this->assertNoText($node1->title, 'Alias was successfully deleted.');
$this->assertResponse(404);
+
+ // Create third test node.
+ $node3 = $this->drupalCreateNode();
+
+ // Create an invalid alias with a leading slash and verify that the slash
+ // is removed when the link is generated. This ensures that URL aliases
+ // cannot be used to inject external URLs.
+ // @todo The user interface should either display an error message or
+ // automatically trim these invalid aliases, rather than allowing them to
+ // be silently created, at which point the functional aspects of this
+ // test will need to be moved elsewhere and switch to using a
+ // programmatically-created alias instead.
+ $alias = $this->randomName(8);
+ $edit = array('path[alias]' => '/' . $alias);
+ $this->drupalPost('node/' . $node3->nid . '/edit', $edit, t('Save'));
+ $this->drupalGet('admin/content');
+ // This checks the link href before clicking it, rather than using
+ // DrupalWebTestCase::assertUrl() after clicking it, because the test
+ // browser does not always preserve the correct number of slashes in the
+ // URL when it visits internal links; using DrupalWebTestCase::assertUrl()
+ // would actually make the test pass unconditionally on the testbot (or
+ // anywhere else where Drupal is installed in a subdirectory).
+ $link_xpath = $this->xpath('//a[normalize-space(text())=:label]', array(':label' => $node3->title));
+ $link_href = (string) $link_xpath[0]['href'];
+ $link_prefix = base_path() . (variable_get('clean_url', 0) ? '' : '?q=');
+ $this->assertEqual($link_href, $link_prefix . $alias);
+ $this->clickLink($node3->title);
+ $this->assertResponse(404);
}
/**
diff --git a/modules/php/php.info b/modules/php/php.info
index 236f9310..0cb5e6f9 100644
--- a/modules/php/php.info
+++ b/modules/php/php.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
files[] = php.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/poll/poll.info b/modules/poll/poll.info
index eeed31d5..3ca58400 100644
--- a/modules/poll/poll.info
+++ b/modules/poll/poll.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = poll.test
stylesheets[all][] = poll.css
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/profile/profile.info b/modules/profile/profile.info
index 1480c618..f59afc43 100644
--- a/modules/profile/profile.info
+++ b/modules/profile/profile.info
@@ -11,8 +11,7 @@ configure = admin/config/people/profile
; See user_system_info_alter().
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/rdf/rdf.info b/modules/rdf/rdf.info
index 18e62970..7ac3dd98 100644
--- a/modules/rdf/rdf.info
+++ b/modules/rdf/rdf.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
files[] = rdf.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/rdf/tests/rdf_test.info b/modules/rdf/tests/rdf_test.info
index a302a7b5..bbaada74 100644
--- a/modules/rdf/tests/rdf_test.info
+++ b/modules/rdf/tests/rdf_test.info
@@ -6,8 +6,7 @@ core = 7.x
hidden = TRUE
dependencies[] = blog
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/search/search.info b/modules/search/search.info
index 248f476c..cd99637e 100644
--- a/modules/search/search.info
+++ b/modules/search/search.info
@@ -8,8 +8,7 @@ files[] = search.test
configure = admin/config/search/settings
stylesheets[all][] = search.css
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/search/tests/search_embedded_form.info b/modules/search/tests/search_embedded_form.info
index 7e1b7367..c91a0aaf 100644
--- a/modules/search/tests/search_embedded_form.info
+++ b/modules/search/tests/search_embedded_form.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/search/tests/search_extra_type.info b/modules/search/tests/search_extra_type.info
index 534edade..c4719fcb 100644
--- a/modules/search/tests/search_extra_type.info
+++ b/modules/search/tests/search_extra_type.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/search/tests/search_node_tags.info b/modules/search/tests/search_node_tags.info
index 16438984..12cba55b 100644
--- a/modules/search/tests/search_node_tags.info
+++ b/modules/search/tests/search_node_tags.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/shortcut/shortcut.info b/modules/shortcut/shortcut.info
index c490374e..7d1c261e 100644
--- a/modules/shortcut/shortcut.info
+++ b/modules/shortcut/shortcut.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = shortcut.test
configure = admin/config/user-interface/shortcut
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/drupal_web_test_case.php b/modules/simpletest/drupal_web_test_case.php
index 3124ffe8..a0872c23 100644
--- a/modules/simpletest/drupal_web_test_case.php
+++ b/modules/simpletest/drupal_web_test_case.php
@@ -3012,7 +3012,7 @@ class DrupalWebTestCase extends DrupalTestCase {
if (!$message) {
$message = t('Raw "@raw" found', array('@raw' => $raw));
}
- return $this->assert(strpos($this->drupalGetContent(), $raw) !== FALSE, $message, $group);
+ return $this->assert(strpos($this->drupalGetContent(), (string) $raw) !== FALSE, $message, $group);
}
/**
@@ -3032,7 +3032,7 @@ class DrupalWebTestCase extends DrupalTestCase {
if (!$message) {
$message = t('Raw "@raw" not found', array('@raw' => $raw));
}
- return $this->assert(strpos($this->drupalGetContent(), $raw) === FALSE, $message, $group);
+ return $this->assert(strpos($this->drupalGetContent(), (string) $raw) === FALSE, $message, $group);
}
/**
diff --git a/modules/simpletest/files/phar-1.phar b/modules/simpletest/files/phar-1.phar
new file mode 100644
index 00000000..8d25e6d4
Binary files /dev/null and b/modules/simpletest/files/phar-1.phar differ
diff --git a/modules/simpletest/simpletest.info b/modules/simpletest/simpletest.info
index 26b3485a..98e7a8bc 100644
--- a/modules/simpletest/simpletest.info
+++ b/modules/simpletest/simpletest.info
@@ -57,8 +57,7 @@ files[] = tests/upgrade/update.trigger.test
files[] = tests/upgrade/update.field.test
files[] = tests/upgrade/update.user.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/actions_loop_test.info b/modules/simpletest/tests/actions_loop_test.info
index 2edf253d..b3236062 100644
--- a/modules/simpletest/tests/actions_loop_test.info
+++ b/modules/simpletest/tests/actions_loop_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/ajax_forms_test.info b/modules/simpletest/tests/ajax_forms_test.info
index 9736647e..b8f81225 100644
--- a/modules/simpletest/tests/ajax_forms_test.info
+++ b/modules/simpletest/tests/ajax_forms_test.info
@@ -5,8 +5,7 @@ package = Testing
version = VERSION
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/ajax_test.info b/modules/simpletest/tests/ajax_test.info
index fe2f90b0..fae288b7 100644
--- a/modules/simpletest/tests/ajax_test.info
+++ b/modules/simpletest/tests/ajax_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/batch_test.info b/modules/simpletest/tests/batch_test.info
index a53e2159..b25a4bed 100644
--- a/modules/simpletest/tests/batch_test.info
+++ b/modules/simpletest/tests/batch_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/boot_test_1.info b/modules/simpletest/tests/boot_test_1.info
index 873825da..06992b60 100644
--- a/modules/simpletest/tests/boot_test_1.info
+++ b/modules/simpletest/tests/boot_test_1.info
@@ -5,8 +5,7 @@ package = Testing
version = VERSION
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/boot_test_2.info b/modules/simpletest/tests/boot_test_2.info
index e8529ba9..2926eac6 100644
--- a/modules/simpletest/tests/boot_test_2.info
+++ b/modules/simpletest/tests/boot_test_2.info
@@ -5,8 +5,7 @@ package = Testing
version = VERSION
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/bootstrap.test b/modules/simpletest/tests/bootstrap.test
index 16ac1714..effd04bf 100644
--- a/modules/simpletest/tests/bootstrap.test
+++ b/modules/simpletest/tests/bootstrap.test
@@ -729,16 +729,12 @@ class BootstrapMiscTestCase extends DrupalUnitTestCase {
* Tests that the drupal_check_memory_limit() function works as expected.
*/
function testCheckMemoryLimit() {
- $memory_limit = ini_get('memory_limit');
// Test that a very reasonable amount of memory is available.
$this->assertTrue(drupal_check_memory_limit('30MB'), '30MB of memory tested available.');
- // Get the available memory and multiply it by two to make it unreasonably
- // high.
- $twice_avail_memory = ($memory_limit * 2) . 'MB';
-
+ // Test an unlimited memory limit.
// The function should always return true if the memory limit is set to -1.
- $this->assertTrue(drupal_check_memory_limit($twice_avail_memory, -1), 'drupal_check_memory_limit() returns TRUE when a limit of -1 (none) is supplied');
+ $this->assertTrue(drupal_check_memory_limit('9999999999YB', -1), 'drupal_check_memory_limit() returns TRUE when a limit of -1 (none) is supplied');
// Test that even though we have 30MB of memory available - the function
// returns FALSE when given an upper limit for how much memory can be used.
diff --git a/modules/simpletest/tests/common_test.info b/modules/simpletest/tests/common_test.info
index 8c56f80c..8c752667 100644
--- a/modules/simpletest/tests/common_test.info
+++ b/modules/simpletest/tests/common_test.info
@@ -7,8 +7,7 @@ stylesheets[all][] = common_test.css
stylesheets[print][] = common_test.print.css
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/common_test_cron_helper.info b/modules/simpletest/tests/common_test_cron_helper.info
index bf8a7290..4de0614a 100644
--- a/modules/simpletest/tests/common_test_cron_helper.info
+++ b/modules/simpletest/tests/common_test_cron_helper.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/database_test.info b/modules/simpletest/tests/database_test.info
index 3ff31eda..cbe4d253 100644
--- a/modules/simpletest/tests/database_test.info
+++ b/modules/simpletest/tests/database_test.info
@@ -5,8 +5,7 @@ package = Testing
version = VERSION
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/drupal_autoload_test/drupal_autoload_test.info b/modules/simpletest/tests/drupal_autoload_test/drupal_autoload_test.info
index b9715351..d02d9aaa 100644
--- a/modules/simpletest/tests/drupal_autoload_test/drupal_autoload_test.info
+++ b/modules/simpletest/tests/drupal_autoload_test/drupal_autoload_test.info
@@ -7,8 +7,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info b/modules/simpletest/tests/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
index f918fdc2..70e739a6 100644
--- a/modules/simpletest/tests/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
+++ b/modules/simpletest/tests/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info b/modules/simpletest/tests/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
index 9edaf9f6..ce798aab 100644
--- a/modules/simpletest/tests/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
+++ b/modules/simpletest/tests/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/entity_cache_test.info b/modules/simpletest/tests/entity_cache_test.info
index 212ce833..3bb91af8 100644
--- a/modules/simpletest/tests/entity_cache_test.info
+++ b/modules/simpletest/tests/entity_cache_test.info
@@ -6,8 +6,7 @@ core = 7.x
dependencies[] = entity_cache_test_dependency
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/entity_cache_test_dependency.info b/modules/simpletest/tests/entity_cache_test_dependency.info
index 58049876..5ce064a8 100644
--- a/modules/simpletest/tests/entity_cache_test_dependency.info
+++ b/modules/simpletest/tests/entity_cache_test_dependency.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/entity_crud_hook_test.info b/modules/simpletest/tests/entity_crud_hook_test.info
index 9f5f3ead..8afcdee4 100644
--- a/modules/simpletest/tests/entity_crud_hook_test.info
+++ b/modules/simpletest/tests/entity_crud_hook_test.info
@@ -5,8 +5,7 @@ package = Testing
version = VERSION
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/entity_query_access_test.info b/modules/simpletest/tests/entity_query_access_test.info
index 328e5d9c..f80bf867 100644
--- a/modules/simpletest/tests/entity_query_access_test.info
+++ b/modules/simpletest/tests/entity_query_access_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/error_test.info b/modules/simpletest/tests/error_test.info
index bf6e044b..eff06a10 100644
--- a/modules/simpletest/tests/error_test.info
+++ b/modules/simpletest/tests/error_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/file.test b/modules/simpletest/tests/file.test
index 89ecac7a..032f2cba 100644
--- a/modules/simpletest/tests/file.test
+++ b/modules/simpletest/tests/file.test
@@ -957,6 +957,15 @@ class FileDirectoryTest extends FileTestCase {
$path = file_create_filename($basename, $directory);
$this->assertEqual($path, $expected, format_string('Creating a new filepath from %original equals %new.', array('%new' => $path, '%original' => $original)), 'File');
+ try {
+ $filename = "a\xFFtest\x80€.txt";
+ file_create_filename($filename, $directory);
+ $this->fail('Expected exception not thrown');
+ }
+ catch (RuntimeException $e) {
+ $this->assertEqual("Invalid filename '$filename'", $e->getMessage());
+ }
+
// @TODO: Finally we copy a file into a directory several times, to ensure a properly iterating filename suffix.
}
@@ -989,6 +998,14 @@ class FileDirectoryTest extends FileTestCase {
$this->assertNotEqual($path, $destination, 'A new filepath destination is created when filepath destination already exists with FILE_EXISTS_RENAME.', 'File');
$path = file_destination($destination, FILE_EXISTS_ERROR);
$this->assertEqual($path, FALSE, 'An error is returned when filepath destination already exists with FILE_EXISTS_ERROR.', 'File');
+
+ try {
+ file_destination("core/misc/a\xFFtest\x80€.txt", FILE_EXISTS_REPLACE);
+ $this->fail('Expected exception not thrown');
+ }
+ catch (RuntimeException $e) {
+ $this->assertEqual("Invalid filename 'a\xFFtest\x80€.txt'", $e->getMessage());
+ }
}
/**
@@ -2766,4 +2783,64 @@ class StreamWrapperTest extends DrupalWebTestCase {
$this->assertTrue(file_stream_wrapper_valid_scheme(file_uri_scheme('public://asdf')), 'Got a valid stream scheme from public://asdf');
$this->assertFalse(file_stream_wrapper_valid_scheme(file_uri_scheme('foo://asdf')), 'Did not get a valid stream scheme from foo://asdf');
}
+
+ /**
+ * Tests that phar stream wrapper is registered as expected.
+ *
+ * @see file_get_stream_wrappers()
+ */
+ public function testPharStreamWrapperRegistration() {
+ if (!class_exists('Phar', FALSE)) {
+ $this->assertFalse(in_array('phar', stream_get_wrappers(), TRUE), 'PHP is compiled without phar support. Therefore, no phar stream wrapper is registered.');
+ }
+ elseif (version_compare(PHP_VERSION, '5.3.3', '<')) {
+ $this->assertFalse(in_array('phar', stream_get_wrappers(), TRUE), 'The PHP version is <5.3.3. The built-in phar stream wrapper has been unregistered and not replaced.');
+ }
+ else {
+ $this->assertTrue(in_array('phar', stream_get_wrappers(), TRUE), 'A phar stream wrapper is registered.');
+ $this->assertFalse(file_stream_wrapper_valid_scheme('phar'), 'The phar scheme is not a valid scheme for Drupal File API usage.');
+ }
+
+ // Ensure that calling file_get_stream_wrappers() multiple times, both
+ // without and with a drupal_static_reset() in between, does not create
+ // errors due to the PharStreamWrapperManager singleton.
+ file_get_stream_wrappers();
+ file_get_stream_wrappers();
+ drupal_static_reset('file_get_stream_wrappers');
+ file_get_stream_wrappers();
+ }
+
+ /**
+ * Tests that only valid phar files can be used.
+ */
+ public function testPharFile() {
+ if (!in_array('phar', stream_get_wrappers(), TRUE)) {
+ $this->pass('There is no phar stream wrapper registered.');
+ // Nothing else in this test is relevant when there's no phar stream
+ // wrapper. testPharStreamWrapperRegistration() is sufficient for testing
+ // the conditions of when the stream wrapper should or should not be
+ // registered.
+ return;
+ }
+
+ $base = dirname(dirname(__FILE__)) . '/files';
+
+ // Ensure that file operations via the phar:// stream wrapper work for phar
+ // files with the .phar extension.
+ $this->assertFalse(file_exists("phar://$base/phar-1.phar/no-such-file.php"));
+ $this->assertTrue(file_exists("phar://$base/phar-1.phar/index.php"));
+ $file_contents = file_get_contents("phar://$base/phar-1.phar/index.php");
+ $expected_hash = 'c7e7904ea573c5ebea3ef00bb08c1f86af1a45961fbfbeb1892ff4a98fd73ad5';
+ $this->assertIdentical($expected_hash, hash('sha256', $file_contents));
+
+ // Ensure that file operations via the phar:// stream wrapper throw an
+ // exception for files without the .phar extension.
+ try {
+ file_exists("phar://$base/image-2.jpg/index.php");
+ $this->fail('Expected exception failed to be thrown when accessing an invalid phar file.');
+ }
+ catch (Exception $e) {
+ $this->assertEqual(get_class($e), 'TYPO3\PharStreamWrapper\Exception', 'Expected exception thrown when accessing an invalid phar file.');
+ }
+ }
}
diff --git a/modules/simpletest/tests/file_test.info b/modules/simpletest/tests/file_test.info
index 3ceb3ebe..4cac2a04 100644
--- a/modules/simpletest/tests/file_test.info
+++ b/modules/simpletest/tests/file_test.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = file_test.module
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/filter_test.info b/modules/simpletest/tests/filter_test.info
index 96c6c4b5..bfc6b566 100644
--- a/modules/simpletest/tests/filter_test.info
+++ b/modules/simpletest/tests/filter_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test
index a441ceeb..e52c8c42 100644
--- a/modules/simpletest/tests/form.test
+++ b/modules/simpletest/tests/form.test
@@ -1420,6 +1420,59 @@ class FormsFormStoragePageCacheTestCase extends DrupalWebTestCase {
}
}
+/**
+ * Test cache_form.
+ */
+class FormsFormCacheTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Form caching',
+ 'description' => 'Tests storage and retrieval of forms from cache.',
+ 'group' => 'Form API',
+ );
+ }
+
+ function setUp() {
+ parent::setUp('form_test');
+ }
+
+ /**
+ * Tests storing and retrieving the form from cache.
+ */
+ function testCacheForm() {
+ $form = drupal_get_form('form_test_cache_form');
+ $form_state = array('foo' => 'bar', 'build_info' => array('baz'));
+ form_set_cache($form['#build_id'], $form, $form_state);
+
+ $cached_form_state = array();
+ $cached_form = form_get_cache($form['#build_id'], $cached_form_state);
+
+ $this->assertEqual($cached_form['#build_id'], $form['#build_id'], 'Form retrieved from cache_form successfully.');
+ $this->assertEqual($cached_form_state['foo'], 'bar', 'Data retrieved from cache_form successfully.');
+ }
+
+ /**
+ * Tests changing form_cache_expiration.
+ */
+ function testCacheFormCustomExpiration() {
+ variable_set('form_cache_expiration', -1 * (24 * 60 * 60));
+
+ $form = drupal_get_form('form_test_cache_form');
+ $form_state = array('foo' => 'bar', 'build_info' => array('baz'));
+ form_set_cache($form['#build_id'], $form, $form_state);
+
+ // Clear expired entries from cache_form, which should include the entry we
+ // just stored. Without this, the form will still be retrieved from cache.
+ cache_clear_all(NULL, 'cache_form');
+
+ $cached_form_state = array();
+ $cached_form = form_get_cache($form['#build_id'], $cached_form_state);
+
+ $this->assertNull($cached_form, 'Expired form was not returned from cache.');
+ $this->assertTrue(empty($cached_form_state), 'No data retrieved from cache for expired form.');
+ }
+}
+
/**
* Test wrapper form callbacks.
*/
diff --git a/modules/simpletest/tests/form_test.info b/modules/simpletest/tests/form_test.info
index 7706be2b..d1316bc0 100644
--- a/modules/simpletest/tests/form_test.info
+++ b/modules/simpletest/tests/form_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module
index 097e5884..9f071826 100644
--- a/modules/simpletest/tests/form_test.module
+++ b/modules/simpletest/tests/form_test.module
@@ -918,6 +918,24 @@ function form_test_storage_page_cache_rebuild($form, &$form_state) {
$form_state['rebuild'] = TRUE;
}
+/**
+ * A simple form for testing form caching.
+ */
+function form_test_cache_form($form, &$form_state) {
+ $form['title'] = array(
+ '#type' => 'textfield',
+ '#title' => 'Title',
+ '#required' => TRUE,
+ );
+
+ $form['submit'] = array(
+ '#type' => 'submit',
+ '#value' => 'Save',
+ );
+
+ return $form;
+}
+
/**
* A form for testing form labels and required marks.
*/
diff --git a/modules/simpletest/tests/image.test b/modules/simpletest/tests/image.test
index 7ca1d3a0..41569640 100644
--- a/modules/simpletest/tests/image.test
+++ b/modules/simpletest/tests/image.test
@@ -335,7 +335,9 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
);
// Systems using non-bundled GD2 don't have imagerotate. Test if available.
- if (function_exists('imagerotate')) {
+ // @todo Remove the version check once https://www.drupal.org/node/2918570
+ // is resolved.
+ if (function_exists('imagerotate') && (version_compare(PHP_VERSION, '7.0.26', '<') || (version_compare(PHP_VERSION, '7.1', '>=') && version_compare(PHP_VERSION, '7.1.12', '<')))) {
$operations += array(
'rotate_90' => array(
'function' => 'rotate',
@@ -357,8 +359,8 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
// See https://bugs.php.net/bug.php?id=65148.
// For the 40x20 test images, the dimensions resulting from rotation will
// be 1 pixel smaller in both width and height in PHP 5.5 and above.
- // @todo: If and when the PHP bug gets solved, add an upper limit
- // version check.
+ // @todo: The PHP bug was fixed in PHP 7.0.26 and 7.1.12. Change the code
+ // below to reflect that in https://www.drupal.org/node/2918570.
if (version_compare(PHP_VERSION, '5.5', '>=')) {
$operations += array(
'rotate_5' => array(
diff --git a/modules/simpletest/tests/image_test.info b/modules/simpletest/tests/image_test.info
index 82d2a3ba..25d7bc89 100644
--- a/modules/simpletest/tests/image_test.info
+++ b/modules/simpletest/tests/image_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/menu_test.info b/modules/simpletest/tests/menu_test.info
index 26d70dc6..486857d9 100644
--- a/modules/simpletest/tests/menu_test.info
+++ b/modules/simpletest/tests/menu_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/module_test.info b/modules/simpletest/tests/module_test.info
index 1ebdd859..6f06fb6b 100644
--- a/modules/simpletest/tests/module_test.info
+++ b/modules/simpletest/tests/module_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/path_test.info b/modules/simpletest/tests/path_test.info
index 43ecd96d..68bc81e3 100644
--- a/modules/simpletest/tests/path_test.info
+++ b/modules/simpletest/tests/path_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/psr_0_test/psr_0_test.info b/modules/simpletest/tests/psr_0_test/psr_0_test.info
index ca69f5c2..642a3091 100644
--- a/modules/simpletest/tests/psr_0_test/psr_0_test.info
+++ b/modules/simpletest/tests/psr_0_test/psr_0_test.info
@@ -5,8 +5,7 @@ core = 7.x
hidden = TRUE
package = Testing
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/psr_4_test/psr_4_test.info b/modules/simpletest/tests/psr_4_test/psr_4_test.info
index 75e5b0cd..edca372d 100644
--- a/modules/simpletest/tests/psr_4_test/psr_4_test.info
+++ b/modules/simpletest/tests/psr_4_test/psr_4_test.info
@@ -5,8 +5,7 @@ core = 7.x
hidden = TRUE
package = Testing
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/requirements1_test.info b/modules/simpletest/tests/requirements1_test.info
index c5b3a606..7655ca53 100644
--- a/modules/simpletest/tests/requirements1_test.info
+++ b/modules/simpletest/tests/requirements1_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/requirements2_test.info b/modules/simpletest/tests/requirements2_test.info
index b12197e8..f554d0bd 100644
--- a/modules/simpletest/tests/requirements2_test.info
+++ b/modules/simpletest/tests/requirements2_test.info
@@ -7,8 +7,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/session_test.info b/modules/simpletest/tests/session_test.info
index 4987deae..466d4116 100644
--- a/modules/simpletest/tests/session_test.info
+++ b/modules/simpletest/tests/session_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/system_dependencies_test.info b/modules/simpletest/tests/system_dependencies_test.info
index 4b03f292..f67e37b8 100644
--- a/modules/simpletest/tests/system_dependencies_test.info
+++ b/modules/simpletest/tests/system_dependencies_test.info
@@ -6,8 +6,7 @@ core = 7.x
hidden = TRUE
dependencies[] = _missing_dependency
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/system_incompatible_core_version_dependencies_test.info b/modules/simpletest/tests/system_incompatible_core_version_dependencies_test.info
index cb2749e3..41e301c2 100644
--- a/modules/simpletest/tests/system_incompatible_core_version_dependencies_test.info
+++ b/modules/simpletest/tests/system_incompatible_core_version_dependencies_test.info
@@ -6,8 +6,7 @@ core = 7.x
hidden = TRUE
dependencies[] = system_incompatible_core_version_test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/system_incompatible_core_version_test.info b/modules/simpletest/tests/system_incompatible_core_version_test.info
index 338521f6..fd7bccab 100644
--- a/modules/simpletest/tests/system_incompatible_core_version_test.info
+++ b/modules/simpletest/tests/system_incompatible_core_version_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 5.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/system_incompatible_module_version_dependencies_test.info b/modules/simpletest/tests/system_incompatible_module_version_dependencies_test.info
index edf6dd12..59ae15f8 100644
--- a/modules/simpletest/tests/system_incompatible_module_version_dependencies_test.info
+++ b/modules/simpletest/tests/system_incompatible_module_version_dependencies_test.info
@@ -7,8 +7,7 @@ hidden = TRUE
; system_incompatible_module_version_test declares version 1.0
dependencies[] = system_incompatible_module_version_test (>2.0)
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/system_incompatible_module_version_test.info b/modules/simpletest/tests/system_incompatible_module_version_test.info
index 51f3efc5..1ab9bff8 100644
--- a/modules/simpletest/tests/system_incompatible_module_version_test.info
+++ b/modules/simpletest/tests/system_incompatible_module_version_test.info
@@ -5,8 +5,7 @@ version = 1.0
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/system_project_namespace_test.info b/modules/simpletest/tests/system_project_namespace_test.info
index 1507739b..e78bc765 100644
--- a/modules/simpletest/tests/system_project_namespace_test.info
+++ b/modules/simpletest/tests/system_project_namespace_test.info
@@ -6,8 +6,7 @@ core = 7.x
hidden = TRUE
dependencies[] = drupal:filter
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/system_test.info b/modules/simpletest/tests/system_test.info
index 4b6175b5..2eeae174 100644
--- a/modules/simpletest/tests/system_test.info
+++ b/modules/simpletest/tests/system_test.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = system_test.module
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/taxonomy_test.info b/modules/simpletest/tests/taxonomy_test.info
index 3ccf2299..ec710ef6 100644
--- a/modules/simpletest/tests/taxonomy_test.info
+++ b/modules/simpletest/tests/taxonomy_test.info
@@ -6,8 +6,7 @@ core = 7.x
hidden = TRUE
dependencies[] = taxonomy
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/theme_test.info b/modules/simpletest/tests/theme_test.info
index f5cb1eaf..964b3c5a 100644
--- a/modules/simpletest/tests/theme_test.info
+++ b/modules/simpletest/tests/theme_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info b/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info
index ed247b7e..a402bdae 100644
--- a/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info
+++ b/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info
@@ -6,8 +6,7 @@ hidden = TRUE
settings[basetheme_only] = base theme value
settings[subtheme_override] = base theme value
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info b/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info
index dfd8bd8a..9da9a93d 100644
--- a/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info
+++ b/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info
@@ -6,8 +6,7 @@ hidden = TRUE
settings[subtheme_override] = subtheme value
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/themes/test_theme/test_theme.info b/modules/simpletest/tests/themes/test_theme/test_theme.info
index c132c910..b01534a0 100644
--- a/modules/simpletest/tests/themes/test_theme/test_theme.info
+++ b/modules/simpletest/tests/themes/test_theme/test_theme.info
@@ -17,8 +17,7 @@ stylesheets[all][] = system.base.css
settings[theme_test_setting] = default value
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/themes/test_theme/theme-settings.php b/modules/simpletest/tests/themes/test_theme/theme-settings.php
new file mode 100644
index 00000000..cb51d942
--- /dev/null
+++ b/modules/simpletest/tests/themes/test_theme/theme-settings.php
@@ -0,0 +1,32 @@
+ 'checkbox',
+ '#title' => 'Test theme checkbox',
+ '#default_value' => theme_get_setting('test_theme_checkbox'),
+ );
+
+ // Force the form to be cached so we can test that this file is properly
+ // loaded and the custom submit handler is properly called even on a cached
+ // form build.
+ $form_state['cache'] = TRUE;
+ $form['#submit'][] = 'test_theme_form_system_theme_settings_submit';
+}
+
+/**
+ * Form submission handler for the test theme settings form.
+ *
+ * @see test_theme_form_system_theme_settings_alter()
+ */
+function test_theme_form_system_theme_settings_submit($form, &$form_state) {
+ drupal_set_message('The test theme setting was saved.');
+}
diff --git a/modules/simpletest/tests/themes/test_theme_nyan_cat/test_theme_nyan_cat.info b/modules/simpletest/tests/themes/test_theme_nyan_cat/test_theme_nyan_cat.info
index a4f5649e..c090c30b 100644
--- a/modules/simpletest/tests/themes/test_theme_nyan_cat/test_theme_nyan_cat.info
+++ b/modules/simpletest/tests/themes/test_theme_nyan_cat/test_theme_nyan_cat.info
@@ -4,8 +4,7 @@ core = 7.x
hidden = TRUE
engine = nyan_cat
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/update_script_test.info b/modules/simpletest/tests/update_script_test.info
index f3bfc50b..e6d955a3 100644
--- a/modules/simpletest/tests/update_script_test.info
+++ b/modules/simpletest/tests/update_script_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/update_test_1.info b/modules/simpletest/tests/update_test_1.info
index a7431d5d..a8e0e3de 100644
--- a/modules/simpletest/tests/update_test_1.info
+++ b/modules/simpletest/tests/update_test_1.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/update_test_2.info b/modules/simpletest/tests/update_test_2.info
index a7431d5d..a8e0e3de 100644
--- a/modules/simpletest/tests/update_test_2.info
+++ b/modules/simpletest/tests/update_test_2.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/update_test_3.info b/modules/simpletest/tests/update_test_3.info
index a7431d5d..a8e0e3de 100644
--- a/modules/simpletest/tests/update_test_3.info
+++ b/modules/simpletest/tests/update_test_3.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/url_alter_test.info b/modules/simpletest/tests/url_alter_test.info
index 23676af5..ba5129cc 100644
--- a/modules/simpletest/tests/url_alter_test.info
+++ b/modules/simpletest/tests/url_alter_test.info
@@ -5,8 +5,7 @@ package = Testing
version = VERSION
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/simpletest/tests/xmlrpc_test.info b/modules/simpletest/tests/xmlrpc_test.info
index ab787cc3..40723d9f 100644
--- a/modules/simpletest/tests/xmlrpc_test.info
+++ b/modules/simpletest/tests/xmlrpc_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/statistics/statistics.info b/modules/statistics/statistics.info
index 26c1794e..b4b1440a 100644
--- a/modules/statistics/statistics.info
+++ b/modules/statistics/statistics.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = statistics.test
configure = admin/config/system/statistics
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/syslog/syslog.info b/modules/syslog/syslog.info
index 3f8b6ca4..dc67dc5d 100644
--- a/modules/syslog/syslog.info
+++ b/modules/syslog/syslog.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = syslog.test
configure = admin/config/development/logging
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc
index cdcc78fb..b7e6fc9e 100644
--- a/modules/system/system.admin.inc
+++ b/modules/system/system.admin.inc
@@ -572,9 +572,10 @@ function system_theme_settings($form, &$form_state, $key = '') {
// Process the theme and all its base themes.
foreach ($theme_keys as $theme) {
// Include the theme-settings.php file.
- $filename = DRUPAL_ROOT . '/' . str_replace("/$theme.info", '', $themes[$theme]->filename) . '/theme-settings.php';
- if (file_exists($filename)) {
- require_once $filename;
+ $theme_settings_path = drupal_get_path('theme', $theme) . '/theme-settings.php';
+ if (file_exists(DRUPAL_ROOT . '/' . $theme_settings_path)) {
+ require_once DRUPAL_ROOT . '/' . $theme_settings_path;
+ $form_state['build_info']['files'][] = $theme_settings_path;
}
// Call theme-specific settings.
@@ -1812,7 +1813,7 @@ function system_file_system_settings() {
'#title' => t('Private file system path'),
'#default_value' => variable_get('file_private_path', ''),
'#maxlength' => 255,
- '#description' => t('An existing local file system path for storing private files. It should be writable by Drupal and not accessible over the web. See the online handbook for more information about securing private files.', array('@handbook' => 'http://drupal.org/documentation/modules/file')),
+ '#description' => t('An existing local file system path for storing private files. It should be writable by Drupal and not accessible over the web. See the online handbook for more information about securing private files.', array('@handbook' => 'https://www.drupal.org/docs/7/core/modules/file/overview')),
'#after_build' => array('system_check_directory'),
);
@@ -2565,9 +2566,21 @@ function theme_system_admin_index($variables) {
/**
* Returns HTML for the status report.
*
+ * This theme function is dependent on install.inc being loaded, because
+ * that's where the constants are defined.
+ *
* @param $variables
* An associative array containing:
- * - requirements: An array of requirements.
+ * - requirements: An array of requirements/status items. Each requirement
+ * is an associative array containing the following elements:
+ * - title: The name of the requirement.
+ * - value: (optional) The current value (version, time, level, etc).
+ * - description: (optional) The description of the requirement.
+ * - severity: (optional) The requirement's result/severity level, one of:
+ * - REQUIREMENT_INFO: Status information.
+ * - REQUIREMENT_OK: The requirement is satisfied.
+ * - REQUIREMENT_WARNING: The requirement failed with a warning.
+ * - REQUIREMENT_ERROR: The requirement failed with an error.
*
* @ingroup themeable
*/
diff --git a/modules/system/system.api.php b/modules/system/system.api.php
index f1855b96..d5de1024 100644
--- a/modules/system/system.api.php
+++ b/modules/system/system.api.php
@@ -1888,8 +1888,8 @@ function hook_boot() {
*
* This hook is not run on cached pages.
*
- * To add CSS or JS that should be present on all pages, modules should not
- * implement this hook, but declare these files in their .info file.
+ * To add CSS or JS files that should be present on all pages, modules should
+ * not implement this hook, but declare these files in their .info file.
*
* @see hook_boot()
*/
diff --git a/modules/system/system.info b/modules/system/system.info
index da08a99e..65cf8c6c 100644
--- a/modules/system/system.info
+++ b/modules/system/system.info
@@ -12,8 +12,7 @@ files[] = system.test
required = TRUE
configure = admin/config/system
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/system/system.install b/modules/system/system.install
index d5e67435..3bb07d95 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -2870,7 +2870,7 @@ function system_update_7061(&$sandbox) {
if (!db_table_exists('system_update_7061')) {
$table = array(
'description' => t('Stores temporary data for system_update_7061.'),
- 'fields' => array('vid' => array('type' => 'int')),
+ 'fields' => array('vid' => array('type' => 'int', 'not null' => TRUE)),
'primary key' => array('vid'),
);
db_create_table('system_update_7061', $table);
@@ -3285,6 +3285,13 @@ function system_update_7081() {
->execute();
}
+/**
+ * Add 'jquery-extend-3.4.0.js' to the 'jquery' library.
+ */
+function system_update_7082() {
+ // Empty update to force a rebuild of hook_library() and JS aggregates.
+}
+
/**
* @} End of "defgroup updates-7.x-extra".
* The next series of updates should start at 8000.
diff --git a/modules/system/system.mail.inc b/modules/system/system.mail.inc
index 443e5740..9a17f55f 100644
--- a/modules/system/system.mail.inc
+++ b/modules/system/system.mail.inc
@@ -70,7 +70,9 @@ class DefaultMailSystem implements MailSystemInterface {
// hosts. The return value of this method will still indicate whether mail
// was sent successfully.
if (!isset($_SERVER['WINDIR']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') === FALSE) {
- if (isset($message['Return-Path']) && !ini_get('safe_mode')) {
+ // We validate the return path, unless it is equal to the site mail, which
+ // we assume to be safe.
+ if (isset($message['Return-Path']) && !ini_get('safe_mode') && (variable_get('site_mail', ini_get('sendmail_from')) === $message['Return-Path'] || self::_isShellSafe($message['Return-Path']))) {
// On most non-Windows systems, the "-f" option to the sendmail command
// is used to set the Return-Path. There is no space between -f and
// the value of the return path.
@@ -109,6 +111,36 @@ class DefaultMailSystem implements MailSystemInterface {
}
return $mail_result;
}
+
+ /**
+ * Disallows potentially unsafe shell characters.
+ *
+ * Functionally similar to PHPMailer::isShellSafe() which resulted from
+ * CVE-2016-10045. Note that escapeshellarg and escapeshellcmd are inadequate
+ * for this purpose.
+ *
+ * @param string $string
+ * The string to be validated.
+ *
+ * @return bool
+ * True if the string is shell-safe.
+ *
+ * @see https://github.com/PHPMailer/PHPMailer/issues/924
+ * @see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.phpmailer.php#L1430
+ *
+ * @todo Rename to ::isShellSafe() and/or discuss whether this is the correct
+ * location for this helper.
+ */
+ protected static function _isShellSafe($string) {
+ if (escapeshellcmd($string) !== $string || !in_array(escapeshellarg($string), array("'$string'", "\"$string\""))) {
+ return FALSE;
+ }
+ if (preg_match('/[^a-zA-Z0-9@_\-.]/', $string) !== 0) {
+ return FALSE;
+ }
+ return TRUE;
+ }
+
}
/**
diff --git a/modules/system/system.module b/modules/system/system.module
index 53844d87..4ce6b9b9 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -1182,6 +1182,9 @@ function system_library() {
'version' => '1.4.4',
'js' => array(
'misc/jquery.js' => array('group' => JS_LIBRARY, 'weight' => -20),
+ // This includes a security fix, so assign a weight that makes this load
+ // as soon after jquery.js is loaded as possible.
+ 'misc/jquery-extend-3.4.0.js' => array('group' => JS_LIBRARY, 'weight' => -19),
),
);
diff --git a/modules/system/system.tar.inc b/modules/system/system.tar.inc
index 86e4e3de..008d6da5 100644
--- a/modules/system/system.tar.inc
+++ b/modules/system/system.tar.inc
@@ -41,8 +41,8 @@
/**
* Note on Drupal 8 porting.
- * This file origin is Tar.php, release 1.4.0 (stable) with some code
- * from PEAR.php, release 1.9.5 (stable) both at http://pear.php.net.
+ * This file origin is Tar.php, release 1.4.5 (stable) with some code
+ * from PEAR.php, release 1.10.5 (stable) both at http://pear.php.net.
* To simplify future porting from pear of this file, you should not
* do cosmetic or other non significant changes to this file.
* The following changes have been done:
@@ -259,6 +259,19 @@ class Archive_Tar
return false;
}
}
+
+
+ if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) {
+ $this->_fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
+ "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
+ "a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
+ } else {
+ $this->_fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
+ "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
+ "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
+ }
+
+
}
public function __destruct()
@@ -278,7 +291,7 @@ class Archive_Tar
* @param string $ext The extension name
* @return bool Success or not on the dl() call
*/
- function loadExtension($ext)
+ public static function loadExtension($ext)
{
if (extension_loaded($ext)) {
return true;
@@ -287,8 +300,7 @@ class Archive_Tar
// if either returns true dl() will produce a FATAL error, stop that
if (
function_exists('dl') === false ||
- ini_get('enable_dl') != 1 ||
- ini_get('safe_mode') == 1
+ ini_get('enable_dl') != 1
) {
return false;
}
@@ -714,7 +726,7 @@ class Archive_Tar
}
// ----- Get the arguments
- $v_att_list = & func_get_args();
+ $v_att_list = func_get_args();
// ----- Read the attributes
$i = 0;
@@ -1394,10 +1406,22 @@ class Archive_Tar
if ($p_stored_filename == '') {
$p_stored_filename = $p_filename;
}
- $v_reduce_filename = $this->_pathReduction($p_stored_filename);
- if (strlen($v_reduce_filename) > 99) {
- if (!$this->_writeLongHeader($v_reduce_filename)) {
+ $v_reduced_filename = $this->_pathReduction($p_stored_filename);
+
+ if (strlen($v_reduced_filename) > 99) {
+ if (!$this->_writeLongHeader($v_reduced_filename, false)) {
+ return false;
+ }
+ }
+
+ $v_linkname = '';
+ if (@is_link($p_filename)) {
+ $v_linkname = readlink($p_filename);
+ }
+
+ if (strlen($v_linkname) > 99) {
+ if (!$this->_writeLongHeader($v_linkname, true)) {
return false;
}
}
@@ -1406,14 +1430,10 @@ class Archive_Tar
$v_uid = sprintf("%07s", DecOct($v_info[4]));
$v_gid = sprintf("%07s", DecOct($v_info[5]));
$v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
-
$v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
- $v_linkname = '';
-
if (@is_link($p_filename)) {
$v_typeflag = '2';
- $v_linkname = readlink($p_filename);
$v_size = sprintf("%011s", DecOct(0));
} elseif (@is_dir($p_filename)) {
$v_typeflag = "5";
@@ -1425,7 +1445,6 @@ class Archive_Tar
}
$v_magic = 'ustar ';
-
$v_version = ' ';
if (function_exists('posix_getpwuid')) {
@@ -1440,14 +1459,12 @@ class Archive_Tar
}
$v_devmajor = '';
-
$v_devminor = '';
-
$v_prefix = '';
$v_binary_data_first = pack(
"a100a8a8a8a12a12",
- $v_reduce_filename,
+ $v_reduced_filename,
$v_perms,
$v_uid,
$v_gid,
@@ -1487,7 +1504,7 @@ class Archive_Tar
$this->_writeBlock($v_binary_data_first, 148);
// ----- Write the calculated checksum
- $v_checksum = sprintf("%06s ", DecOct($v_checksum));
+ $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum));
$v_binary_data = pack("a8", $v_checksum);
$this->_writeBlock($v_binary_data, 8);
@@ -1519,7 +1536,7 @@ class Archive_Tar
$p_filename = $this->_pathReduction($p_filename);
if (strlen($p_filename) > 99) {
- if (!$this->_writeLongHeader($p_filename)) {
+ if (!$this->_writeLongHeader($p_filename, false)) {
return false;
}
}
@@ -1615,36 +1632,31 @@ class Archive_Tar
* @param string $p_filename
* @return bool
*/
- public function _writeLongHeader($p_filename)
+ public function _writeLongHeader($p_filename, $is_link = false)
{
- $v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
-
- $v_typeflag = 'L';
-
+ $v_uid = sprintf("%07s", 0);
+ $v_gid = sprintf("%07s", 0);
+ $v_perms = sprintf("%07s", 0);
+ $v_size = sprintf("%'011s", DecOct(strlen($p_filename)));
+ $v_mtime = sprintf("%011s", 0);
+ $v_typeflag = ($is_link ? 'K' : 'L');
$v_linkname = '';
-
- $v_magic = '';
-
- $v_version = '';
-
+ $v_magic = 'ustar ';
+ $v_version = ' ';
$v_uname = '';
-
$v_gname = '';
-
$v_devmajor = '';
-
$v_devminor = '';
-
$v_prefix = '';
$v_binary_data_first = pack(
"a100a8a8a8a12a12",
'././@LongLink',
- 0,
- 0,
- 0,
+ $v_perms,
+ $v_uid,
+ $v_gid,
$v_size,
- 0
+ $v_mtime
);
$v_binary_data_last = pack(
"a1a100a6a2a32a32a8a8a155a12",
@@ -1679,7 +1691,7 @@ class Archive_Tar
$this->_writeBlock($v_binary_data_first, 148);
// ----- Write the calculated checksum
- $v_checksum = sprintf("%06s ", DecOct($v_checksum));
+ $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum));
$v_binary_data = pack("a8", $v_checksum);
$this->_writeBlock($v_binary_data, 8);
@@ -1720,28 +1732,13 @@ class Archive_Tar
// ----- Calculate the checksum
$v_checksum = 0;
// ..... First part of the header
- for ($i = 0; $i < 148; $i++) {
- $v_checksum += ord(substr($v_binary_data, $i, 1));
- }
- // ..... Ignore the checksum value and replace it by ' ' (space)
- for ($i = 148; $i < 156; $i++) {
- $v_checksum += ord(' ');
- }
- // ..... Last part of the header
- for ($i = 156; $i < 512; $i++) {
- $v_checksum += ord(substr($v_binary_data, $i, 1));
- }
+ $v_binary_split = str_split($v_binary_data);
+ $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 0, 148)));
+ $v_checksum += array_sum(array_map('ord', array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',)));
+ $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 156, 512)));
- if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) {
- $fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
- "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
- "a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
- } else {
- $fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
- "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
- "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
- }
- $v_data = unpack($fmt, $v_binary_data);
+
+ $v_data = unpack($this->_fmt, $v_binary_data);
if (strlen($v_data["prefix"]) > 0) {
$v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
@@ -1777,7 +1774,7 @@ class Archive_Tar
$v_header['mode'] = OctDec(trim($v_data['mode']));
$v_header['uid'] = OctDec(trim($v_data['uid']));
$v_header['gid'] = OctDec(trim($v_data['gid']));
- $v_header['size'] = OctDec(trim($v_data['size']));
+ $v_header['size'] = $this->_tarRecToSize($v_data['size']);
$v_header['mtime'] = OctDec(trim($v_data['mtime']));
if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
$v_header['size'] = 0;
@@ -1796,6 +1793,40 @@ class Archive_Tar
return true;
}
+ /**
+ * Convert Tar record size to actual size
+ *
+ * @param string $tar_size
+ * @return size of tar record in bytes
+ */
+ private function _tarRecToSize($tar_size)
+ {
+ /*
+ * First byte of size has a special meaning if bit 7 is set.
+ *
+ * Bit 7 indicates base-256 encoding if set.
+ * Bit 6 is the sign bit.
+ * Bits 5:0 are most significant value bits.
+ */
+ $ch = ord($tar_size[0]);
+ if ($ch & 0x80) {
+ // Full 12-bytes record is required.
+ $rec_str = $tar_size . "\x00";
+
+ $size = ($ch & 0x40) ? -1 : 0;
+ $size = ($size << 6) | ($ch & 0x3f);
+
+ for ($num_ch = 1; $num_ch < 12; ++$num_ch) {
+ $size = ($size * 256) + ord($rec_str[$num_ch]);
+ }
+
+ return $size;
+
+ } else {
+ return OctDec(trim($tar_size));
+ }
+ }
+
/**
* Detect and report a malicious file name
*
@@ -1805,10 +1836,13 @@ class Archive_Tar
*/
private function _maliciousFilename($file)
{
- if (strpos($file, '/../') !== false) {
+ if (strpos($file, 'phar://') === 0) {
return true;
}
- if (strpos($file, '../') === 0) {
+ if (strpos($file, DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR) !== false) {
+ return true;
+ }
+ if (strpos($file, '..' . DIRECTORY_SEPARATOR) === 0) {
return true;
}
return false;
@@ -1873,11 +1907,20 @@ class Archive_Tar
continue;
}
- // ----- Look for long filename
- if ($v_header['typeflag'] == 'L') {
- if (!$this->_readLongHeader($v_header)) {
- return null;
- }
+ switch ($v_header['typeflag']) {
+ case 'L': {
+ if (!$this->_readLongHeader($v_header)) {
+ return null;
+ }
+ } break;
+
+ case 'K': {
+ $v_link_header = $v_header;
+ if (!$this->_readLongHeader($v_link_header)) {
+ return null;
+ }
+ $v_header['link'] = $v_link_header['filename'];
+ } break;
}
if ($v_header['filename'] == $p_filename) {
@@ -1978,11 +2021,20 @@ class Archive_Tar
continue;
}
- // ----- Look for long filename
- if ($v_header['typeflag'] == 'L') {
- if (!$this->_readLongHeader($v_header)) {
- return false;
- }
+ switch ($v_header['typeflag']) {
+ case 'L': {
+ if (!$this->_readLongHeader($v_header)) {
+ return null;
+ }
+ } break;
+
+ case 'K': {
+ $v_link_header = $v_header;
+ if (!$this->_readLongHeader($v_link_header)) {
+ return null;
+ }
+ $v_header['link'] = $v_link_header['filename'];
+ } break;
}
// ignore extended / pax headers
diff --git a/modules/system/system.test b/modules/system/system.test
index 9eaf562b..5ae33416 100644
--- a/modules/system/system.test
+++ b/modules/system/system.test
@@ -1944,6 +1944,30 @@ class SystemThemeFunctionalTest extends DrupalWebTestCase {
$this->assertEqual($elements[0]['src'], file_create_url($uploaded_filename));
}
+
+ /**
+ * Test the individual per-theme settings form.
+ */
+ function testPerThemeSettings() {
+ // Enable the test theme and the module that controls it. Clear caches in
+ // between so that the module's hook_system_theme_info() implementation is
+ // correctly registered.
+ module_enable(array('theme_test'));
+ drupal_flush_all_caches();
+ theme_enable(array('test_theme'));
+
+ // Test that the theme-specific settings form can be saved and that the
+ // theme-specific checkbox is checked and unchecked as appropriate.
+ $this->drupalGet('admin/appearance/settings/test_theme');
+ $this->assertNoFieldChecked('edit-test-theme-checkbox', 'The test_theme_checkbox setting is unchecked.');
+ $this->drupalPost(NULL, array('test_theme_checkbox' => TRUE), t('Save configuration'));
+ $this->assertText('The test theme setting was saved.');
+ $this->assertFieldChecked('edit-test-theme-checkbox', 'The test_theme_checkbox setting is checked.');
+ $this->drupalPost(NULL, array('test_theme_checkbox' => FALSE), t('Save configuration'));
+ $this->assertText('The test theme setting was saved.');
+ $this->assertNoFieldChecked('edit-test-theme-checkbox', 'The test_theme_checkbox setting is unchecked.');
+ }
+
/**
* Test the administration theme functionality.
*/
diff --git a/modules/system/tests/cron_queue_test.info b/modules/system/tests/cron_queue_test.info
index 86d9e089..c6614a69 100644
--- a/modules/system/tests/cron_queue_test.info
+++ b/modules/system/tests/cron_queue_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/system/tests/system_cron_test.info b/modules/system/tests/system_cron_test.info
index 662c7c45..8a29644b 100644
--- a/modules/system/tests/system_cron_test.info
+++ b/modules/system/tests/system_cron_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/taxonomy/taxonomy.info b/modules/taxonomy/taxonomy.info
index 1f2fec80..8f00e9fe 100644
--- a/modules/taxonomy/taxonomy.info
+++ b/modules/taxonomy/taxonomy.info
@@ -8,8 +8,7 @@ files[] = taxonomy.module
files[] = taxonomy.test
configure = admin/structure/taxonomy
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index 981649d2..e3ee48e0 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -283,6 +283,8 @@ function taxonomy_menu() {
'title' => 'Taxonomy term',
'title callback' => 'taxonomy_term_title',
'title arguments' => array(2),
+ // The page callback also invokes drupal_set_title() in case
+ // the menu router's title is overridden by a menu link.
'page callback' => 'taxonomy_term_page',
'page arguments' => array(2),
'access arguments' => array('access content'),
@@ -1714,13 +1716,15 @@ function taxonomy_field_formatter_prepare_view($entity_type, $entities, $field,
}
/**
- * Title callback for term pages.
+ * Title callback: Returns the title of the taxonomy term.
*
* @param $term
* A term object.
*
* @return
- * The term name to be used as the page title.
+ * An unsanitized string that is the title of the taxonomy term.
+ *
+ * @see taxonomy_menu()
*/
function taxonomy_term_title($term) {
return $term->name;
diff --git a/modules/toolbar/toolbar.info b/modules/toolbar/toolbar.info
index f0257612..7af42b0b 100644
--- a/modules/toolbar/toolbar.info
+++ b/modules/toolbar/toolbar.info
@@ -4,8 +4,7 @@ core = 7.x
package = Core
version = VERSION
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/tracker/tracker.info b/modules/tracker/tracker.info
index d7cb61b6..7edca1f9 100644
--- a/modules/tracker/tracker.info
+++ b/modules/tracker/tracker.info
@@ -6,8 +6,7 @@ version = VERSION
core = 7.x
files[] = tracker.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/translation/tests/translation_test.info b/modules/translation/tests/translation_test.info
index 9b597a0e..32a2203c 100644
--- a/modules/translation/tests/translation_test.info
+++ b/modules/translation/tests/translation_test.info
@@ -5,8 +5,7 @@ package = Testing
version = VERSION
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/translation/translation.info b/modules/translation/translation.info
index 3e6513f0..8b007da7 100644
--- a/modules/translation/translation.info
+++ b/modules/translation/translation.info
@@ -6,8 +6,7 @@ version = VERSION
core = 7.x
files[] = translation.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/trigger/tests/trigger_test.info b/modules/trigger/tests/trigger_test.info
index 13e0698d..0023f195 100644
--- a/modules/trigger/tests/trigger_test.info
+++ b/modules/trigger/tests/trigger_test.info
@@ -4,8 +4,7 @@ package = Testing
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/trigger/trigger.info b/modules/trigger/trigger.info
index 4c21ba8f..fca1698a 100644
--- a/modules/trigger/trigger.info
+++ b/modules/trigger/trigger.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = trigger.test
configure = admin/structure/trigger
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/update/tests/aaa_update_test.info b/modules/update/tests/aaa_update_test.info
index 96ac28aa..98027695 100644
--- a/modules/update/tests/aaa_update_test.info
+++ b/modules/update/tests/aaa_update_test.info
@@ -4,8 +4,7 @@ package = Testing
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/update/tests/bbb_update_test.info b/modules/update/tests/bbb_update_test.info
index 954fb75b..4014483e 100644
--- a/modules/update/tests/bbb_update_test.info
+++ b/modules/update/tests/bbb_update_test.info
@@ -4,8 +4,7 @@ package = Testing
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/update/tests/ccc_update_test.info b/modules/update/tests/ccc_update_test.info
index f3b7d043..6857ee86 100644
--- a/modules/update/tests/ccc_update_test.info
+++ b/modules/update/tests/ccc_update_test.info
@@ -4,8 +4,7 @@ package = Testing
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/update/tests/themes/update_test_admintheme/update_test_admintheme.info b/modules/update/tests/themes/update_test_admintheme/update_test_admintheme.info
index d21dd9ca..c7e8397e 100644
--- a/modules/update/tests/themes/update_test_admintheme/update_test_admintheme.info
+++ b/modules/update/tests/themes/update_test_admintheme/update_test_admintheme.info
@@ -3,8 +3,7 @@ description = Test theme which is used as admin theme.
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/update/tests/themes/update_test_basetheme/update_test_basetheme.info b/modules/update/tests/themes/update_test_basetheme/update_test_basetheme.info
index 07eb50ff..406c4199 100644
--- a/modules/update/tests/themes/update_test_basetheme/update_test_basetheme.info
+++ b/modules/update/tests/themes/update_test_basetheme/update_test_basetheme.info
@@ -3,8 +3,7 @@ description = Test theme which acts as a base theme for other test subthemes.
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/update/tests/themes/update_test_subtheme/update_test_subtheme.info b/modules/update/tests/themes/update_test_subtheme/update_test_subtheme.info
index 26b480c5..89ab55da 100644
--- a/modules/update/tests/themes/update_test_subtheme/update_test_subtheme.info
+++ b/modules/update/tests/themes/update_test_subtheme/update_test_subtheme.info
@@ -4,8 +4,7 @@ core = 7.x
base theme = update_test_basetheme
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/update/tests/update_test.info b/modules/update/tests/update_test.info
index 7b42bc2e..06aa16be 100644
--- a/modules/update/tests/update_test.info
+++ b/modules/update/tests/update_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/update/update.info b/modules/update/update.info
index 4d9c3691..10256738 100644
--- a/modules/update/update.info
+++ b/modules/update/update.info
@@ -6,8 +6,7 @@ core = 7.x
files[] = update.test
configure = admin/reports/updates/settings
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/user/tests/user_form_test.info b/modules/user/tests/user_form_test.info
index 17ce34a5..abda2bc9 100644
--- a/modules/user/tests/user_form_test.info
+++ b/modules/user/tests/user_form_test.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/user/user.info b/modules/user/user.info
index 83e2b8e3..c51cf271 100644
--- a/modules/user/user.info
+++ b/modules/user/user.info
@@ -9,8 +9,7 @@ required = TRUE
configure = admin/config/people
stylesheets[all][] = user.css
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/modules/user/user.module b/modules/user/user.module
index 12ca2800..2309aa92 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -637,7 +637,7 @@ function user_validate_name($name) {
if (strpos($name, ' ') !== FALSE) {
return t('The username cannot contain multiple spaces in a row.');
}
- if (preg_match('/[^\x{80}-\x{F7} a-z0-9@_.\'-]/i', $name)) {
+ if (preg_match('/[^\x{80}-\x{F7} a-z0-9@+_.\'-]/i', $name)) {
return t('The username contains an illegal character.');
}
if (preg_match('/[\x{80}-\x{A0}' . // Non-printable ISO-8859-1 + NBSP
@@ -689,7 +689,7 @@ function user_validate_picture(&$form, &$form_state) {
$validators = array(
'file_validate_is_image' => array(),
'file_validate_image_resolution' => array(variable_get('user_picture_dimensions', '85x85')),
- 'file_validate_size' => array(variable_get('user_picture_file_size', '30') * 1024),
+ 'file_validate_size' => array((int) variable_get('user_picture_file_size', '30') * 1024),
);
// Save the file as a temporary file.
diff --git a/modules/user/user.test b/modules/user/user.test
index 0875e0ac..fb82c93c 100644
--- a/modules/user/user.test
+++ b/modules/user/user.test
@@ -276,6 +276,7 @@ class UserValidationTestCase extends DrupalWebTestCase {
'foo@example.com' => array('Valid username', 'assertNull'),
'foo@-example.com' => array('Valid username', 'assertNull'), // invalid domains are allowed in usernames
'þòøÇߪř€' => array('Valid username', 'assertNull'),
+ 'foo+bar' => array('Valid username', 'assertNull'), // '+' symbol is allowed
'ᚠᛇᚻ᛫ᛒᛦᚦ' => array('Valid UTF8 username', 'assertNull'), // runes
' foo' => array('Invalid username that starts with a space', 'assertNotNull'),
'foo ' => array('Invalid username that ends with a space', 'assertNotNull'),
@@ -2386,7 +2387,13 @@ class UserUserSearchTestCase extends DrupalWebTestCase {
}
function testUserSearch() {
+ // Verify that a user without 'administer users' permission cannot search
+ // for users by email address. Additionally, ensure that the username has a
+ // plus sign to ensure searching works with that.
$user1 = $this->drupalCreateUser(array('access user profiles', 'search content', 'use advanced search'));
+ $edit['name'] = 'foo+bar';
+ $edit['mail'] = $edit['name'] . '@example.com';
+ user_save($user1, $edit);
$this->drupalLogin($user1);
$keys = $user1->mail;
$edit = array('keys' => $keys);
diff --git a/profiles/minimal/minimal.info b/profiles/minimal/minimal.info
index 1b363abd..81218e44 100644
--- a/profiles/minimal/minimal.info
+++ b/profiles/minimal/minimal.info
@@ -5,8 +5,7 @@ core = 7.x
dependencies[] = block
dependencies[] = dblog
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/profiles/standard/standard.info b/profiles/standard/standard.info
index a3fd9e29..ff5bc686 100644
--- a/profiles/standard/standard.info
+++ b/profiles/standard/standard.info
@@ -24,8 +24,7 @@ dependencies[] = field_ui
dependencies[] = file
dependencies[] = rdf
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/profiles/testing/modules/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info b/profiles/testing/modules/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
index 7a11e329..81374415 100644
--- a/profiles/testing/modules/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
+++ b/profiles/testing/modules/drupal_system_listing_compatible_test/drupal_system_listing_compatible_test.info
@@ -6,8 +6,7 @@ core = 7.x
hidden = TRUE
files[] = drupal_system_listing_compatible_test.test
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/profiles/testing/modules/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info b/profiles/testing/modules/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
index d2bd9479..bf3bcec9 100644
--- a/profiles/testing/modules/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
+++ b/profiles/testing/modules/drupal_system_listing_incompatible_test/drupal_system_listing_incompatible_test.info
@@ -8,8 +8,7 @@ version = VERSION
core = 6.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/profiles/testing/testing.info b/profiles/testing/testing.info
index e9fec6dc..bab064a3 100644
--- a/profiles/testing/testing.info
+++ b/profiles/testing/testing.info
@@ -4,8 +4,7 @@ version = VERSION
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/themes/bartik/bartik.info b/themes/bartik/bartik.info
index 76336801..c334abd5 100644
--- a/themes/bartik/bartik.info
+++ b/themes/bartik/bartik.info
@@ -34,8 +34,7 @@ regions[footer] = Footer
settings[shortcut_module_link] = 0
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/themes/garland/garland.info b/themes/garland/garland.info
index 3a81d19f..576ada67 100644
--- a/themes/garland/garland.info
+++ b/themes/garland/garland.info
@@ -7,8 +7,7 @@ stylesheets[all][] = style.css
stylesheets[print][] = print.css
settings[garland_width] = fluid
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/themes/seven/seven.info b/themes/seven/seven.info
index ce455f5a..f8b80509 100644
--- a/themes/seven/seven.info
+++ b/themes/seven/seven.info
@@ -13,8 +13,7 @@ regions[page_bottom] = Page bottom
regions[sidebar_first] = First sidebar
regions_hidden[] = sidebar_first
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"
diff --git a/themes/stark/stark.info b/themes/stark/stark.info
index 6c1bc204..0721ccb1 100644
--- a/themes/stark/stark.info
+++ b/themes/stark/stark.info
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
stylesheets[all][] = layout.css
-; Information added by Drupal.org packaging script on 2018-03-28
-version = "7.58"
+; Information added by Drupal.org packaging script on 2019-04-17
+version = "7.66"
project = "drupal"
-datestamp = "1522264019"
-
+datestamp = "1555533576"