diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 0929559d..4adf5a43 100755 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,33 @@ +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 ----------------------- @@ -5,7 +35,7 @@ Drupal 7.59, 2018-04-25 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 100755 --- 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 a91c398f..6891f127 100755 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -8,7 +8,7 @@ /** * The current system version. */ -define('VERSION', '7.59'); +define('VERSION', '7.63'); /** * 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(); + } + } } /** @@ -3785,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 f61d1eb0..c5b4ff26 100755 --- a/includes/common.inc +++ b/includes/common.inc @@ -867,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': @@ -878,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: @@ -2311,7 +2317,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..50a3b768 100755 --- a/includes/file.inc +++ b/includes/file.inc @@ -1534,9 +1534,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. 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 100755 --- 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 100755 --- 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 100755 --- 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 100755 --- 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/theme.inc b/includes/theme.inc index 9b606e9f..a926b764 100755 --- 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/tabledrag.js b/misc/tabledrag.js index 7ea88b60..836568f5 100755 --- 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 @@ +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/TYPO3/phar-stream-wrapper/badges/quality-score.png?b=v2)](https://scrutinizer-ci.com/g/TYPO3/phar-stream-wrapper/?branch=v2) +[![Travis CI Build Status](https://travis-ci.org/TYPO3/phar-stream-wrapper.svg?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 18821d29..a5532dc2 100755 --- a/modules/aggregator/aggregator.info +++ b/modules/aggregator/aggregator.info @@ -7,7 +7,7 @@ files[] = aggregator.test configure = admin/config/services/aggregator/settings stylesheets[all][] = aggregator.css -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/aggregator/tests/aggregator_test.info b/modules/aggregator/tests/aggregator_test.info index d0d7f09f..90a8b2f6 100755 --- a/modules/aggregator/tests/aggregator_test.info +++ b/modules/aggregator/tests/aggregator_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/block/block.info b/modules/block/block.info index c65e0232..c9c4171e 100755 --- a/modules/block/block.info +++ b/modules/block/block.info @@ -6,7 +6,7 @@ core = 7.x files[] = block.test configure = admin/structure/block -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/block/tests/block_test.info b/modules/block/tests/block_test.info index 04d117ba..beb9141a 100755 --- a/modules/block/tests/block_test.info +++ b/modules/block/tests/block_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 f1983a4b..89305fc0 100755 --- 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,7 +13,7 @@ regions[footer] = Footer regions[highlighted] = Highlighted regions[help] = Help -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/blog/blog.info b/modules/blog/blog.info index ba12e290..041aadcf 100755 --- a/modules/blog/blog.info +++ b/modules/blog/blog.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x files[] = blog.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/book/book.info b/modules/book/book.info index b2413669..a3c5af7e 100755 --- a/modules/book/book.info +++ b/modules/book/book.info @@ -7,7 +7,7 @@ files[] = book.test configure = admin/content/book/settings stylesheets[all][] = book.css -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/book/book.module b/modules/book/book.module index 7afed9ae..32047f93 100755 --- 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 f3c14ead..2f986d90 100755 --- a/modules/color/color.info +++ b/modules/color/color.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x files[] = color.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/comment/comment.info b/modules/comment/comment.info index d00d4675..7970128c 100755 --- a/modules/comment/comment.info +++ b/modules/comment/comment.info @@ -9,7 +9,7 @@ files[] = comment.test configure = admin/content/comment stylesheets[all][] = comment.css -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/contact/contact.info b/modules/contact/contact.info index 99232a9d..663818e1 100755 --- a/modules/contact/contact.info +++ b/modules/contact/contact.info @@ -6,7 +6,7 @@ core = 7.x files[] = contact.test configure = admin/structure/contact -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/contextual/contextual.info b/modules/contextual/contextual.info index e7f7218f..d23cc9a8 100755 --- a/modules/contextual/contextual.info +++ b/modules/contextual/contextual.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x files[] = contextual.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/dashboard/dashboard.info b/modules/dashboard/dashboard.info index f83f5f87..d3ca7216 100755 --- a/modules/dashboard/dashboard.info +++ b/modules/dashboard/dashboard.info @@ -7,7 +7,7 @@ files[] = dashboard.test dependencies[] = block configure = admin/dashboard/customize -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/dblog/dblog.info b/modules/dblog/dblog.info index 5c908437..26e17371 100755 --- a/modules/dblog/dblog.info +++ b/modules/dblog/dblog.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x files[] = dblog.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/field/field.info b/modules/field/field.info index 93d560ae..2228c059 100755 --- a/modules/field/field.info +++ b/modules/field/field.info @@ -11,7 +11,7 @@ dependencies[] = field_sql_storage required = TRUE stylesheets[all][] = theme/field.css -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 d7e27be4..e43fe820 100755 --- a/modules/field/modules/field_sql_storage/field_sql_storage.info +++ b/modules/field/modules/field_sql_storage/field_sql_storage.info @@ -7,7 +7,7 @@ dependencies[] = field files[] = field_sql_storage.test required = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/field/modules/list/list.info b/modules/field/modules/list/list.info index 1f2b7874..851292eb 100755 --- a/modules/field/modules/list/list.info +++ b/modules/field/modules/list/list.info @@ -7,7 +7,7 @@ dependencies[] = field dependencies[] = options files[] = tests/list.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/field/modules/list/list.install b/modules/field/modules/list/list.install index 2386f048..c10fbc84 100755 --- 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 561bd87e..9a8e792e 100755 --- a/modules/field/modules/list/tests/list_test.info +++ b/modules/field/modules/list/tests/list_test.info @@ -5,7 +5,7 @@ package = Testing version = VERSION hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/field/modules/number/number.info b/modules/field/modules/number/number.info index 6bd079c9..a7853d59 100755 --- a/modules/field/modules/number/number.info +++ b/modules/field/modules/number/number.info @@ -6,7 +6,7 @@ core = 7.x dependencies[] = field files[] = number.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/field/modules/options/options.info b/modules/field/modules/options/options.info index add868ee..77b1359f 100755 --- a/modules/field/modules/options/options.info +++ b/modules/field/modules/options/options.info @@ -6,7 +6,7 @@ core = 7.x dependencies[] = field files[] = options.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/field/modules/text/text.info b/modules/field/modules/text/text.info index 22f2eff0..39881eb1 100755 --- a/modules/field/modules/text/text.info +++ b/modules/field/modules/text/text.info @@ -7,7 +7,7 @@ dependencies[] = field files[] = text.test required = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/field/tests/field_test.info b/modules/field/tests/field_test.info index f37ab1bb..e0f42e98 100755 --- a/modules/field/tests/field_test.info +++ b/modules/field/tests/field_test.info @@ -6,7 +6,7 @@ files[] = field_test.entity.inc version = VERSION hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/field_ui/field_ui.info b/modules/field_ui/field_ui.info index 77ada251..d7564f5a 100755 --- a/modules/field_ui/field_ui.info +++ b/modules/field_ui/field_ui.info @@ -6,7 +6,7 @@ core = 7.x dependencies[] = field files[] = field_ui.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/file/file.info b/modules/file/file.info index 6717d666..f2d0872f 100755 --- a/modules/file/file.info +++ b/modules/file/file.info @@ -6,7 +6,7 @@ core = 7.x dependencies[] = field files[] = tests/file.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/file/tests/file_module_test.info b/modules/file/tests/file_module_test.info index e3417796..a8b4acc9 100755 --- a/modules/file/tests/file_module_test.info +++ b/modules/file/tests/file_module_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/filter/filter.info b/modules/filter/filter.info index c96213e6..f16777f8 100755 --- a/modules/filter/filter.info +++ b/modules/filter/filter.info @@ -7,7 +7,7 @@ files[] = filter.test required = TRUE configure = admin/config/content/formats -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/forum/forum.info b/modules/forum/forum.info index 1d747023..758f35b2 100755 --- a/modules/forum/forum.info +++ b/modules/forum/forum.info @@ -9,7 +9,7 @@ files[] = forum.test configure = admin/structure/forum stylesheets[all][] = forum.css -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/help/help.info b/modules/help/help.info index 86a154f2..46ee825c 100755 --- a/modules/help/help.info +++ b/modules/help/help.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x files[] = help.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/image/image.admin.inc b/modules/image/image.admin.inc index cebe8940..0fbdc0b7 100755 --- 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 d6190e31..7903f2c2 100755 --- a/modules/image/image.info +++ b/modules/image/image.info @@ -7,7 +7,7 @@ dependencies[] = file files[] = image.test configure = admin/config/media/image-styles -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/image/tests/image_module_test.info b/modules/image/tests/image_module_test.info index 5182a091..124b6996 100755 --- a/modules/image/tests/image_module_test.info +++ b/modules/image/tests/image_module_test.info @@ -6,7 +6,7 @@ core = 7.x files[] = image_module_test.module hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/locale/locale.info b/modules/locale/locale.info index 8a7c1da5..fb257d1a 100755 --- a/modules/locale/locale.info +++ b/modules/locale/locale.info @@ -6,7 +6,7 @@ core = 7.x files[] = locale.test configure = admin/config/regional/language -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/locale/locale.test b/modules/locale/locale.test index db87e055..b890b061 100755 --- 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 76a18f7d..5727160f 100755 --- a/modules/locale/tests/locale_test.info +++ b/modules/locale/tests/locale_test.info @@ -5,7 +5,7 @@ package = Testing version = VERSION hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/menu/menu.info b/modules/menu/menu.info index 26163eed..52b127b6 100755 --- a/modules/menu/menu.info +++ b/modules/menu/menu.info @@ -6,7 +6,7 @@ core = 7.x files[] = menu.test configure = admin/structure/menu -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/node/node.info b/modules/node/node.info index 778e11b9..91e55247 100755 --- a/modules/node/node.info +++ b/modules/node/node.info @@ -9,7 +9,7 @@ required = TRUE configure = admin/structure/types stylesheets[all][] = node.css -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/node/tests/node_access_test.info b/modules/node/tests/node_access_test.info index 4f6966cc..b4c70c84 100755 --- a/modules/node/tests/node_access_test.info +++ b/modules/node/tests/node_access_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/node/tests/node_test.info b/modules/node/tests/node_test.info index a36f6c73..162dca0e 100755 --- a/modules/node/tests/node_test.info +++ b/modules/node/tests/node_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/node/tests/node_test_exception.info b/modules/node/tests/node_test_exception.info index a0aac909..80032910 100755 --- a/modules/node/tests/node_test_exception.info +++ b/modules/node/tests/node_test_exception.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/openid/openid.info b/modules/openid/openid.info index 85714e10..c6b93251 100755 --- a/modules/openid/openid.info +++ b/modules/openid/openid.info @@ -5,7 +5,7 @@ package = Core core = 7.x files[] = openid.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/openid/tests/openid_test.info b/modules/openid/tests/openid_test.info index 9cdea741..5f06fc28 100755 --- a/modules/openid/tests/openid_test.info +++ b/modules/openid/tests/openid_test.info @@ -6,7 +6,7 @@ core = 7.x dependencies[] = openid hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/overlay/overlay.info b/modules/overlay/overlay.info index dd760b75..d8f9cf62 100755 --- a/modules/overlay/overlay.info +++ b/modules/overlay/overlay.info @@ -4,7 +4,7 @@ package = Core version = VERSION core = 7.x -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/path/path.info b/modules/path/path.info index 404b8eef..1878b27d 100755 --- a/modules/path/path.info +++ b/modules/path/path.info @@ -6,7 +6,7 @@ core = 7.x files[] = path.test configure = admin/config/search/path -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/path/path.test b/modules/path/path.test index edecff5c..f6131ce6 100755 --- 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 9d211b05..8f64cf09 100755 --- a/modules/php/php.info +++ b/modules/php/php.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x files[] = php.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/poll/poll.info b/modules/poll/poll.info index 2b4f1997..630ba42a 100755 --- a/modules/poll/poll.info +++ b/modules/poll/poll.info @@ -6,7 +6,7 @@ core = 7.x files[] = poll.test stylesheets[all][] = poll.css -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/profile/profile.info b/modules/profile/profile.info index ef52e3ad..7d1e7914 100755 --- a/modules/profile/profile.info +++ b/modules/profile/profile.info @@ -11,7 +11,7 @@ configure = admin/config/people/profile ; See user_system_info_alter(). hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/rdf/rdf.info b/modules/rdf/rdf.info index 59644867..ee1d9c82 100755 --- a/modules/rdf/rdf.info +++ b/modules/rdf/rdf.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x files[] = rdf.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/rdf/tests/rdf_test.info b/modules/rdf/tests/rdf_test.info index df9e8293..063514f7 100755 --- a/modules/rdf/tests/rdf_test.info +++ b/modules/rdf/tests/rdf_test.info @@ -6,7 +6,7 @@ core = 7.x hidden = TRUE dependencies[] = blog -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/search/search.info b/modules/search/search.info index 87336e57..4806cb8f 100755 --- a/modules/search/search.info +++ b/modules/search/search.info @@ -8,7 +8,7 @@ files[] = search.test configure = admin/config/search/settings stylesheets[all][] = search.css -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/search/tests/search_embedded_form.info b/modules/search/tests/search_embedded_form.info index d037a822..a16393ff 100755 --- a/modules/search/tests/search_embedded_form.info +++ b/modules/search/tests/search_embedded_form.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/search/tests/search_extra_type.info b/modules/search/tests/search_extra_type.info index cc8f2bf0..85d76cc1 100755 --- a/modules/search/tests/search_extra_type.info +++ b/modules/search/tests/search_extra_type.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/search/tests/search_node_tags.info b/modules/search/tests/search_node_tags.info index b3964b38..5f0f84d6 100644 --- a/modules/search/tests/search_node_tags.info +++ b/modules/search/tests/search_node_tags.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/shortcut/shortcut.info b/modules/shortcut/shortcut.info index cfe7f4a9..a8bcc268 100755 --- a/modules/shortcut/shortcut.info +++ b/modules/shortcut/shortcut.info @@ -6,7 +6,7 @@ core = 7.x files[] = shortcut.test configure = admin/config/user-interface/shortcut -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 67234c52..7190c676 100755 --- a/modules/simpletest/simpletest.info +++ b/modules/simpletest/simpletest.info @@ -57,7 +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-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/actions_loop_test.info b/modules/simpletest/tests/actions_loop_test.info index cc0cf531..a7939735 100755 --- a/modules/simpletest/tests/actions_loop_test.info +++ b/modules/simpletest/tests/actions_loop_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/ajax_forms_test.info b/modules/simpletest/tests/ajax_forms_test.info index 574b8825..d802f30c 100755 --- a/modules/simpletest/tests/ajax_forms_test.info +++ b/modules/simpletest/tests/ajax_forms_test.info @@ -5,7 +5,7 @@ package = Testing version = VERSION hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/ajax_test.info b/modules/simpletest/tests/ajax_test.info index 8b6d24e6..6ecc1ca0 100755 --- a/modules/simpletest/tests/ajax_test.info +++ b/modules/simpletest/tests/ajax_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/batch_test.info b/modules/simpletest/tests/batch_test.info index b0903307..579ca641 100755 --- a/modules/simpletest/tests/batch_test.info +++ b/modules/simpletest/tests/batch_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/boot_test_1.info b/modules/simpletest/tests/boot_test_1.info index ec2a28a5..b46d19f6 100644 --- a/modules/simpletest/tests/boot_test_1.info +++ b/modules/simpletest/tests/boot_test_1.info @@ -5,7 +5,7 @@ package = Testing version = VERSION hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/boot_test_2.info b/modules/simpletest/tests/boot_test_2.info index b944fef8..c2d6f8ce 100644 --- a/modules/simpletest/tests/boot_test_2.info +++ b/modules/simpletest/tests/boot_test_2.info @@ -5,7 +5,7 @@ package = Testing version = VERSION hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/common_test.info b/modules/simpletest/tests/common_test.info index c4ae99c2..21e565d0 100755 --- a/modules/simpletest/tests/common_test.info +++ b/modules/simpletest/tests/common_test.info @@ -7,7 +7,7 @@ stylesheets[all][] = common_test.css stylesheets[print][] = common_test.print.css hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/common_test_cron_helper.info b/modules/simpletest/tests/common_test_cron_helper.info index dd5487d3..cfe45113 100755 --- a/modules/simpletest/tests/common_test_cron_helper.info +++ b/modules/simpletest/tests/common_test_cron_helper.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/database_test.info b/modules/simpletest/tests/database_test.info index 2707a7b9..a8828237 100755 --- a/modules/simpletest/tests/database_test.info +++ b/modules/simpletest/tests/database_test.info @@ -5,7 +5,7 @@ package = Testing version = VERSION hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 1934fd4a..76640549 100644 --- a/modules/simpletest/tests/drupal_autoload_test/drupal_autoload_test.info +++ b/modules/simpletest/tests/drupal_autoload_test/drupal_autoload_test.info @@ -7,7 +7,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 d4826beb..d1f3545e 100755 --- 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,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 f2a8cff0..061a1437 100755 --- 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,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/entity_cache_test.info b/modules/simpletest/tests/entity_cache_test.info index 82f10dbf..7f52e24b 100755 --- a/modules/simpletest/tests/entity_cache_test.info +++ b/modules/simpletest/tests/entity_cache_test.info @@ -6,7 +6,7 @@ core = 7.x dependencies[] = entity_cache_test_dependency hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/entity_cache_test_dependency.info b/modules/simpletest/tests/entity_cache_test_dependency.info index b69b4a28..5dc9a367 100755 --- a/modules/simpletest/tests/entity_cache_test_dependency.info +++ b/modules/simpletest/tests/entity_cache_test_dependency.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/entity_crud_hook_test.info b/modules/simpletest/tests/entity_crud_hook_test.info index 94f34b6a..edc4d5ca 100755 --- a/modules/simpletest/tests/entity_crud_hook_test.info +++ b/modules/simpletest/tests/entity_crud_hook_test.info @@ -5,7 +5,7 @@ package = Testing version = VERSION hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/entity_query_access_test.info b/modules/simpletest/tests/entity_query_access_test.info index 1c1bbf78..21d13156 100755 --- a/modules/simpletest/tests/entity_query_access_test.info +++ b/modules/simpletest/tests/entity_query_access_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/error_test.info b/modules/simpletest/tests/error_test.info index f5342911..c7fe885e 100755 --- a/modules/simpletest/tests/error_test.info +++ b/modules/simpletest/tests/error_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/file.test b/modules/simpletest/tests/file.test index 89ecac7a..55dd1906 100755 --- a/modules/simpletest/tests/file.test +++ b/modules/simpletest/tests/file.test @@ -2766,4 +2766,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 da253a89..d73960ce 100755 --- a/modules/simpletest/tests/file_test.info +++ b/modules/simpletest/tests/file_test.info @@ -6,7 +6,7 @@ core = 7.x files[] = file_test.module hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/filter_test.info b/modules/simpletest/tests/filter_test.info index c660e012..6433ddd3 100755 --- a/modules/simpletest/tests/filter_test.info +++ b/modules/simpletest/tests/filter_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test index a441ceeb..e52c8c42 100755 --- 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 1c93e0df..a2657115 100755 --- a/modules/simpletest/tests/form_test.info +++ b/modules/simpletest/tests/form_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module index 097e5884..9f071826 100755 --- 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 100755 --- 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 6605d3d4..cc14c8f9 100755 --- a/modules/simpletest/tests/image_test.info +++ b/modules/simpletest/tests/image_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/menu_test.info b/modules/simpletest/tests/menu_test.info index baa7b5a5..c61864d1 100755 --- a/modules/simpletest/tests/menu_test.info +++ b/modules/simpletest/tests/menu_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/module_test.info b/modules/simpletest/tests/module_test.info index c916d5bb..bdf17ea1 100755 --- a/modules/simpletest/tests/module_test.info +++ b/modules/simpletest/tests/module_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/path_test.info b/modules/simpletest/tests/path_test.info index f30412a5..4f177d4d 100755 --- a/modules/simpletest/tests/path_test.info +++ b/modules/simpletest/tests/path_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 deada7b6..3d01fab3 100755 --- a/modules/simpletest/tests/psr_0_test/psr_0_test.info +++ b/modules/simpletest/tests/psr_0_test/psr_0_test.info @@ -5,7 +5,7 @@ core = 7.x hidden = TRUE package = Testing -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 c2dde66f..0619a243 100644 --- a/modules/simpletest/tests/psr_4_test/psr_4_test.info +++ b/modules/simpletest/tests/psr_4_test/psr_4_test.info @@ -5,7 +5,7 @@ core = 7.x hidden = TRUE package = Testing -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/requirements1_test.info b/modules/simpletest/tests/requirements1_test.info index 3fca686f..783326cf 100755 --- a/modules/simpletest/tests/requirements1_test.info +++ b/modules/simpletest/tests/requirements1_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/requirements2_test.info b/modules/simpletest/tests/requirements2_test.info index f09c28dc..8312c3a2 100755 --- a/modules/simpletest/tests/requirements2_test.info +++ b/modules/simpletest/tests/requirements2_test.info @@ -7,7 +7,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/session_test.info b/modules/simpletest/tests/session_test.info index 5057671d..8bf277cf 100755 --- a/modules/simpletest/tests/session_test.info +++ b/modules/simpletest/tests/session_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/system_dependencies_test.info b/modules/simpletest/tests/system_dependencies_test.info index 4ab29b99..2a82092a 100755 --- a/modules/simpletest/tests/system_dependencies_test.info +++ b/modules/simpletest/tests/system_dependencies_test.info @@ -6,7 +6,7 @@ core = 7.x hidden = TRUE dependencies[] = _missing_dependency -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 f0889900..a385a05a 100755 --- a/modules/simpletest/tests/system_incompatible_core_version_dependencies_test.info +++ b/modules/simpletest/tests/system_incompatible_core_version_dependencies_test.info @@ -6,7 +6,7 @@ core = 7.x hidden = TRUE dependencies[] = system_incompatible_core_version_test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/system_incompatible_core_version_test.info b/modules/simpletest/tests/system_incompatible_core_version_test.info index 6e64ea55..e1284747 100755 --- a/modules/simpletest/tests/system_incompatible_core_version_test.info +++ b/modules/simpletest/tests/system_incompatible_core_version_test.info @@ -5,7 +5,7 @@ version = VERSION core = 5.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 f2428bb3..29bd5445 100755 --- a/modules/simpletest/tests/system_incompatible_module_version_dependencies_test.info +++ b/modules/simpletest/tests/system_incompatible_module_version_dependencies_test.info @@ -7,7 +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-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/system_incompatible_module_version_test.info b/modules/simpletest/tests/system_incompatible_module_version_test.info index 148170a8..7383a279 100755 --- a/modules/simpletest/tests/system_incompatible_module_version_test.info +++ b/modules/simpletest/tests/system_incompatible_module_version_test.info @@ -5,7 +5,7 @@ version = 1.0 core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/system_project_namespace_test.info b/modules/simpletest/tests/system_project_namespace_test.info index a6a2340a..9bc711dc 100644 --- a/modules/simpletest/tests/system_project_namespace_test.info +++ b/modules/simpletest/tests/system_project_namespace_test.info @@ -6,7 +6,7 @@ core = 7.x hidden = TRUE dependencies[] = drupal:filter -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/system_test.info b/modules/simpletest/tests/system_test.info index 8f06e417..5e78b89b 100755 --- a/modules/simpletest/tests/system_test.info +++ b/modules/simpletest/tests/system_test.info @@ -6,7 +6,7 @@ core = 7.x files[] = system_test.module hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/taxonomy_test.info b/modules/simpletest/tests/taxonomy_test.info index 14d51a89..59f71422 100755 --- a/modules/simpletest/tests/taxonomy_test.info +++ b/modules/simpletest/tests/taxonomy_test.info @@ -6,7 +6,7 @@ core = 7.x hidden = TRUE dependencies[] = taxonomy -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/theme_test.info b/modules/simpletest/tests/theme_test.info index ee68377d..c810edcb 100755 --- a/modules/simpletest/tests/theme_test.info +++ b/modules/simpletest/tests/theme_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info b/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info index 718830f0..cab073b5 100755 --- a/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info +++ b/modules/simpletest/tests/themes/test_basetheme/test_basetheme.info @@ -6,7 +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-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info b/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info index 17b6fd15..d80c5d0f 100755 --- a/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info +++ b/modules/simpletest/tests/themes/test_subtheme/test_subtheme.info @@ -6,7 +6,7 @@ hidden = TRUE settings[subtheme_override] = subtheme value -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/themes/test_theme/test_theme.info b/modules/simpletest/tests/themes/test_theme/test_theme.info index b57bc12d..a0e0dd68 100755 --- a/modules/simpletest/tests/themes/test_theme/test_theme.info +++ b/modules/simpletest/tests/themes/test_theme/test_theme.info @@ -17,7 +17,7 @@ stylesheets[all][] = system.base.css settings[theme_test_setting] = default value -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 29a66bcd..49513572 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,7 +4,7 @@ core = 7.x hidden = TRUE engine = nyan_cat -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/update_script_test.info b/modules/simpletest/tests/update_script_test.info index a84f716c..ea7b5065 100755 --- a/modules/simpletest/tests/update_script_test.info +++ b/modules/simpletest/tests/update_script_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/update_test_1.info b/modules/simpletest/tests/update_test_1.info index c9d4661a..3e3b36f6 100755 --- a/modules/simpletest/tests/update_test_1.info +++ b/modules/simpletest/tests/update_test_1.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/update_test_2.info b/modules/simpletest/tests/update_test_2.info index c9d4661a..3e3b36f6 100755 --- a/modules/simpletest/tests/update_test_2.info +++ b/modules/simpletest/tests/update_test_2.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/update_test_3.info b/modules/simpletest/tests/update_test_3.info index c9d4661a..3e3b36f6 100755 --- a/modules/simpletest/tests/update_test_3.info +++ b/modules/simpletest/tests/update_test_3.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/url_alter_test.info b/modules/simpletest/tests/url_alter_test.info index 98436f8c..36d1ef40 100755 --- a/modules/simpletest/tests/url_alter_test.info +++ b/modules/simpletest/tests/url_alter_test.info @@ -5,7 +5,7 @@ package = Testing version = VERSION hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/simpletest/tests/xmlrpc_test.info b/modules/simpletest/tests/xmlrpc_test.info index f0a21cc7..2c6d90cc 100755 --- a/modules/simpletest/tests/xmlrpc_test.info +++ b/modules/simpletest/tests/xmlrpc_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/statistics/statistics.info b/modules/statistics/statistics.info index 5d13982d..617ada79 100755 --- a/modules/statistics/statistics.info +++ b/modules/statistics/statistics.info @@ -6,7 +6,7 @@ core = 7.x files[] = statistics.test configure = admin/config/system/statistics -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/syslog/syslog.info b/modules/syslog/syslog.info index 5e1aae57..0814a398 100755 --- a/modules/syslog/syslog.info +++ b/modules/syslog/syslog.info @@ -6,7 +6,7 @@ core = 7.x files[] = syslog.test configure = admin/config/development/logging -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc index cdcc78fb..b7e6fc9e 100755 --- 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 100755 --- 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 7914ef22..dfaf47fe 100755 --- a/modules/system/system.info +++ b/modules/system/system.info @@ -12,7 +12,7 @@ files[] = system.test required = TRUE configure = admin/config/system -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/system/system.mail.inc b/modules/system/system.mail.inc index 443e5740..9a17f55f 100755 --- 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.tar.inc b/modules/system/system.tar.inc index 86e4e3de..008d6da5 100755 --- 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 100755 --- 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 f0548966..d574d64d 100644 --- a/modules/system/tests/cron_queue_test.info +++ b/modules/system/tests/cron_queue_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/system/tests/system_cron_test.info b/modules/system/tests/system_cron_test.info index ea9c7116..d57b6043 100644 --- a/modules/system/tests/system_cron_test.info +++ b/modules/system/tests/system_cron_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/taxonomy/taxonomy.info b/modules/taxonomy/taxonomy.info index d9315956..34e21b91 100755 --- a/modules/taxonomy/taxonomy.info +++ b/modules/taxonomy/taxonomy.info @@ -8,7 +8,7 @@ files[] = taxonomy.module files[] = taxonomy.test configure = admin/structure/taxonomy -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module index 981649d2..e3ee48e0 100755 --- 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 9ec38392..55f8c5cf 100755 --- a/modules/toolbar/toolbar.info +++ b/modules/toolbar/toolbar.info @@ -4,7 +4,7 @@ core = 7.x package = Core version = VERSION -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/tracker/tracker.info b/modules/tracker/tracker.info index 568a4e1a..09869622 100755 --- a/modules/tracker/tracker.info +++ b/modules/tracker/tracker.info @@ -6,7 +6,7 @@ version = VERSION core = 7.x files[] = tracker.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/translation/tests/translation_test.info b/modules/translation/tests/translation_test.info index 5e5620f8..a4e0bd28 100755 --- a/modules/translation/tests/translation_test.info +++ b/modules/translation/tests/translation_test.info @@ -5,7 +5,7 @@ package = Testing version = VERSION hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/translation/translation.info b/modules/translation/translation.info index c6e74772..cab857c4 100755 --- a/modules/translation/translation.info +++ b/modules/translation/translation.info @@ -6,7 +6,7 @@ version = VERSION core = 7.x files[] = translation.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/trigger/tests/trigger_test.info b/modules/trigger/tests/trigger_test.info index 8486e1fd..b49b6e98 100755 --- a/modules/trigger/tests/trigger_test.info +++ b/modules/trigger/tests/trigger_test.info @@ -4,7 +4,7 @@ package = Testing core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/trigger/trigger.info b/modules/trigger/trigger.info index 0a6efeb2..4baee27e 100755 --- a/modules/trigger/trigger.info +++ b/modules/trigger/trigger.info @@ -6,7 +6,7 @@ core = 7.x files[] = trigger.test configure = admin/structure/trigger -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/update/tests/aaa_update_test.info b/modules/update/tests/aaa_update_test.info index 1542255b..e3984130 100755 --- a/modules/update/tests/aaa_update_test.info +++ b/modules/update/tests/aaa_update_test.info @@ -4,7 +4,7 @@ package = Testing core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/update/tests/bbb_update_test.info b/modules/update/tests/bbb_update_test.info index 3efd6637..bf0ea54b 100755 --- a/modules/update/tests/bbb_update_test.info +++ b/modules/update/tests/bbb_update_test.info @@ -4,7 +4,7 @@ package = Testing core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/update/tests/ccc_update_test.info b/modules/update/tests/ccc_update_test.info index 9387a037..a541d0de 100755 --- a/modules/update/tests/ccc_update_test.info +++ b/modules/update/tests/ccc_update_test.info @@ -4,7 +4,7 @@ package = Testing core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 2b1e2b9d..c6507858 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,7 +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-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 1f361db8..4f1bb125 100755 --- 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,7 +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-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 81428d27..b3d8ba9d 100755 --- 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,7 +4,7 @@ core = 7.x base theme = update_test_basetheme hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/update/tests/update_test.info b/modules/update/tests/update_test.info index b989a758..4a0ab86a 100755 --- a/modules/update/tests/update_test.info +++ b/modules/update/tests/update_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/update/update.info b/modules/update/update.info index 2ec8ee7b..0f591346 100755 --- a/modules/update/update.info +++ b/modules/update/update.info @@ -6,7 +6,7 @@ core = 7.x files[] = update.test configure = admin/reports/updates/settings -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/user/tests/user_form_test.info b/modules/user/tests/user_form_test.info index b275c355..0526ab2b 100755 --- a/modules/user/tests/user_form_test.info +++ b/modules/user/tests/user_form_test.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/user/user.info b/modules/user/user.info index 331ad59c..6c132a38 100755 --- a/modules/user/user.info +++ b/modules/user/user.info @@ -9,7 +9,7 @@ required = TRUE configure = admin/config/people stylesheets[all][] = user.css -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/modules/user/user.module b/modules/user/user.module index cfcd10ba..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. @@ -2359,26 +2359,14 @@ function user_external_login_register($name, $module) { * following properties: * - uid: The user ID number. * - login: The UNIX timestamp of the user's last login. - * @param array $options - * (optional) A keyed array of settings. Supported options are: - * - langcode: A language code to be used when generating locale-sensitive - * urls. If langcode is NULL the users preferred language is used. * * @return * A unique URL that provides a one-time log in for the user, from which * they can change their password. */ -function user_pass_reset_url($account, $options = array()) { +function user_pass_reset_url($account) { $timestamp = REQUEST_TIME; - $url_options = array('absolute' => TRUE); - if (isset($options['langcode'])) { - $languages = language_list(); - $url_options['language'] = $languages[$options['langcode']]; - } - else { - $url_options['language'] = user_preferred_language($account); - } - return url("user/reset/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid), $url_options); + return url("user/reset/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid), array('absolute' => TRUE)); } /** @@ -2390,10 +2378,6 @@ function user_pass_reset_url($account, $options = array()) { * - uid: The user ID number. * - pass: The hashed user password string. * - login: The UNIX timestamp of the user's last login. - * @param array $options - * (optional) A keyed array of settings. Supported options are: - * - langcode: A language code to be used when generating locale-sensitive - * urls. If langcode is NULL the users preferred language is used. * * @return * A unique URL that may be used to confirm the cancellation of the user @@ -2402,17 +2386,9 @@ function user_pass_reset_url($account, $options = array()) { * @see user_mail_tokens() * @see user_cancel_confirm() */ -function user_cancel_url($account, $options = array()) { +function user_cancel_url($account) { $timestamp = REQUEST_TIME; - $url_options = array('absolute' => TRUE); - if (isset($options['langcode'])) { - $languages = language_list(); - $url_options['language'] = $languages[$options['langcode']]; - } - else { - $url_options['language'] = user_preferred_language($account); - } - return url("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid), $url_options); + return url("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login, $account->uid), array('absolute' => TRUE)); } /** @@ -2902,7 +2878,7 @@ Your account on [site:name] has been canceled. if ($replace) { // We do not sanitize the token replacement, since the output of this // replacement is intended for an e-mail message, not a web browser. - return token_replace($text, $variables, array('language' => $language, 'langcode' => $langcode, 'callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE)); + return token_replace($text, $variables, array('language' => $language, 'callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE)); } return $text; @@ -2929,8 +2905,8 @@ Your account on [site:name] has been canceled. */ function user_mail_tokens(&$replacements, $data, $options) { if (isset($data['user'])) { - $replacements['[user:one-time-login-url]'] = user_pass_reset_url($data['user'], $options); - $replacements['[user:cancel-url]'] = user_cancel_url($data['user'], $options); + $replacements['[user:one-time-login-url]'] = user_pass_reset_url($data['user']); + $replacements['[user:cancel-url]'] = user_cancel_url($data['user']); } } diff --git a/modules/user/user.test b/modules/user/user.test index f26cf260..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'), @@ -2320,26 +2321,6 @@ class UserTokenReplaceTestCase extends DrupalWebTestCase { ); } - public function setUp() { - parent::setUp('locale'); - - $account = $this->drupalCreateUser(array('access administration pages', 'administer languages')); - $this->drupalLogin($account); - - // Add language. - $edit = array('langcode' => 'de'); - $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language')); - - // Enable URL language detection and selection. - $edit = array('language[enabled][locale-url]' => 1); - $this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings')); - - // Reset static caching. - drupal_static_reset('language_list'); - drupal_static_reset('locale_url_outbound_alter'); - drupal_static_reset('locale_language_url_rewrite_url'); - } - /** * Creates a user, then tests the tokens generated from it. */ @@ -2390,39 +2371,6 @@ class UserTokenReplaceTestCase extends DrupalWebTestCase { $output = token_replace($input, array('user' => $account), array('language' => $language, 'sanitize' => FALSE)); $this->assertEqual($output, $expected, format_string('Unsanitized user token %token replaced.', array('%token' => $input))); } - - $languages = language_list(); - - // Generate login and cancel link. - $tests = array(); - $tests['[user:one-time-login-url]'] = user_pass_reset_url($account); - $tests['[user:cancel-url]'] = user_cancel_url($account); - - // Generate tokens with interface language. - $link = url('user', array('absolute' => TRUE)); - foreach ($tests as $input => $expected) { - $output = token_replace($input, array('user' => $account), array('langcode' => $language->language, 'callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE)); - $this->assertTrue(strpos($output, $link) === 0, 'Generated URL is in interface language.'); - } - - // Generate tokens with the user's preferred language. - $edit['language'] = 'de'; - $account = user_save($account, $edit); - $link = url('user', array('language' => $languages[$account->language], 'absolute' => TRUE)); - foreach ($tests as $input => $expected) { - $output = token_replace($input, array('user' => $account), array('callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE)); - $this->assertTrue(strpos($output, $link) === 0, "Generated URL is in the user's preferred language."); - } - - // Generate tokens with one specific language. - $link = url('user', array('language' => $languages['de'], 'absolute' => TRUE)); - foreach ($tests as $input => $expected) { - foreach (array($user1, $user2) as $account) { - $output = token_replace($input, array('user' => $account), array('langcode' => 'de', 'callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE)); - $this->assertTrue(strpos($output, $link) === 0, "Generated URL in in the requested language."); - } - } - } } @@ -2439,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 933068c8..a4d469df 100755 --- a/profiles/minimal/minimal.info +++ b/profiles/minimal/minimal.info @@ -5,7 +5,7 @@ core = 7.x dependencies[] = block dependencies[] = dblog -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/profiles/standard/standard.info b/profiles/standard/standard.info index b56253df..9c30220f 100755 --- a/profiles/standard/standard.info +++ b/profiles/standard/standard.info @@ -24,7 +24,7 @@ dependencies[] = field_ui dependencies[] = file dependencies[] = rdf -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 995e2834..2adcf3dc 100755 --- 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,7 +6,7 @@ core = 7.x hidden = TRUE files[] = drupal_system_listing_compatible_test.test -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" 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 45d36598..8ae9c3fc 100755 --- 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,7 +8,7 @@ version = VERSION core = 6.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/profiles/testing/testing.info b/profiles/testing/testing.info index 0b2a332c..a8a2c5c9 100755 --- a/profiles/testing/testing.info +++ b/profiles/testing/testing.info @@ -4,7 +4,7 @@ version = VERSION core = 7.x hidden = TRUE -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/themes/bartik/bartik.info b/themes/bartik/bartik.info index a49c03e6..51eb8125 100755 --- a/themes/bartik/bartik.info +++ b/themes/bartik/bartik.info @@ -34,7 +34,7 @@ regions[footer] = Footer settings[shortcut_module_link] = 0 -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/themes/garland/garland.info b/themes/garland/garland.info index b211949d..450ff95c 100755 --- a/themes/garland/garland.info +++ b/themes/garland/garland.info @@ -7,7 +7,7 @@ stylesheets[all][] = style.css stylesheets[print][] = print.css settings[garland_width] = fluid -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/themes/seven/seven.info b/themes/seven/seven.info index 8b1eb067..5f53557b 100755 --- a/themes/seven/seven.info +++ b/themes/seven/seven.info @@ -13,7 +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-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965" diff --git a/themes/stark/stark.info b/themes/stark/stark.info index e5c5beaa..a404f692 100755 --- a/themes/stark/stark.info +++ b/themes/stark/stark.info @@ -5,7 +5,7 @@ version = VERSION core = 7.x stylesheets[all][] = layout.css -; Information added by Drupal.org packaging script on 2018-04-25 -version = "7.59" +; Information added by Drupal.org packaging script on 2019-01-16 +version = "7.63" project = "drupal" -datestamp = "1524673284" +datestamp = "1547681965"