security update core+modules
This commit is contained in:
@@ -281,7 +281,7 @@ function drupal_get_rdf_namespaces() {
|
||||
/**
|
||||
* Adds output to the HEAD tag of the HTML page.
|
||||
*
|
||||
* This function can be called as long the headers aren't sent. Pass no
|
||||
* This function can be called as long as the headers aren't sent. Pass no
|
||||
* arguments (or NULL for both) to retrieve the currently stored elements.
|
||||
*
|
||||
* @param $data
|
||||
@@ -458,7 +458,7 @@ function drupal_get_query_array($query) {
|
||||
$result = array();
|
||||
if (!empty($query)) {
|
||||
foreach (explode('&', $query) as $param) {
|
||||
$param = explode('=', $param);
|
||||
$param = explode('=', $param, 2);
|
||||
$result[$param[0]] = isset($param[1]) ? rawurldecode($param[1]) : '';
|
||||
}
|
||||
}
|
||||
@@ -544,37 +544,32 @@ function drupal_get_destination() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a system URL string into an associative array suitable for url().
|
||||
* Parses a URL string into its path, query, and fragment components.
|
||||
*
|
||||
* This function should only be used for URLs that have been generated by the
|
||||
* system, such as via url(). It should not be used for URLs that come from
|
||||
* external sources, or URLs that link to external resources.
|
||||
* This function splits both internal paths like @code node?b=c#d @endcode and
|
||||
* external URLs like @code https://example.com/a?b=c#d @endcode into their
|
||||
* component parts. See
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-3 RFC 3986 @endlink for an
|
||||
* explanation of what the component parts are.
|
||||
*
|
||||
* The returned array contains a 'path' that may be passed separately to url().
|
||||
* For example:
|
||||
* @code
|
||||
* $options = drupal_parse_url($_GET['destination']);
|
||||
* $my_url = url($options['path'], $options);
|
||||
* $my_link = l('Example link', $options['path'], $options);
|
||||
* @endcode
|
||||
* Note that, unlike the RFC, when passed an external URL, this function
|
||||
* groups the scheme, authority, and path together into the path component.
|
||||
*
|
||||
* This is required, because url() does not support relative URLs containing a
|
||||
* query string or fragment in its $path argument. Instead, any query string
|
||||
* needs to be parsed into an associative query parameter array in
|
||||
* $options['query'] and the fragment into $options['fragment'].
|
||||
* @param string $url
|
||||
* The internal path or external URL string to parse.
|
||||
*
|
||||
* @param $url
|
||||
* The URL string to parse, f.e. $_GET['destination'].
|
||||
* @return array
|
||||
* An associative array containing:
|
||||
* - path: The path component of $url. If $url is an external URL, this
|
||||
* includes the scheme, authority, and path.
|
||||
* - query: An array of query parameters from $url, if they exist.
|
||||
* - fragment: The fragment component from $url, if it exists.
|
||||
*
|
||||
* @return
|
||||
* An associative array containing the keys:
|
||||
* - 'path': The path of the URL. If the given $url is external, this includes
|
||||
* the scheme and host.
|
||||
* - 'query': An array of query parameters of $url, if existent.
|
||||
* - 'fragment': The fragment of $url, if existent.
|
||||
*
|
||||
* @see url()
|
||||
* @see drupal_goto()
|
||||
* @see l()
|
||||
* @see url()
|
||||
* @see http://tools.ietf.org/html/rfc3986
|
||||
*
|
||||
* @ingroup php_wrappers
|
||||
*/
|
||||
function drupal_parse_url($url) {
|
||||
@@ -641,7 +636,7 @@ function drupal_encode_path($path) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the user to a different Drupal page.
|
||||
* Sends the user to a different page.
|
||||
*
|
||||
* This issues an on-site HTTP redirect. The function makes sure the redirected
|
||||
* URL is formatted correctly.
|
||||
@@ -785,6 +780,13 @@ function drupal_access_denied() {
|
||||
* - data: A string containing the response body that was received.
|
||||
*/
|
||||
function drupal_http_request($url, array $options = array()) {
|
||||
// Allow an alternate HTTP client library to replace Drupal's default
|
||||
// implementation.
|
||||
$override_function = variable_get('drupal_http_request_function', FALSE);
|
||||
if (!empty($override_function) && function_exists($override_function)) {
|
||||
return $override_function($url, $options);
|
||||
}
|
||||
|
||||
$result = new stdClass();
|
||||
|
||||
// Parse the URL and make sure we can handle the schema.
|
||||
@@ -922,7 +924,7 @@ function drupal_http_request($url, array $options = array()) {
|
||||
|
||||
// If the server URL has a user then attempt to use basic authentication.
|
||||
if (isset($uri['user'])) {
|
||||
$options['headers']['Authorization'] = 'Basic ' . base64_encode($uri['user'] . (isset($uri['pass']) ? ':' . $uri['pass'] : ''));
|
||||
$options['headers']['Authorization'] = 'Basic ' . base64_encode($uri['user'] . (isset($uri['pass']) ? ':' . $uri['pass'] : ':'));
|
||||
}
|
||||
|
||||
// If the database prefix is being used by SimpleTest to run the tests in a copied
|
||||
@@ -983,9 +985,10 @@ function drupal_http_request($url, array $options = array()) {
|
||||
$response = preg_split("/\r\n|\n|\r/", $response);
|
||||
|
||||
// Parse the response status line.
|
||||
list($protocol, $code, $status_message) = explode(' ', trim(array_shift($response)), 3);
|
||||
$result->protocol = $protocol;
|
||||
$result->status_message = $status_message;
|
||||
$response_status_array = _drupal_parse_response_status(trim(array_shift($response)));
|
||||
$result->protocol = $response_status_array['http_version'];
|
||||
$result->status_message = $response_status_array['reason_phrase'];
|
||||
$code = $response_status_array['response_code'];
|
||||
|
||||
$result->headers = array();
|
||||
|
||||
@@ -1076,12 +1079,43 @@ function drupal_http_request($url, array $options = array()) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$result->error = $status_message;
|
||||
$result->error = $result->status_message;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits an HTTP response status line into components.
|
||||
*
|
||||
* See the @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html status line definition @endlink
|
||||
* in RFC 2616.
|
||||
*
|
||||
* @param string $respone
|
||||
* The response status line, for example 'HTTP/1.1 500 Internal Server Error'.
|
||||
*
|
||||
* @return array
|
||||
* Keyed array containing the component parts. If the response is malformed,
|
||||
* all possible parts will be extracted. 'reason_phrase' could be empty.
|
||||
* Possible keys:
|
||||
* - 'http_version'
|
||||
* - 'response_code'
|
||||
* - 'reason_phrase'
|
||||
*/
|
||||
function _drupal_parse_response_status($response) {
|
||||
$response_array = explode(' ', trim($response), 3);
|
||||
// Set up empty values.
|
||||
$result = array(
|
||||
'reason_phrase' => '',
|
||||
);
|
||||
$result['http_version'] = $response_array[0];
|
||||
$result['response_code'] = $response_array[1];
|
||||
if (isset($response_array[2])) {
|
||||
$result['reason_phrase'] = $response_array[2];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for determining hosts excluded from needing a proxy.
|
||||
*
|
||||
@@ -1127,7 +1161,7 @@ function _fix_gpc_magic(&$item) {
|
||||
* @param $key
|
||||
* The key for the item within $_FILES.
|
||||
*
|
||||
* @see http://php.net/manual/en/features.file-upload.php#42280
|
||||
* @see http://php.net/manual/features.file-upload.php#42280
|
||||
*/
|
||||
function _fix_gpc_magic_files(&$item, $key) {
|
||||
if ($key != 'tmp_name') {
|
||||
@@ -1167,7 +1201,8 @@ function fix_gpc_magic() {
|
||||
/**
|
||||
* Verifies the syntax of the given e-mail address.
|
||||
*
|
||||
* See @link http://tools.ietf.org/html/rfc5321 RFC 5321 @endlink for details.
|
||||
* This uses the
|
||||
* @link http://php.net/manual/filter.filters.validate.php PHP e-mail validation filter. @endlink
|
||||
*
|
||||
* @param $mail
|
||||
* A string containing an e-mail address.
|
||||
@@ -1418,7 +1453,6 @@ function filter_xss_admin($string) {
|
||||
* valid UTF-8.
|
||||
*
|
||||
* @see drupal_validate_utf8()
|
||||
* @ingroup sanitization
|
||||
*/
|
||||
function filter_xss($string, $allowed_tags = array('a', 'em', 'strong', 'cite', 'blockquote', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd')) {
|
||||
// Only operate on valid UTF-8 strings. This is necessary to prevent cross
|
||||
@@ -1942,7 +1976,7 @@ function format_interval($interval, $granularity = 2, $langcode = NULL) {
|
||||
* get interpreted as date format characters.
|
||||
* @param $timezone
|
||||
* (optional) Time zone identifier, as described at
|
||||
* http://php.net/manual/en/timezones.php Defaults to the time zone used to
|
||||
* http://php.net/manual/timezones.php Defaults to the time zone used to
|
||||
* display the page.
|
||||
* @param $langcode
|
||||
* (optional) Language code to translate to. Defaults to the language used to
|
||||
@@ -2078,6 +2112,9 @@ function _format_date_callback(array $matches = NULL, $new_langcode = NULL) {
|
||||
/**
|
||||
* Format a username.
|
||||
*
|
||||
* This is also the label callback implementation of
|
||||
* callback_entity_info_label() for user_entity_info().
|
||||
*
|
||||
* By default, the passed-in object's 'name' property is used if it exists, or
|
||||
* else, the site-defined value for the 'anonymous' variable. However, a module
|
||||
* may override this by implementing hook_username_alter(&$name, $account).
|
||||
@@ -2177,14 +2214,20 @@ function url($path = NULL, array $options = array()) {
|
||||
'prefix' => ''
|
||||
);
|
||||
|
||||
// A duplicate of the code from url_is_external() to avoid needing another
|
||||
// function call, since performance inside url() is critical.
|
||||
if (!isset($options['external'])) {
|
||||
// Return an external link if $path contains an allowed absolute URL. Only
|
||||
// call the slow drupal_strip_dangerous_protocols() if $path contains a ':'
|
||||
// before any / ? or #. Note: we could use url_is_external($path) here, but
|
||||
// that would require another function call, and performance inside url() is
|
||||
// critical.
|
||||
// Return an external link if $path contains an allowed absolute URL. Avoid
|
||||
// calling drupal_strip_dangerous_protocols() if there is any slash (/),
|
||||
// hash (#) or question_mark (?) before the colon (:) occurrence - if any -
|
||||
// as this would clearly mean it is not a URL. If the path starts with 2
|
||||
// slashes then it is always considered an external URL without an explicit
|
||||
// protocol part.
|
||||
$colonpos = strpos($path, ':');
|
||||
$options['external'] = ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && drupal_strip_dangerous_protocols($path) == $path);
|
||||
$options['external'] = (strpos($path, '//') === 0)
|
||||
|| ($colonpos !== FALSE
|
||||
&& !preg_match('![/?#]!', substr($path, 0, $colonpos))
|
||||
&& drupal_strip_dangerous_protocols($path) == $path);
|
||||
}
|
||||
|
||||
// Preserve the original path before altering or aliasing.
|
||||
@@ -2222,6 +2265,11 @@ function url($path = NULL, array $options = array()) {
|
||||
return $path . $options['fragment'];
|
||||
}
|
||||
|
||||
// Strip leading slashes from internal paths to prevent them becoming external
|
||||
// URLs without protocol. /example.com should not be turned into
|
||||
// //example.com.
|
||||
$path = ltrim($path, '/');
|
||||
|
||||
global $base_url, $base_secure_url, $base_insecure_url;
|
||||
|
||||
// The base_url might be rewritten from the language rewrite in domain mode.
|
||||
@@ -2299,10 +2347,15 @@ function url($path = NULL, array $options = array()) {
|
||||
*/
|
||||
function url_is_external($path) {
|
||||
$colonpos = strpos($path, ':');
|
||||
// Avoid calling drupal_strip_dangerous_protocols() if there is any
|
||||
// slash (/), hash (#) or question_mark (?) before the colon (:)
|
||||
// occurrence - if any - as this would clearly mean it is not a URL.
|
||||
return $colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && drupal_strip_dangerous_protocols($path) == $path;
|
||||
// Avoid calling drupal_strip_dangerous_protocols() if there is any slash (/),
|
||||
// hash (#) or question_mark (?) before the colon (:) occurrence - if any - as
|
||||
// this would clearly mean it is not a URL. If the path starts with 2 slashes
|
||||
// then it is always considered an external URL without an explicit protocol
|
||||
// part.
|
||||
return (strpos($path, '//') === 0)
|
||||
|| ($colonpos !== FALSE
|
||||
&& !preg_match('![/?#]!', substr($path, 0, $colonpos))
|
||||
&& drupal_strip_dangerous_protocols($path) == $path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2379,6 +2432,14 @@ function drupal_attributes(array $attributes = array()) {
|
||||
* internal links output by modules should be generated by this function if
|
||||
* possible.
|
||||
*
|
||||
* However, for links enclosed in translatable text you should use t() and
|
||||
* embed the HTML anchor tag directly in the translated string. For example:
|
||||
* @code
|
||||
* t('Visit the <a href="@url">settings</a> page', array('@url' => url('admin')));
|
||||
* @endcode
|
||||
* This keeps the context of the link title ('settings' in the example) for
|
||||
* translators.
|
||||
*
|
||||
* @param string $text
|
||||
* The translated link text for the anchor tag.
|
||||
* @param string $path
|
||||
@@ -2591,7 +2652,10 @@ function drupal_deliver_html_page($page_callback_result) {
|
||||
|
||||
// Keep old path for reference, and to allow forms to redirect to it.
|
||||
if (!isset($_GET['destination'])) {
|
||||
$_GET['destination'] = $_GET['q'];
|
||||
// Make sure that the current path is not interpreted as external URL.
|
||||
if (!url_is_external($_GET['q'])) {
|
||||
$_GET['destination'] = $_GET['q'];
|
||||
}
|
||||
}
|
||||
|
||||
$path = drupal_get_normal_path(variable_get('site_404', ''));
|
||||
@@ -2620,7 +2684,10 @@ function drupal_deliver_html_page($page_callback_result) {
|
||||
|
||||
// Keep old path for reference, and to allow forms to redirect to it.
|
||||
if (!isset($_GET['destination'])) {
|
||||
$_GET['destination'] = $_GET['q'];
|
||||
// Make sure that the current path is not interpreted as external URL.
|
||||
if (!url_is_external($_GET['q'])) {
|
||||
$_GET['destination'] = $_GET['q'];
|
||||
}
|
||||
}
|
||||
|
||||
$path = drupal_get_normal_path(variable_get('site_403', ''));
|
||||
@@ -2779,7 +2846,7 @@ function drupal_set_time_limit($time_limit) {
|
||||
* The name of the item for which the path is requested.
|
||||
*
|
||||
* @return
|
||||
* The path to the requested item.
|
||||
* The path to the requested item or an empty string if the item is not found.
|
||||
*/
|
||||
function drupal_get_path($type, $name) {
|
||||
return dirname(drupal_get_filename($type, $name));
|
||||
@@ -3429,7 +3496,11 @@ function drupal_pre_render_styles($elements) {
|
||||
$import_batch = array_slice($import, 0, 31);
|
||||
$import = array_slice($import, 31);
|
||||
$element = $style_element_defaults;
|
||||
$element['#value'] = implode("\n", $import_batch);
|
||||
// This simplifies the JavaScript regex, allowing each line
|
||||
// (separated by \n) to be treated as a completely different string.
|
||||
// This means that we can use ^ and $ on one line at a time, and not
|
||||
// worry about style tags since they'll never match the regex.
|
||||
$element['#value'] = "\n" . implode("\n", $import_batch) . "\n";
|
||||
$element['#attributes']['media'] = $group['media'];
|
||||
$element['#browsers'] = $group['browsers'];
|
||||
$elements[] = $element;
|
||||
@@ -3654,17 +3725,23 @@ function drupal_load_stylesheet($file, $optimize = NULL, $reset_basepath = TRUE)
|
||||
if ($basepath && !file_uri_scheme($file)) {
|
||||
$file = $basepath . '/' . $file;
|
||||
}
|
||||
// Store the parent base path to restore it later.
|
||||
$parent_base_path = $basepath;
|
||||
// Set the current base path to process possible child imports.
|
||||
$basepath = dirname($file);
|
||||
|
||||
// Load the CSS stylesheet. We suppress errors because themes may specify
|
||||
// stylesheets in their .info file that don't exist in the theme's path,
|
||||
// but are merely there to disable certain module CSS files.
|
||||
$content = '';
|
||||
if ($contents = @file_get_contents($file)) {
|
||||
// Return the processed stylesheet.
|
||||
return drupal_load_stylesheet_content($contents, $_optimize);
|
||||
$content = drupal_load_stylesheet_content($contents, $_optimize);
|
||||
}
|
||||
|
||||
return '';
|
||||
// Restore the parent base path as the file and its childen are processed.
|
||||
$basepath = $parent_base_path;
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3681,7 +3758,7 @@ function drupal_load_stylesheet($file, $optimize = NULL, $reset_basepath = TRUE)
|
||||
*/
|
||||
function drupal_load_stylesheet_content($contents, $optimize = FALSE) {
|
||||
// Remove multiple charset declarations for standards compliance (and fixing Safari problems).
|
||||
$contents = preg_replace('/^@charset\s+[\'"](\S*)\b[\'"];/i', '', $contents);
|
||||
$contents = preg_replace('/^@charset\s+[\'"](\S*?)\b[\'"];/i', '', $contents);
|
||||
|
||||
if ($optimize) {
|
||||
// Perform some safe CSS optimizations.
|
||||
@@ -3700,7 +3777,7 @@ function drupal_load_stylesheet_content($contents, $optimize = FALSE) {
|
||||
// Remove certain whitespace.
|
||||
// There are different conditions for removing leading and trailing
|
||||
// whitespace.
|
||||
// @see http://php.net/manual/en/regexp.reference.subpatterns.php
|
||||
// @see http://php.net/manual/regexp.reference.subpatterns.php
|
||||
$contents = preg_replace('<
|
||||
# Strip leading and trailing whitespace.
|
||||
\s*([@{};,])\s*
|
||||
@@ -3749,7 +3826,7 @@ function _drupal_load_stylesheet($matches) {
|
||||
// Alter all internal url() paths. Leave external paths alone. We don't need
|
||||
// to normalize absolute paths here (i.e. remove folder/... segments) because
|
||||
// that will be done later.
|
||||
return preg_replace('/url\(\s*([\'"]?)(?![a-z]+:|\/+)/i', 'url(\1'. $directory, $file);
|
||||
return preg_replace('/url\(\s*([\'"]?)(?![a-z]+:|\/+)([^\'")]+)([\'"]?)\s*\)/i', 'url(\1' . $directory . '\2\3)', $file);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3814,7 +3891,14 @@ function drupal_clean_css_identifier($identifier, $filter = array(' ' => '-', '_
|
||||
* The cleaned class name.
|
||||
*/
|
||||
function drupal_html_class($class) {
|
||||
return drupal_clean_css_identifier(drupal_strtolower($class));
|
||||
// The output of this function will never change, so this uses a normal
|
||||
// static instead of drupal_static().
|
||||
static $classes = array();
|
||||
|
||||
if (!isset($classes[$class])) {
|
||||
$classes[$class] = drupal_clean_css_identifier(drupal_strtolower($class));
|
||||
}
|
||||
return $classes[$class];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3869,7 +3953,16 @@ function drupal_html_id($id) {
|
||||
// requested id. $_POST['ajax_html_ids'] contains the ids as they were
|
||||
// returned by this function, potentially with the appended counter, so
|
||||
// we parse that to reconstruct the $seen_ids array.
|
||||
foreach ($_POST['ajax_html_ids'] as $seen_id) {
|
||||
if (isset($_POST['ajax_html_ids'][0]) && strpos($_POST['ajax_html_ids'][0], ',') === FALSE) {
|
||||
$ajax_html_ids = $_POST['ajax_html_ids'];
|
||||
}
|
||||
else {
|
||||
// jquery.form.js may send the server a comma-separated string as the
|
||||
// first element of an array (see http://drupal.org/node/1575060), so
|
||||
// we need to convert it to an array in that case.
|
||||
$ajax_html_ids = explode(',', $_POST['ajax_html_ids'][0]);
|
||||
}
|
||||
foreach ($ajax_html_ids as $seen_id) {
|
||||
// We rely on '--' being used solely for separating a base id from the
|
||||
// counter, which this function ensures when returning an id.
|
||||
$parts = explode('--', $seen_id, 2);
|
||||
@@ -4069,7 +4162,14 @@ function drupal_region_class($region) {
|
||||
* else being the same, JavaScript added by a call to drupal_add_js() that
|
||||
* happened later in the page request gets added to the page after one for
|
||||
* which drupal_add_js() happened earlier in the page request.
|
||||
* - defer: If set to TRUE, the defer attribute is set on the <script>
|
||||
* - requires_jquery: Set this to FALSE if the JavaScript you are adding does
|
||||
* not have a dependency on jQuery. Defaults to TRUE, except for JavaScript
|
||||
* settings where it defaults to FALSE. This is used on sites that have the
|
||||
* 'javascript_always_use_jquery' variable set to FALSE; on those sites, if
|
||||
* all the JavaScript added to the page by drupal_add_js() does not have a
|
||||
* dependency on jQuery, then for improved front-end performance Drupal
|
||||
* will not add jQuery and related libraries and settings to the page.
|
||||
* - defer: If set to TRUE, the defer attribute is set on the <script>
|
||||
* tag. Defaults to FALSE.
|
||||
* - cache: If set to FALSE, the JavaScript file is loaded anew on every page
|
||||
* call; in other words, it is not cached. Used only when 'type' references
|
||||
@@ -4086,6 +4186,14 @@ function drupal_region_class($region) {
|
||||
*/
|
||||
function drupal_add_js($data = NULL, $options = NULL) {
|
||||
$javascript = &drupal_static(__FUNCTION__, array());
|
||||
$jquery_added = &drupal_static(__FUNCTION__ . ':jquery_added', FALSE);
|
||||
|
||||
// If the $javascript variable has been reset with drupal_static_reset(),
|
||||
// jQuery and related files will have been removed from the list, so set the
|
||||
// variable back to FALSE to indicate they have not yet been added.
|
||||
if (empty($javascript)) {
|
||||
$jquery_added = FALSE;
|
||||
}
|
||||
|
||||
// Construct the options, taking the defaults into consideration.
|
||||
if (isset($options)) {
|
||||
@@ -4096,6 +4204,9 @@ function drupal_add_js($data = NULL, $options = NULL) {
|
||||
else {
|
||||
$options = array();
|
||||
}
|
||||
if (isset($options['type']) && $options['type'] == 'setting') {
|
||||
$options += array('requires_jquery' => FALSE);
|
||||
}
|
||||
$options += drupal_js_defaults($data);
|
||||
|
||||
// Preprocess can only be set if caching is enabled.
|
||||
@@ -4106,14 +4217,18 @@ function drupal_add_js($data = NULL, $options = NULL) {
|
||||
$options['weight'] += count($javascript) / 1000;
|
||||
|
||||
if (isset($data)) {
|
||||
// Add jquery.js and drupal.js, as well as the basePath setting, the
|
||||
// first time a JavaScript file is added.
|
||||
if (empty($javascript)) {
|
||||
// Add jquery.js, drupal.js, and related files and settings if they have
|
||||
// not been added yet. However, if the 'javascript_always_use_jquery'
|
||||
// variable is set to FALSE (indicating that the site does not want jQuery
|
||||
// automatically added on all pages) then only add it if a file or setting
|
||||
// that requires jQuery is being added also.
|
||||
if (!$jquery_added && (variable_get('javascript_always_use_jquery', TRUE) || $options['requires_jquery'])) {
|
||||
$jquery_added = TRUE;
|
||||
// url() generates the prefix using hook_url_outbound_alter(). Instead of
|
||||
// running the hook_url_outbound_alter() again here, extract the prefix
|
||||
// from url().
|
||||
url('', array('prefix' => &$prefix));
|
||||
$javascript = array(
|
||||
$default_javascript = array(
|
||||
'settings' => array(
|
||||
'data' => array(
|
||||
array('basePath' => base_path()),
|
||||
@@ -4132,11 +4247,13 @@ function drupal_add_js($data = NULL, $options = NULL) {
|
||||
'group' => JS_LIBRARY,
|
||||
'every_page' => TRUE,
|
||||
'weight' => -1,
|
||||
'requires_jquery' => TRUE,
|
||||
'preprocess' => TRUE,
|
||||
'cache' => TRUE,
|
||||
'defer' => FALSE,
|
||||
),
|
||||
);
|
||||
$javascript = drupal_array_merge_deep($javascript, $default_javascript);
|
||||
// Register all required libraries.
|
||||
drupal_add_library('system', 'jquery', TRUE);
|
||||
drupal_add_library('system', 'jquery.once', TRUE);
|
||||
@@ -4177,6 +4294,7 @@ function drupal_js_defaults($data = NULL) {
|
||||
'group' => JS_DEFAULT,
|
||||
'every_page' => FALSE,
|
||||
'weight' => 0,
|
||||
'requires_jquery' => TRUE,
|
||||
'scope' => 'header',
|
||||
'cache' => TRUE,
|
||||
'defer' => FALSE,
|
||||
@@ -4223,7 +4341,12 @@ function drupal_get_js($scope = 'header', $javascript = NULL, $skip_alter = FALS
|
||||
if (!isset($javascript)) {
|
||||
$javascript = drupal_add_js();
|
||||
}
|
||||
if (empty($javascript)) {
|
||||
|
||||
// If no JavaScript items have been added, or if the only JavaScript items
|
||||
// that have been added are JavaScript settings (which don't do anything
|
||||
// without any JavaScript code to use them), then no JavaScript code should
|
||||
// be added to the page.
|
||||
if (empty($javascript) || (isset($javascript['settings']) && count($javascript) == 1)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -4377,8 +4500,8 @@ function drupal_get_js($scope = 'header', $javascript = NULL, $skip_alter = FALS
|
||||
*
|
||||
* Libraries, JavaScript, CSS and other types of custom structures are attached
|
||||
* to elements using the #attached property. The #attached property is an
|
||||
* associative array, where the keys are the the attachment types and the values
|
||||
* are the attached data. For example:
|
||||
* associative array, where the keys are the attachment types and the values are
|
||||
* the attached data. For example:
|
||||
* @code
|
||||
* $build['#attached'] = array(
|
||||
* 'js' => array(drupal_get_path('module', 'taxonomy') . '/taxonomy.js'),
|
||||
@@ -5006,19 +5129,6 @@ function drupal_json_output($var = NULL) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a salt useful for hardening against SQL injection.
|
||||
*
|
||||
* @return
|
||||
* A salt based on information in settings.php, not in the database.
|
||||
*/
|
||||
function drupal_get_hash_salt() {
|
||||
global $drupal_hash_salt, $databases;
|
||||
// If the $drupal_hash_salt variable is empty, a hash of the serialized
|
||||
// database credentials is used as a fallback salt.
|
||||
return empty($drupal_hash_salt) ? hash('sha256', serialize($databases)) : $drupal_hash_salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the private key variable used to generate tokens is set.
|
||||
*
|
||||
@@ -5027,7 +5137,7 @@ function drupal_get_hash_salt() {
|
||||
*/
|
||||
function drupal_get_private_key() {
|
||||
if (!($key = variable_get('drupal_private_key', 0))) {
|
||||
$key = drupal_hash_base64(drupal_random_bytes(55));
|
||||
$key = drupal_random_key();
|
||||
variable_set('drupal_private_key', $key);
|
||||
}
|
||||
return $key;
|
||||
@@ -5038,6 +5148,18 @@ function drupal_get_private_key() {
|
||||
*
|
||||
* @param $value
|
||||
* An additional value to base the token on.
|
||||
*
|
||||
* The generated token is based on the session ID of the current user. Normally,
|
||||
* anonymous users do not have a session, so the generated token will be
|
||||
* different on every page request. To generate a token for users without a
|
||||
* session, manually start a session prior to calling this function.
|
||||
*
|
||||
* @return string
|
||||
* A 43-character URL-safe token for validation, based on the user session ID,
|
||||
* the hash salt provided from drupal_get_hash_salt(), and the
|
||||
* 'drupal_private_key' configuration variable.
|
||||
*
|
||||
* @see drupal_get_hash_salt()
|
||||
*/
|
||||
function drupal_get_token($value = '') {
|
||||
return drupal_hmac_base64($value, session_id() . drupal_get_private_key() . drupal_get_hash_salt());
|
||||
@@ -5059,7 +5181,7 @@ function drupal_get_token($value = '') {
|
||||
*/
|
||||
function drupal_valid_token($token, $value = '', $skip_anonymous = FALSE) {
|
||||
global $user;
|
||||
return (($skip_anonymous && $user->uid == 0) || ($token == drupal_get_token($value)));
|
||||
return (($skip_anonymous && $user->uid == 0) || ($token === drupal_get_token($value)));
|
||||
}
|
||||
|
||||
function _drupal_bootstrap_full() {
|
||||
@@ -5092,6 +5214,10 @@ function _drupal_bootstrap_full() {
|
||||
module_load_all();
|
||||
// Make sure all stream wrappers are registered.
|
||||
file_get_stream_wrappers();
|
||||
// Ensure mt_rand is reseeded, to prevent random values from one page load
|
||||
// being exploited to predict random values in subsequent page loads.
|
||||
$seed = unpack("L", drupal_random_bytes(4));
|
||||
mt_srand($seed[1]);
|
||||
|
||||
$test_info = &$GLOBALS['drupal_test_info'];
|
||||
if (!empty($test_info['in_child_site'])) {
|
||||
@@ -5129,7 +5255,7 @@ function _drupal_bootstrap_full() {
|
||||
* client without gzip support.
|
||||
*
|
||||
* Page compression requires the PHP zlib extension
|
||||
* (http://php.net/manual/en/ref.zlib.php).
|
||||
* (http://php.net/manual/ref.zlib.php).
|
||||
*
|
||||
* @see drupal_page_header()
|
||||
*/
|
||||
@@ -5137,6 +5263,10 @@ function drupal_page_set_cache() {
|
||||
global $base_root;
|
||||
|
||||
if (drupal_page_is_cacheable()) {
|
||||
|
||||
// Check whether the current page might be compressed.
|
||||
$page_compressed = variable_get('page_compression', TRUE) && extension_loaded('zlib');
|
||||
|
||||
$cache = (object) array(
|
||||
'cid' => $base_root . request_uri(),
|
||||
'data' => array(
|
||||
@@ -5144,6 +5274,9 @@ function drupal_page_set_cache() {
|
||||
'body' => ob_get_clean(),
|
||||
'title' => drupal_get_title(),
|
||||
'headers' => array(),
|
||||
// We need to store whether page was compressed or not,
|
||||
// because by the time it is read, the configuration might change.
|
||||
'page_compressed' => $page_compressed,
|
||||
),
|
||||
'expire' => CACHE_TEMPORARY,
|
||||
'created' => REQUEST_TIME,
|
||||
@@ -5161,7 +5294,7 @@ function drupal_page_set_cache() {
|
||||
}
|
||||
|
||||
if ($cache->data['body']) {
|
||||
if (variable_get('page_compression', TRUE) && extension_loaded('zlib')) {
|
||||
if ($page_compressed) {
|
||||
$cache->data['body'] = gzencode($cache->data['body'], 9, FORCE_GZIP);
|
||||
}
|
||||
cache_set($cache->cid, $cache->data, 'cache_page', $cache->expire);
|
||||
@@ -5210,8 +5343,6 @@ function drupal_cron_run() {
|
||||
foreach ($queues as $queue_name => $info) {
|
||||
DrupalQueue::get($queue_name)->createQueue();
|
||||
}
|
||||
// Register shutdown callback.
|
||||
drupal_register_shutdown_function('drupal_cron_cleanup');
|
||||
|
||||
// Iterate through the modules calling their cron handlers (if any):
|
||||
foreach (module_implements('cron') as $module) {
|
||||
@@ -5236,12 +5367,23 @@ function drupal_cron_run() {
|
||||
}
|
||||
|
||||
foreach ($queues as $queue_name => $info) {
|
||||
if (!empty($info['skip on cron'])) {
|
||||
// Do not run if queue wants to skip.
|
||||
continue;
|
||||
}
|
||||
$function = $info['worker callback'];
|
||||
$end = time() + (isset($info['time']) ? $info['time'] : 15);
|
||||
$queue = DrupalQueue::get($queue_name);
|
||||
while (time() < $end && ($item = $queue->claimItem())) {
|
||||
$function($item->data);
|
||||
$queue->deleteItem($item);
|
||||
try {
|
||||
$function($item->data);
|
||||
$queue->deleteItem($item);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// In case of exception log it and leave the item in the queue
|
||||
// to be processed again later.
|
||||
watchdog_exception('cron', $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Restore the user.
|
||||
@@ -5252,10 +5394,13 @@ function drupal_cron_run() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown function: Performs cron cleanup.
|
||||
* DEPRECATED: Shutdown function: Performs cron cleanup.
|
||||
*
|
||||
* @see drupal_cron_run()
|
||||
* @see drupal_register_shutdown_function()
|
||||
* This function is deprecated because the 'cron_semaphore' variable it
|
||||
* references no longer exists. It is therefore no longer used as a shutdown
|
||||
* function by Drupal core.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
function drupal_cron_cleanup() {
|
||||
// See if the semaphore is still locked.
|
||||
@@ -5568,7 +5713,7 @@ function drupal_pre_render_link($element) {
|
||||
* @code
|
||||
* $node->content['links'] = array(
|
||||
* '#theme' => 'links__node',
|
||||
* '#pre_render' = array('drupal_pre_render_links'),
|
||||
* '#pre_render' => array('drupal_pre_render_links'),
|
||||
* 'comment' => array(
|
||||
* '#theme' => 'links__node__comment',
|
||||
* '#links' => array(
|
||||
@@ -5773,23 +5918,23 @@ function drupal_render_page($page) {
|
||||
* array to be rendered independently and prevents them from being rendered
|
||||
* more than once on subsequent calls to drupal_render() (e.g., as part of a
|
||||
* larger array). If the same array or array element is passed more than once
|
||||
* to drupal_render(), it simply returns a NULL value.
|
||||
* to drupal_render(), it simply returns an empty string.
|
||||
*
|
||||
* @param $elements
|
||||
* @param array $elements
|
||||
* The structured array describing the data to be rendered.
|
||||
*
|
||||
* @return
|
||||
* @return string
|
||||
* The rendered HTML.
|
||||
*/
|
||||
function drupal_render(&$elements) {
|
||||
// Early-return nothing if user does not have access.
|
||||
if (empty($elements) || (isset($elements['#access']) && !$elements['#access'])) {
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
// Do not print elements twice.
|
||||
if (!empty($elements['#printed'])) {
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
// Try to fetch the element's markup from cache and return.
|
||||
@@ -5825,7 +5970,7 @@ function drupal_render(&$elements) {
|
||||
|
||||
// Allow #pre_render to abort rendering.
|
||||
if (!empty($elements['#printed'])) {
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
|
||||
// Get the children of the element, sorted by weight.
|
||||
@@ -5896,14 +6041,16 @@ function drupal_render(&$elements) {
|
||||
/**
|
||||
* Renders children of an element and concatenates them.
|
||||
*
|
||||
* This renders all children of an element using drupal_render() and then
|
||||
* joins them together into a single string.
|
||||
*
|
||||
* @param $element
|
||||
* @param array $element
|
||||
* The structured array whose children shall be rendered.
|
||||
* @param $children_keys
|
||||
* If the keys of the element's children are already known, they can be passed
|
||||
* in to save another run of element_children().
|
||||
* @param array $children_keys
|
||||
* (optional) If the keys of the element's children are already known, they
|
||||
* can be passed in to save another run of element_children().
|
||||
*
|
||||
* @return string
|
||||
* The rendered HTML of all children of the element.
|
||||
|
||||
* @see drupal_render()
|
||||
*/
|
||||
function drupal_render_children(&$element, $children_keys = NULL) {
|
||||
if ($children_keys === NULL) {
|
||||
@@ -6447,6 +6594,44 @@ function element_set_attributes(array &$element, array $map) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively computes the difference of arrays with additional index check.
|
||||
*
|
||||
* This is a version of array_diff_assoc() that supports multidimensional
|
||||
* arrays.
|
||||
*
|
||||
* @param array $array1
|
||||
* The array to compare from.
|
||||
* @param array $array2
|
||||
* The array to compare to.
|
||||
*
|
||||
* @return array
|
||||
* Returns an array containing all the values from array1 that are not present
|
||||
* in array2.
|
||||
*/
|
||||
function drupal_array_diff_assoc_recursive($array1, $array2) {
|
||||
$difference = array();
|
||||
|
||||
foreach ($array1 as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
if (!array_key_exists($key, $array2) || !is_array($array2[$key])) {
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
else {
|
||||
$new_diff = drupal_array_diff_assoc_recursive($value, $array2[$key]);
|
||||
if (!empty($new_diff)) {
|
||||
$difference[$key] = $new_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (!array_key_exists($key, $array2) || $array2[$key] !== $value) {
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $difference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in a nested array with variable depth.
|
||||
*
|
||||
@@ -6540,10 +6725,10 @@ function drupal_array_set_nested_value(array &$array, array $parents, $value, $f
|
||||
* $value = drupal_array_get_nested_value($form, $parents);
|
||||
* @endcode
|
||||
*
|
||||
* The return value will be NULL, regardless of whether the actual value is NULL
|
||||
* or whether the requested key does not exist. If it is required to know
|
||||
* whether the nested array key actually exists, pass a third argument that is
|
||||
* altered by reference:
|
||||
* A return value of NULL is ambiguous, and can mean either that the requested
|
||||
* key does not exist, or that the actual value is NULL. If it is required to
|
||||
* know whether the nested array key actually exists, pass a third argument that
|
||||
* is altered by reference:
|
||||
* @code
|
||||
* $key_exists = NULL;
|
||||
* $value = drupal_array_get_nested_value($form, $parents, $key_exists);
|
||||
@@ -7739,7 +7924,10 @@ function entity_load_unchanged($entity_type, $id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity controller class for an entity type.
|
||||
* Gets the entity controller for an entity type.
|
||||
*
|
||||
* @return DrupalEntityControllerInterface
|
||||
* The entity controller object for the specified entity type.
|
||||
*/
|
||||
function entity_get_controller($entity_type) {
|
||||
$controllers = &drupal_static(__FUNCTION__, array());
|
||||
@@ -7799,6 +7987,56 @@ function entity_prepare_view($entity_type, $entities, $langcode = NULL) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke hook_entity_view_mode_alter().
|
||||
*
|
||||
* If adding a new entity similar to nodes, comments or users, you should invoke
|
||||
* this function during the ENTITY_build_content() or ENTITY_view_multiple()
|
||||
* phases of rendering to allow other modules to alter the view mode during this
|
||||
* phase. This function needs to be called before field_attach_prepare_view() to
|
||||
* ensure that the correct content is loaded by field API.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The type of entity, i.e. 'node', 'user'.
|
||||
* @param $entities
|
||||
* The entity objects which are being prepared for view, keyed by object ID.
|
||||
* @param $view_mode
|
||||
* The original view mode e.g. 'full', 'teaser'...
|
||||
* @param $langcode
|
||||
* (optional) A language code to be used for rendering. Defaults to the global
|
||||
* content language of the current request.
|
||||
* @return
|
||||
* An associative array with arrays of entities keyed by view mode.
|
||||
*
|
||||
* @see hook_entity_view_mode_alter()
|
||||
*/
|
||||
function entity_view_mode_prepare($entity_type, $entities, $view_mode, $langcode = NULL) {
|
||||
if (!isset($langcode)) {
|
||||
$langcode = $GLOBALS['language_content']->language;
|
||||
}
|
||||
|
||||
// To ensure hooks are never run after field_attach_prepare_view() only
|
||||
// process items without the entity_view_prepared flag.
|
||||
$entities_by_view_mode = array();
|
||||
foreach ($entities as $id => $entity) {
|
||||
$entity_view_mode = $view_mode;
|
||||
if (empty($entity->entity_view_prepared)) {
|
||||
|
||||
// Allow modules to change the view mode.
|
||||
$context = array(
|
||||
'entity_type' => $entity_type,
|
||||
'entity' => $entity,
|
||||
'langcode' => $langcode,
|
||||
);
|
||||
drupal_alter('entity_view_mode', $entity_view_mode, $context);
|
||||
}
|
||||
|
||||
$entities_by_view_mode[$entity_view_mode][$id] = $entity;
|
||||
}
|
||||
|
||||
return $entities_by_view_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URI elements of an entity.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user