update core to 7.36
This commit is contained in:
@@ -211,7 +211,7 @@
|
||||
*
|
||||
* When returning an Ajax command array, it is often useful to have
|
||||
* status messages rendered along with other tasks in the command array.
|
||||
* In that case the the Ajax commands array may be constructed like this:
|
||||
* In that case the Ajax commands array may be constructed like this:
|
||||
* @code
|
||||
* $commands = array();
|
||||
* $commands[] = ajax_command_replace(NULL, $output);
|
||||
@@ -276,7 +276,7 @@ function ajax_render($commands = array()) {
|
||||
|
||||
$extra_commands = array();
|
||||
if (!empty($styles)) {
|
||||
$extra_commands[] = ajax_command_prepend('head', $styles);
|
||||
$extra_commands[] = ajax_command_add_css($styles);
|
||||
}
|
||||
if (!empty($scripts_header)) {
|
||||
$extra_commands[] = ajax_command_prepend('head', $scripts_header);
|
||||
@@ -292,7 +292,7 @@ function ajax_render($commands = array()) {
|
||||
$scripts = drupal_add_js();
|
||||
if (!empty($scripts['settings'])) {
|
||||
$settings = $scripts['settings'];
|
||||
array_unshift($commands, ajax_command_settings(call_user_func_array('array_merge_recursive', $settings['data']), TRUE));
|
||||
array_unshift($commands, ajax_command_settings(drupal_array_merge_deep_array($settings['data']), TRUE));
|
||||
}
|
||||
|
||||
// Allow modules to alter any Ajax response.
|
||||
@@ -1257,3 +1257,26 @@ function ajax_command_update_build_id($form) {
|
||||
'new' => $form['#build_id'],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Drupal Ajax 'add_css' command.
|
||||
*
|
||||
* This method will add css via ajax in a cross-browser compatible way.
|
||||
*
|
||||
* This command is implemented by Drupal.ajax.prototype.commands.add_css()
|
||||
* defined in misc/ajax.js.
|
||||
*
|
||||
* @param $styles
|
||||
* A string that contains the styles to be added.
|
||||
*
|
||||
* @return
|
||||
* An array suitable for use with the ajax_render() function.
|
||||
*
|
||||
* @see misc/ajax.js
|
||||
*/
|
||||
function ajax_command_add_css($styles) {
|
||||
return array(
|
||||
'command' => 'add_css',
|
||||
'data' => $styles,
|
||||
);
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
/**
|
||||
* The current system version.
|
||||
*/
|
||||
define('VERSION', '7.28');
|
||||
define('VERSION', '7.36');
|
||||
|
||||
/**
|
||||
* Core API compatibility.
|
||||
@@ -248,6 +248,15 @@ define('REGISTRY_WRITE_LOOKUP_CACHE', 2);
|
||||
*/
|
||||
define('DRUPAL_PHP_FUNCTION_PATTERN', '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*');
|
||||
|
||||
/**
|
||||
* A RFC7231 Compliant date.
|
||||
*
|
||||
* http://tools.ietf.org/html/rfc7231#section-7.1.1.1
|
||||
*
|
||||
* Example: Sun, 06 Nov 1994 08:49:37 GMT
|
||||
*/
|
||||
define('DATE_RFC7231', 'D, d M Y H:i:s \G\M\T');
|
||||
|
||||
/**
|
||||
* Provides a caching wrapper to be used in place of large array structures.
|
||||
*
|
||||
@@ -520,9 +529,8 @@ function timer_stop($name) {
|
||||
* Returns the appropriate configuration directory.
|
||||
*
|
||||
* Returns the configuration path based on the site's hostname, port, and
|
||||
* pathname. Uses find_conf_path() to find the current configuration directory.
|
||||
* See default.settings.php for examples on how the URL is converted to a
|
||||
* directory.
|
||||
* pathname. See default.settings.php for examples on how the URL is converted
|
||||
* to a directory.
|
||||
*
|
||||
* @param bool $require_settings
|
||||
* Only configuration directories with an existing settings.php file
|
||||
@@ -700,7 +708,14 @@ function drupal_environment_initialize() {
|
||||
* TRUE if only containing valid characters, or FALSE otherwise.
|
||||
*/
|
||||
function drupal_valid_http_host($host) {
|
||||
return preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host);
|
||||
// Limit the length of the host name to 1000 bytes to prevent DoS attacks with
|
||||
// long host names.
|
||||
return strlen($host) <= 1000
|
||||
// Limit the number of subdomains and port separators to prevent DoS attacks
|
||||
// in conf_path().
|
||||
&& substr_count($host, '.') <= 100
|
||||
&& substr_count($host, ':') <= 100
|
||||
&& preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -845,7 +860,7 @@ function drupal_get_filename($type, $name, $filename = NULL) {
|
||||
try {
|
||||
if (function_exists('db_query')) {
|
||||
$file = db_query("SELECT filename FROM {system} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type))->fetchField();
|
||||
if (file_exists(DRUPAL_ROOT . '/' . $file)) {
|
||||
if ($file !== FALSE && file_exists(DRUPAL_ROOT . '/' . $file)) {
|
||||
$files[$type][$name] = $file;
|
||||
}
|
||||
}
|
||||
@@ -1230,23 +1245,10 @@ function drupal_send_headers($default_headers = array(), $only_default = FALSE)
|
||||
* fresh page on every request. This prevents authenticated users from seeing
|
||||
* locally cached pages.
|
||||
*
|
||||
* Also give each page a unique ETag. This will force clients to include both
|
||||
* an If-Modified-Since header and an If-None-Match header when doing
|
||||
* conditional requests for the page (required by RFC 2616, section 13.3.4),
|
||||
* making the validation more robust. This is a workaround for a bug in Mozilla
|
||||
* Firefox that is triggered when Drupal's caching is enabled and the user
|
||||
* accesses Drupal via an HTTP proxy (see
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=269303): When an authenticated
|
||||
* user requests a page, and then logs out and requests the same page again,
|
||||
* Firefox may send a conditional request based on the page that was cached
|
||||
* locally when the user was logged in. If this page did not have an ETag
|
||||
* header, the request only contains an If-Modified-Since header. The date will
|
||||
* be recent, because with authenticated users the Last-Modified header always
|
||||
* refers to the time of the request. If the user accesses Drupal via a proxy
|
||||
* server, and the proxy already has a cached copy of the anonymous page with an
|
||||
* older Last-Modified date, the proxy may respond with 304 Not Modified, making
|
||||
* the client think that the anonymous and authenticated pageviews are
|
||||
* identical.
|
||||
* ETag and Last-Modified headers are not set per default for authenticated
|
||||
* users so that browsers do not send If-Modified-Since headers from
|
||||
* authenticated user pages. drupal_serve_page_from_cache() will set appropriate
|
||||
* ETag and Last-Modified headers for cached pages.
|
||||
*
|
||||
* @see drupal_page_set_cache()
|
||||
*/
|
||||
@@ -1259,9 +1261,7 @@ function drupal_page_header() {
|
||||
|
||||
$default_headers = array(
|
||||
'Expires' => 'Sun, 19 Nov 1978 05:00:00 GMT',
|
||||
'Last-Modified' => gmdate(DATE_RFC1123, REQUEST_TIME),
|
||||
'Cache-Control' => 'no-cache, must-revalidate, post-check=0, pre-check=0',
|
||||
'ETag' => '"' . REQUEST_TIME . '"',
|
||||
);
|
||||
drupal_send_headers($default_headers);
|
||||
}
|
||||
@@ -1329,7 +1329,7 @@ function drupal_serve_page_from_cache(stdClass $cache) {
|
||||
drupal_add_http_header($name, $value);
|
||||
}
|
||||
|
||||
$default_headers['Last-Modified'] = gmdate(DATE_RFC1123, $cache->created);
|
||||
$default_headers['Last-Modified'] = gmdate(DATE_RFC7231, $cache->created);
|
||||
|
||||
// HTTP/1.0 proxies does not support the Vary header, so prevent any caching
|
||||
// by sending an Expires date in the past. HTTP/1.1 clients ignores the
|
||||
@@ -1552,12 +1552,13 @@ function format_string($string, array $args = array()) {
|
||||
* Also validates strings as UTF-8 to prevent cross site scripting attacks on
|
||||
* Internet Explorer 6.
|
||||
*
|
||||
* @param $text
|
||||
* @param string $text
|
||||
* The text to be checked or processed.
|
||||
*
|
||||
* @return
|
||||
* An HTML safe version of $text, or an empty string if $text is not
|
||||
* valid UTF-8.
|
||||
* @return string
|
||||
* An HTML safe version of $text. If $text is not valid UTF-8, an empty string
|
||||
* is returned and, on PHP < 5.4, a warning may be issued depending on server
|
||||
* configuration (see @link https://bugs.php.net/bug.php?id=47494 @endlink).
|
||||
*
|
||||
* @see drupal_validate_utf8()
|
||||
* @ingroup sanitization
|
||||
@@ -1642,14 +1643,14 @@ function request_uri() {
|
||||
* information about the passed-in exception is used.
|
||||
* @param $variables
|
||||
* Array of variables to replace in the message on display. Defaults to the
|
||||
* return value of drupal_decode_exception().
|
||||
* return value of _drupal_decode_exception().
|
||||
* @param $severity
|
||||
* The severity of the message, as per RFC 3164.
|
||||
* @param $link
|
||||
* A link to associate with the message.
|
||||
*
|
||||
* @see watchdog()
|
||||
* @see drupal_decode_exception()
|
||||
* @see _drupal_decode_exception()
|
||||
*/
|
||||
function watchdog_exception($type, Exception $exception, $message = NULL, $variables = array(), $severity = WATCHDOG_ERROR, $link = NULL) {
|
||||
|
||||
@@ -2169,7 +2170,7 @@ function drupal_anonymous_user() {
|
||||
* drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
|
||||
* @endcode
|
||||
*
|
||||
* @param $phase
|
||||
* @param int $phase
|
||||
* A constant telling which phase to bootstrap to. When you bootstrap to a
|
||||
* particular phase, all earlier phases are run automatically. Possible
|
||||
* values:
|
||||
@@ -2182,11 +2183,11 @@ function drupal_anonymous_user() {
|
||||
* - DRUPAL_BOOTSTRAP_LANGUAGE: Finds out the language of the page.
|
||||
* - DRUPAL_BOOTSTRAP_FULL: Fully loads Drupal. Validates and fixes input
|
||||
* data.
|
||||
* @param $new_phase
|
||||
* @param boolean $new_phase
|
||||
* A boolean, set to FALSE if calling drupal_bootstrap from inside a
|
||||
* function called from drupal_bootstrap (recursion).
|
||||
*
|
||||
* @return
|
||||
* @return int
|
||||
* The most recently completed phase.
|
||||
*/
|
||||
function drupal_bootstrap($phase = NULL, $new_phase = TRUE) {
|
||||
@@ -2208,12 +2209,13 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) {
|
||||
// bootstrap state.
|
||||
static $stored_phase = -1;
|
||||
|
||||
// When not recursing, store the phase name so it's not forgotten while
|
||||
// recursing.
|
||||
if ($new_phase) {
|
||||
$final_phase = $phase;
|
||||
}
|
||||
if (isset($phase)) {
|
||||
// When not recursing, store the phase name so it's not forgotten while
|
||||
// recursing but take care of not going backwards.
|
||||
if ($new_phase && $phase >= $stored_phase) {
|
||||
$final_phase = $phase;
|
||||
}
|
||||
|
||||
// Call a phase if it has not been called before and is below the requested
|
||||
// phase.
|
||||
while ($phases && $phase > $stored_phase && $final_phase > $stored_phase) {
|
||||
@@ -2479,6 +2481,26 @@ function _drupal_bootstrap_variables() {
|
||||
// Load bootstrap modules.
|
||||
require_once DRUPAL_ROOT . '/includes/module.inc';
|
||||
module_load_all(TRUE);
|
||||
|
||||
// Sanitize the destination parameter (which is often used for redirects) to
|
||||
// prevent open redirect attacks leading to other domains. Sanitize both
|
||||
// $_GET['destination'] and $_REQUEST['destination'] to protect code that
|
||||
// relies on either, but do not sanitize $_POST to avoid interfering with
|
||||
// unrelated form submissions. The sanitization happens here because
|
||||
// url_is_external() requires the variable system to be available.
|
||||
if (isset($_GET['destination']) || isset($_REQUEST['destination'])) {
|
||||
require_once DRUPAL_ROOT . '/includes/common.inc';
|
||||
// If the destination is an external URL, remove it.
|
||||
if (isset($_GET['destination']) && url_is_external($_GET['destination'])) {
|
||||
unset($_GET['destination']);
|
||||
unset($_REQUEST['destination']);
|
||||
}
|
||||
// If there's still something in $_REQUEST['destination'] that didn't come
|
||||
// from $_GET, check it too.
|
||||
if (isset($_REQUEST['destination']) && (!isset($_GET['destination']) || $_REQUEST['destination'] != $_GET['destination']) && url_is_external($_REQUEST['destination'])) {
|
||||
unset($_REQUEST['destination']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2501,7 +2523,7 @@ function _drupal_bootstrap_page_header() {
|
||||
* @see drupal_bootstrap()
|
||||
*/
|
||||
function drupal_get_bootstrap_phase() {
|
||||
return drupal_bootstrap();
|
||||
return drupal_bootstrap(NULL, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2615,7 +2637,7 @@ function drupal_installation_attempted() {
|
||||
*
|
||||
* This would include implementations of hook_install(), which could run
|
||||
* during the Drupal installation phase, and might also be run during
|
||||
* non-installation time, such as while installing the module from the the
|
||||
* non-installation time, such as while installing the module from the
|
||||
* module administration page.
|
||||
*
|
||||
* Example usage:
|
||||
@@ -3144,10 +3166,13 @@ function _registry_check_code($type, $name = NULL) {
|
||||
// This function may get called when the default database is not active, but
|
||||
// there is no reason we'd ever want to not use the default database for
|
||||
// this query.
|
||||
$file = Database::getConnection('default', 'default')->query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array(
|
||||
':name' => $name,
|
||||
':type' => $type,
|
||||
))
|
||||
$file = Database::getConnection('default', 'default')
|
||||
->select('registry', 'r', array('target' => 'default'))
|
||||
->fields('r', array('filename'))
|
||||
// Use LIKE here to make the query case-insensitive.
|
||||
->condition('r.name', db_like($name), 'LIKE')
|
||||
->condition('r.type', $type)
|
||||
->execute()
|
||||
->fetchField();
|
||||
|
||||
// Flag that we've run a lookup query and need to update the cache.
|
||||
@@ -3321,11 +3346,9 @@ function registry_update() {
|
||||
* @param $default_value
|
||||
* Optional default value.
|
||||
* @param $reset
|
||||
* TRUE to reset a specific named variable, or all variables if $name is NULL.
|
||||
* Resetting every variable should only be used, for example, for running
|
||||
* unit tests with a clean environment. Should be used only though via
|
||||
* function drupal_static_reset() and the return value should not be used in
|
||||
* this case.
|
||||
* TRUE to reset one or all variables(s). This parameter is only used
|
||||
* internally and should not be passed in; use drupal_static_reset() instead.
|
||||
* (This function's return value should not be used when TRUE is passed in.)
|
||||
*
|
||||
* @return
|
||||
* Returns a variable by reference.
|
||||
@@ -3370,6 +3393,8 @@ function &drupal_static($name, $default_value = NULL, $reset = FALSE) {
|
||||
*
|
||||
* @param $name
|
||||
* Name of the static variable to reset. Omit to reset all variables.
|
||||
* Resetting all variables should only be used, for example, for running unit
|
||||
* tests with a clean environment.
|
||||
*/
|
||||
function drupal_static_reset($name = NULL) {
|
||||
drupal_static($name, NULL, TRUE);
|
||||
@@ -3485,3 +3510,34 @@ function drupal_check_memory_limit($required, $memory_limit = NULL) {
|
||||
// - The memory limit is greater than the memory required for the operation.
|
||||
return ((!$memory_limit) || ($memory_limit == -1) || (parse_size($memory_limit) >= parse_size($required)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates a PHP file from any active opcode caches.
|
||||
*
|
||||
* If the opcode cache does not support the invalidation of individual files,
|
||||
* the entire cache will be flushed.
|
||||
*
|
||||
* @param string $filepath
|
||||
* The absolute path of the PHP file to invalidate.
|
||||
*/
|
||||
function drupal_clear_opcode_cache($filepath) {
|
||||
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50300) {
|
||||
// Below PHP 5.3, clearstatcache does not accept any function parameters.
|
||||
clearstatcache();
|
||||
}
|
||||
else {
|
||||
clearstatcache(TRUE, $filepath);
|
||||
}
|
||||
|
||||
// Zend OPcache.
|
||||
if (function_exists('opcache_invalidate')) {
|
||||
opcache_invalidate($filepath, TRUE);
|
||||
}
|
||||
// APC.
|
||||
if (function_exists('apc_delete_file')) {
|
||||
// apc_delete_file() throws a PHP warning in case the specified file was
|
||||
// not compiled yet.
|
||||
// @see http://php.net/apc-delete-file
|
||||
@apc_delete_file($filepath);
|
||||
}
|
||||
}
|
||||
|
@@ -98,9 +98,11 @@ function cache_get_multiple(array &$cids, $bin = 'cache') {
|
||||
* @param $data
|
||||
* The data to store in the cache. Complex data types will be automatically
|
||||
* serialized before insertion. Strings will be stored as plain text and are
|
||||
* not serialized.
|
||||
* not serialized. Some storage engines only allow objects up to a maximum of
|
||||
* 1MB in size to be stored by default. When caching large arrays or similar,
|
||||
* take care to ensure $data does not exceed this size.
|
||||
* @param $bin
|
||||
* The cache bin to store the data in. Valid core values are:
|
||||
* (optional) The cache bin to store the data in. Valid core values are:
|
||||
* - cache: (default) Generic cache storage bin (used for theme registry,
|
||||
* locale date, list of simpletest tests, etc.).
|
||||
* - cache_block: Stores the content of various blocks.
|
||||
@@ -119,7 +121,7 @@ function cache_get_multiple(array &$cids, $bin = 'cache') {
|
||||
* the administrator panel.
|
||||
* - cache_path: Stores the system paths that have an alias.
|
||||
* @param $expire
|
||||
* One of the following values:
|
||||
* (optional) One of the following values:
|
||||
* - CACHE_PERMANENT: Indicates that the item should never be removed unless
|
||||
* explicitly told to using cache_clear_all() with a cache ID.
|
||||
* - CACHE_TEMPORARY: Indicates that the item should be removed at the next
|
||||
@@ -254,10 +256,12 @@ interface DrupalCacheInterface {
|
||||
* The cache ID of the data to store.
|
||||
* @param $data
|
||||
* The data to store in the cache. Complex data types will be automatically
|
||||
* serialized before insertion.
|
||||
* Strings will be stored as plain text and not serialized.
|
||||
* serialized before insertion. Strings will be stored as plain text and not
|
||||
* serialized. Some storage engines only allow objects up to a maximum of
|
||||
* 1MB in size to be stored by default. When caching large arrays or
|
||||
* similar, take care to ensure $data does not exceed this size.
|
||||
* @param $expire
|
||||
* One of the following values:
|
||||
* (optional) One of the following values:
|
||||
* - CACHE_PERMANENT: Indicates that the item should never be removed unless
|
||||
* explicitly told to using cache_clear_all() with a cache ID.
|
||||
* - CACHE_TEMPORARY: Indicates that the item should be removed at the next
|
||||
|
@@ -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) {
|
||||
@@ -990,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();
|
||||
|
||||
@@ -1083,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.
|
||||
*
|
||||
@@ -2187,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.
|
||||
@@ -2232,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.
|
||||
@@ -2309,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2609,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', ''));
|
||||
@@ -2638,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', ''));
|
||||
@@ -3447,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;
|
||||
@@ -3773,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4109,6 +4162,13 @@ 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.
|
||||
* - 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
|
||||
@@ -4126,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)) {
|
||||
@@ -4136,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.
|
||||
@@ -4146,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()),
|
||||
@@ -4172,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);
|
||||
@@ -4217,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,
|
||||
@@ -4263,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 '';
|
||||
}
|
||||
|
||||
@@ -4417,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'),
|
||||
@@ -5260,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) {
|
||||
@@ -5313,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.
|
||||
@@ -6641,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);
|
||||
@@ -7903,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.
|
||||
*
|
||||
|
@@ -736,7 +736,7 @@ abstract class DatabaseConnection extends PDO {
|
||||
// to expand it out into a comma-delimited set of placeholders.
|
||||
foreach (array_filter($args, 'is_array') as $key => $data) {
|
||||
$new_keys = array();
|
||||
foreach ($data as $i => $value) {
|
||||
foreach (array_values($data) as $i => $value) {
|
||||
// This assumes that there are no other placeholders that use the same
|
||||
// name. For example, if the array placeholder is defined as :example
|
||||
// and there is already an :example_2 placeholder, this will generate
|
||||
@@ -2832,7 +2832,7 @@ function db_drop_table($table) {
|
||||
* will be set to the value of the key in all rows. This is most useful for
|
||||
* creating NOT NULL columns with no default value in existing tables.
|
||||
* @param $keys_new
|
||||
* Optional keys and indexes specification to be created on the table along
|
||||
* (optional) Keys and indexes specification to be created on the table along
|
||||
* with adding the field. The format is the same as a table specification, but
|
||||
* without the 'fields' element. If you are adding a type 'serial' field, you
|
||||
* MUST specify at least one key or index including it in this array. See
|
||||
@@ -3012,7 +3012,7 @@ function db_drop_index($table, $name) {
|
||||
* @param $spec
|
||||
* The field specification for the new field.
|
||||
* @param $keys_new
|
||||
* Optional keys and indexes specification to be created on the table along
|
||||
* (optional) Keys and indexes specification to be created on the table along
|
||||
* with changing the field. The format is the same as a table specification
|
||||
* but without the 'fields' element.
|
||||
*/
|
||||
|
@@ -36,6 +36,10 @@ class DatabaseConnection_mysql extends DatabaseConnection {
|
||||
// Default to TCP connection on port 3306.
|
||||
$dsn = 'mysql:host=' . $connection_options['host'] . ';port=' . (empty($connection_options['port']) ? 3306 : $connection_options['port']);
|
||||
}
|
||||
// Character set is added to dsn to ensure PDO uses the proper character
|
||||
// set when escaping. This has security implications. See
|
||||
// https://www.drupal.org/node/1201452 for further discussion.
|
||||
$dsn .= ';charset=utf8';
|
||||
$dsn .= ';dbname=' . $connection_options['database'];
|
||||
// Allow PDO options to be overridden.
|
||||
$connection_options += array(
|
||||
|
@@ -40,7 +40,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
}
|
||||
else {
|
||||
$db_info = Database::getConnectionInfo();
|
||||
$info['database'] = $db_info['default']['database'];
|
||||
$info['database'] = $db_info[$this->connection->getTarget()]['database'];
|
||||
$info['table'] = $table;
|
||||
}
|
||||
return $info;
|
||||
@@ -301,10 +301,10 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
|
||||
public function renameTable($table, $new_name) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot rename %table to %table_new: table %table doesn't exist.", array('%table' => $table, '%table_new' => $new_name)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot rename @table to @table_new: table @table doesn't exist.", array('@table' => $table, '@table_new' => $new_name)));
|
||||
}
|
||||
if ($this->tableExists($new_name)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename %table to %table_new: table %table_new already exists.", array('%table' => $table, '%table_new' => $new_name)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
|
||||
}
|
||||
|
||||
$info = $this->getPrefixInfo($new_name);
|
||||
@@ -322,10 +322,10 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
|
||||
public function addField($table, $field, $spec, $keys_new = array()) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field @table.@field: table doesn't exist.", array('@field' => $field, '@table' => $table)));
|
||||
}
|
||||
if ($this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
|
||||
}
|
||||
|
||||
$fixnull = FALSE;
|
||||
@@ -361,7 +361,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
|
||||
public function fieldSetDefault($table, $field, $default) {
|
||||
if (!$this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
|
||||
}
|
||||
|
||||
if (!isset($default)) {
|
||||
@@ -376,7 +376,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
|
||||
public function fieldSetNoDefault($table, $field) {
|
||||
if (!$this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
|
||||
}
|
||||
|
||||
$this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN `' . $field . '` DROP DEFAULT');
|
||||
@@ -391,10 +391,10 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
|
||||
public function addPrimaryKey($table, $fields) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add primary key to table %table: table doesn't exist.", array('%table' => $table)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add primary key to table @table: table doesn't exist.", array('@table' => $table)));
|
||||
}
|
||||
if ($this->indexExists($table, 'PRIMARY')) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
|
||||
}
|
||||
|
||||
$this->connection->query('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . $this->createKeySql($fields) . ')');
|
||||
@@ -411,10 +411,10 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
|
||||
public function addUniqueKey($table, $name, $fields) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add unique key %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add unique key @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
if ($this->indexExists($table, $name)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key @name to table @table: unique key already exists.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
|
||||
$this->connection->query('ALTER TABLE {' . $table . '} ADD UNIQUE KEY `' . $name . '` (' . $this->createKeySql($fields) . ')');
|
||||
@@ -431,10 +431,10 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
|
||||
public function addIndex($table, $name, $fields) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add index %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
if ($this->indexExists($table, $name)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add index %name to table %table: index already exists.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
|
||||
$this->connection->query('ALTER TABLE {' . $table . '} ADD INDEX `' . $name . '` (' . $this->createKeySql($fields) . ')');
|
||||
@@ -451,10 +451,10 @@ class DatabaseSchema_mysql extends DatabaseSchema {
|
||||
|
||||
public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
|
||||
if (!$this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot change the definition of field %table.%name: field doesn't exist.", array('%table' => $table, '%name' => $field)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot change the definition of field @table.@name: field doesn't exist.", array('@table' => $table, '@name' => $field)));
|
||||
}
|
||||
if (($field != $field_new) && $this->fieldExists($table, $field_new)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename field %table.%name to %name_new: target field already exists.", array('%table' => $table, '%name' => $field, '%name_new' => $field_new)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", array('@table' => $table, '@name' => $field, '@name_new' => $field_new)));
|
||||
}
|
||||
|
||||
$sql = 'ALTER TABLE {' . $table . '} CHANGE `' . $field . '` ' . $this->createFieldSql($field_new, $this->processField($spec));
|
||||
|
@@ -314,10 +314,10 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
|
||||
|
||||
function renameTable($table, $new_name) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot rename %table to %table_new: table %table doesn't exist.", array('%table' => $table, '%table_new' => $new_name)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot rename @table to @table_new: table @table doesn't exist.", array('@table' => $table, '@table_new' => $new_name)));
|
||||
}
|
||||
if ($this->tableExists($new_name)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename %table to %table_new: table %table_new already exists.", array('%table' => $table, '%table_new' => $new_name)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
|
||||
}
|
||||
|
||||
// Get the schema and tablename for the old table.
|
||||
@@ -351,10 +351,10 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
|
||||
|
||||
public function addField($table, $field, $spec, $new_keys = array()) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field @table.@field: table doesn't exist.", array('@field' => $field, '@table' => $table)));
|
||||
}
|
||||
if ($this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
|
||||
}
|
||||
|
||||
$fixnull = FALSE;
|
||||
@@ -393,7 +393,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
|
||||
|
||||
public function fieldSetDefault($table, $field, $default) {
|
||||
if (!$this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
|
||||
}
|
||||
|
||||
if (!isset($default)) {
|
||||
@@ -408,7 +408,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
|
||||
|
||||
public function fieldSetNoDefault($table, $field) {
|
||||
if (!$this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
|
||||
}
|
||||
|
||||
$this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" DROP DEFAULT');
|
||||
@@ -435,10 +435,10 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
|
||||
|
||||
public function addPrimaryKey($table, $fields) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add primary key to table %table: table doesn't exist.", array('%table' => $table)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add primary key to table @table: table doesn't exist.", array('@table' => $table)));
|
||||
}
|
||||
if ($this->constraintExists($table, 'pkey')) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
|
||||
}
|
||||
|
||||
$this->connection->query('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . implode(',', $fields) . ')');
|
||||
@@ -455,10 +455,10 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
|
||||
|
||||
function addUniqueKey($table, $name, $fields) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add unique key %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add unique key @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
if ($this->constraintExists($table, $name . '_key')) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key @name to table @table: unique key already exists.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
|
||||
$this->connection->query('ALTER TABLE {' . $table . '} ADD CONSTRAINT "' . $this->prefixNonTable($table, $name, 'key') . '" UNIQUE (' . implode(',', $fields) . ')');
|
||||
@@ -475,10 +475,10 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
|
||||
|
||||
public function addIndex($table, $name, $fields) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add index %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
if ($this->indexExists($table, $name)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add index %name to table %table: index already exists.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
|
||||
$this->connection->query($this->_createIndexSql($table, $name, $fields));
|
||||
@@ -495,10 +495,10 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
|
||||
|
||||
public function changeField($table, $field, $field_new, $spec, $new_keys = array()) {
|
||||
if (!$this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot change the definition of field %table.%name: field doesn't exist.", array('%table' => $table, '%name' => $field)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot change the definition of field @table.@name: field doesn't exist.", array('@table' => $table, '@name' => $field)));
|
||||
}
|
||||
if (($field != $field_new) && $this->fieldExists($table, $field_new)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename field %table.%name to %name_new: target field already exists.", array('%table' => $table, '%name' => $field, '%name_new' => $field_new)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", array('@table' => $table, '@name' => $field, '@name_new' => $field_new)));
|
||||
}
|
||||
|
||||
$spec = $this->processField($spec);
|
||||
|
@@ -1694,7 +1694,7 @@ class DatabaseCondition implements QueryConditionInterface, Countable {
|
||||
* Implements Countable::count().
|
||||
*
|
||||
* Returns the size of this conditional. The size of the conditional is the
|
||||
* size of its conditional array minus one, because one element is the the
|
||||
* size of its conditional array minus one, because one element is the
|
||||
* conjunction.
|
||||
*/
|
||||
public function count() {
|
||||
|
@@ -416,7 +416,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
|
||||
* This is most useful for creating NOT NULL columns with no default
|
||||
* value in existing tables.
|
||||
* @param $keys_new
|
||||
* Optional keys and indexes specification to be created on the
|
||||
* (optional) Keys and indexes specification to be created on the
|
||||
* table along with adding the field. The format is the same as a
|
||||
* table specification but without the 'fields' element. If you are
|
||||
* adding a type 'serial' field, you MUST specify at least one key
|
||||
@@ -630,7 +630,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
|
||||
* @param $spec
|
||||
* The field specification for the new field.
|
||||
* @param $keys_new
|
||||
* Optional keys and indexes specification to be created on the
|
||||
* (optional) Keys and indexes specification to be created on the
|
||||
* table along with changing the field. The format is the same as a
|
||||
* table specification but without the 'fields' element.
|
||||
*
|
||||
@@ -654,7 +654,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
|
||||
*/
|
||||
public function createTable($name, $table) {
|
||||
if ($this->tableExists($name)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t('Table %name already exists.', array('%name' => $name)));
|
||||
throw new DatabaseSchemaObjectExistsException(t('Table @name already exists.', array('@name' => $name)));
|
||||
}
|
||||
$statements = $this->createTableSql($name, $table);
|
||||
foreach ($statements as $statement) {
|
||||
|
@@ -377,7 +377,8 @@ interface SelectQueryInterface extends QueryConditionInterface, QueryAlterableIn
|
||||
* @param $field
|
||||
* The field on which to order.
|
||||
* @param $direction
|
||||
* The direction to sort. Legal values are "ASC" and "DESC".
|
||||
* The direction to sort. Legal values are "ASC" and "DESC". Any other value
|
||||
* will be converted to "ASC".
|
||||
* @return SelectQueryInterface
|
||||
* The called object.
|
||||
*/
|
||||
@@ -1384,6 +1385,8 @@ class SelectQuery extends Query implements SelectQueryInterface {
|
||||
}
|
||||
|
||||
public function orderBy($field, $direction = 'ASC') {
|
||||
// Only allow ASC and DESC, default to ASC.
|
||||
$direction = strtoupper($direction) == 'DESC' ? 'DESC' : 'ASC';
|
||||
$this->order[$field] = $direction;
|
||||
return $this;
|
||||
}
|
||||
|
@@ -232,10 +232,10 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||
|
||||
public function renameTable($table, $new_name) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot rename %table to %table_new: table %table doesn't exist.", array('%table' => $table, '%table_new' => $new_name)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot rename @table to @table_new: table @table doesn't exist.", array('@table' => $table, '@table_new' => $new_name)));
|
||||
}
|
||||
if ($this->tableExists($new_name)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename %table to %table_new: table %table_new already exists.", array('%table' => $table, '%table_new' => $new_name)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
|
||||
}
|
||||
|
||||
$schema = $this->introspectSchema($table);
|
||||
@@ -278,10 +278,10 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||
|
||||
public function addField($table, $field, $specification, $keys_new = array()) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array('%field' => $field, '%table' => $table)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field @table.@field: table doesn't exist.", array('@field' => $field, '@table' => $table)));
|
||||
}
|
||||
if ($this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array('%field' => $field, '%table' => $table)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
|
||||
}
|
||||
|
||||
// SQLite doesn't have a full-featured ALTER TABLE statement. It only
|
||||
@@ -494,10 +494,10 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||
|
||||
public function changeField($table, $field, $field_new, $spec, $keys_new = array()) {
|
||||
if (!$this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot change the definition of field %table.%name: field doesn't exist.", array('%table' => $table, '%name' => $field)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot change the definition of field @table.@name: field doesn't exist.", array('@table' => $table, '@name' => $field)));
|
||||
}
|
||||
if (($field != $field_new) && $this->fieldExists($table, $field_new)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename field %table.%name to %name_new: target field already exists.", array('%table' => $table, '%name' => $field, '%name_new' => $field_new)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", array('@table' => $table, '@name' => $field, '@name_new' => $field_new)));
|
||||
}
|
||||
|
||||
$old_schema = $this->introspectSchema($table);
|
||||
@@ -559,10 +559,10 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||
|
||||
public function addIndex($table, $name, $fields) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add index %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
if ($this->indexExists($table, $name)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add index %name to table %table: index already exists.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
|
||||
$schema['indexes'][$name] = $fields;
|
||||
@@ -591,10 +591,10 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||
|
||||
public function addUniqueKey($table, $name, $fields) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add unique key %name to table %table: table doesn't exist.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add unique key @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
if ($this->indexExists($table, $name)) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key @name to table @table: unique key already exists.", array('@table' => $table, '@name' => $name)));
|
||||
}
|
||||
|
||||
$schema['unique keys'][$name] = $fields;
|
||||
@@ -617,14 +617,14 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||
|
||||
public function addPrimaryKey($table, $fields) {
|
||||
if (!$this->tableExists($table)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add primary key to table %table: table doesn't exist.", array('%table' => $table)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add primary key to table @table: table doesn't exist.", array('@table' => $table)));
|
||||
}
|
||||
|
||||
$old_schema = $this->introspectSchema($table);
|
||||
$new_schema = $old_schema;
|
||||
|
||||
if (!empty($new_schema['primary key'])) {
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
|
||||
throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
|
||||
}
|
||||
|
||||
$new_schema['primary key'] = $fields;
|
||||
@@ -646,7 +646,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||
|
||||
public function fieldSetDefault($table, $field, $default) {
|
||||
if (!$this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
|
||||
}
|
||||
|
||||
$old_schema = $this->introspectSchema($table);
|
||||
@@ -658,7 +658,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
|
||||
|
||||
public function fieldSetNoDefault($table, $field) {
|
||||
if (!$this->fieldExists($table, $field)) {
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
|
||||
throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
|
||||
}
|
||||
|
||||
$old_schema = $this->introspectSchema($table);
|
||||
|
@@ -28,7 +28,9 @@ interface DrupalEntityControllerInterface {
|
||||
* @param $ids
|
||||
* An array of entity IDs, or FALSE to load all entities.
|
||||
* @param $conditions
|
||||
* An array of conditions in the form 'field' => $value.
|
||||
* An array of conditions. Keys are field names on the entity's base table.
|
||||
* Values will be compared for equality. All the comparisons will be ANDed
|
||||
* together. This parameter is deprecated; use an EntityFieldQuery instead.
|
||||
*
|
||||
* @return
|
||||
* An array of entity objects indexed by their ids. When no results are
|
||||
@@ -46,7 +48,7 @@ interface DrupalEntityControllerInterface {
|
||||
class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
|
||||
|
||||
/**
|
||||
* Static cache of entities.
|
||||
* Static cache of entities, keyed by entity ID.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
@@ -236,7 +238,9 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
|
||||
* @param $ids
|
||||
* An array of entity IDs, or FALSE to load all entities.
|
||||
* @param $conditions
|
||||
* An array of conditions in the form 'field' => $value.
|
||||
* An array of conditions. Keys are field names on the entity's base table.
|
||||
* Values will be compared for equality. All the comparisons will be ANDed
|
||||
* together. This parameter is deprecated; use an EntityFieldQuery instead.
|
||||
* @param $revision_id
|
||||
* The ID of the revision to load, or FALSE if this query is asking for the
|
||||
* most current revision(s).
|
||||
|
@@ -1152,7 +1152,7 @@ function file_munge_filename($filename, $extensions, $alerts = TRUE) {
|
||||
// Remove any null bytes. See http://php.net/manual/security.filesystem.nullbytes.php
|
||||
$filename = str_replace(chr(0), '', $filename);
|
||||
|
||||
$whitelist = array_unique(explode(' ', trim($extensions)));
|
||||
$whitelist = array_unique(explode(' ', strtolower(trim($extensions))));
|
||||
|
||||
// Split the filename up by periods. The first part becomes the basename
|
||||
// the last part the final extension.
|
||||
@@ -1165,7 +1165,7 @@ function file_munge_filename($filename, $extensions, $alerts = TRUE) {
|
||||
// of allowed extensions.
|
||||
foreach ($filename_parts as $filename_part) {
|
||||
$new_filename .= '.' . $filename_part;
|
||||
if (!in_array($filename_part, $whitelist) && preg_match("/^[a-zA-Z]{2,5}\d?$/", $filename_part)) {
|
||||
if (!in_array(strtolower($filename_part), $whitelist) && preg_match("/^[a-zA-Z]{2,5}\d?$/", $filename_part)) {
|
||||
$new_filename .= '_';
|
||||
}
|
||||
}
|
||||
@@ -1559,7 +1559,7 @@ function file_save_upload($form_field_name, $validators = array(), $destination
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Add in our check of the the file name length.
|
||||
// Add in our check of the file name length.
|
||||
$validators['file_validate_name_length'] = array();
|
||||
|
||||
// Call the validation functions specified by this function's caller.
|
||||
@@ -1729,8 +1729,6 @@ function file_validate_extensions(stdClass $file, $extensions) {
|
||||
/**
|
||||
* Checks that the file's size is below certain limits.
|
||||
*
|
||||
* This check is not enforced for the user #1.
|
||||
*
|
||||
* @param $file
|
||||
* A Drupal file object.
|
||||
* @param $file_limit
|
||||
@@ -1748,20 +1746,17 @@ function file_validate_extensions(stdClass $file, $extensions) {
|
||||
*/
|
||||
function file_validate_size(stdClass $file, $file_limit = 0, $user_limit = 0) {
|
||||
global $user;
|
||||
|
||||
$errors = array();
|
||||
|
||||
// Bypass validation for uid = 1.
|
||||
if ($user->uid != 1) {
|
||||
if ($file_limit && $file->filesize > $file_limit) {
|
||||
$errors[] = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size($file->filesize), '%maxsize' => format_size($file_limit)));
|
||||
}
|
||||
|
||||
// Save a query by only calling file_space_used() when a limit is provided.
|
||||
if ($user_limit && (file_space_used($user->uid) + $file->filesize) > $user_limit) {
|
||||
$errors[] = t('The file is %filesize which would exceed your disk quota of %quota.', array('%filesize' => format_size($file->filesize), '%quota' => format_size($user_limit)));
|
||||
}
|
||||
if ($file_limit && $file->filesize > $file_limit) {
|
||||
$errors[] = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size($file->filesize), '%maxsize' => format_size($file_limit)));
|
||||
}
|
||||
|
||||
// Save a query by only calling file_space_used() when a limit is provided.
|
||||
if ($user_limit && (file_space_used($user->uid) + $file->filesize) > $user_limit) {
|
||||
$errors[] = t('The file is %filesize which would exceed your disk quota of %quota.', array('%filesize' => format_size($file->filesize), '%quota' => format_size($user_limit)));
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
@@ -1999,23 +1994,7 @@ function file_download() {
|
||||
$target = implode('/', $args);
|
||||
$uri = $scheme . '://' . $target;
|
||||
if (file_stream_wrapper_valid_scheme($scheme) && file_exists($uri)) {
|
||||
// Let other modules provide headers and controls access to the file.
|
||||
// module_invoke_all() uses array_merge_recursive() which merges header
|
||||
// values into a new array. To avoid that and allow modules to override
|
||||
// headers instead, use array_merge() to merge the returned arrays.
|
||||
$headers = array();
|
||||
foreach (module_implements('file_download') as $module) {
|
||||
$function = $module . '_file_download';
|
||||
$result = $function($uri);
|
||||
if ($result == -1) {
|
||||
// Throw away the headers received so far.
|
||||
$headers = array();
|
||||
break;
|
||||
}
|
||||
if (isset($result) && is_array($result)) {
|
||||
$headers = array_merge($headers, $result);
|
||||
}
|
||||
}
|
||||
$headers = file_download_headers($uri);
|
||||
if (count($headers)) {
|
||||
file_transfer($uri, $headers);
|
||||
}
|
||||
@@ -2027,6 +2006,69 @@ function file_download() {
|
||||
drupal_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves headers for a private file download.
|
||||
*
|
||||
* Calls all module implementations of hook_file_download() to retrieve headers
|
||||
* for files by the module that originally provided the file. The presence of
|
||||
* returned headers indicates the current user has access to the file.
|
||||
*
|
||||
* @param $uri
|
||||
* The URI for the file whose headers should be retrieved.
|
||||
*
|
||||
* @return
|
||||
* If access is allowed, headers for the file, suitable for passing to
|
||||
* file_transfer(). If access is not allowed, an empty array will be returned.
|
||||
*
|
||||
* @see file_transfer()
|
||||
* @see file_download_access()
|
||||
* @see hook_file_downlaod()
|
||||
*/
|
||||
function file_download_headers($uri) {
|
||||
// Let other modules provide headers and control access to the file.
|
||||
// module_invoke_all() uses array_merge_recursive() which merges header
|
||||
// values into a new array. To avoid that and allow modules to override
|
||||
// headers instead, use array_merge() to merge the returned arrays.
|
||||
$headers = array();
|
||||
foreach (module_implements('file_download') as $module) {
|
||||
$function = $module . '_file_download';
|
||||
$result = $function($uri);
|
||||
if ($result == -1) {
|
||||
// Throw away the headers received so far.
|
||||
$headers = array();
|
||||
break;
|
||||
}
|
||||
if (isset($result) && is_array($result)) {
|
||||
$headers = array_merge($headers, $result);
|
||||
}
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the current user has access to a particular file.
|
||||
*
|
||||
* The return value of this function hinges on the return value from
|
||||
* file_download_headers(), which is the function responsible for collecting
|
||||
* access information through hook_file_download().
|
||||
*
|
||||
* If immediately transferring the file to the browser and the headers will
|
||||
* need to be retrieved, the return value of file_download_headers() should be
|
||||
* used to determine access directly, so that access checks will not be run
|
||||
* twice.
|
||||
*
|
||||
* @param $uri
|
||||
* The URI for the file whose access should be retrieved.
|
||||
*
|
||||
* @return
|
||||
* Boolean TRUE if access is allowed. FALSE if access is not allowed.
|
||||
*
|
||||
* @see file_download_headers()
|
||||
* @see hook_file_download()
|
||||
*/
|
||||
function file_download_access($uri) {
|
||||
return count(file_download_headers($uri)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all files that match a given mask in a given directory.
|
||||
|
@@ -43,6 +43,7 @@ function file_default_mimetype_mapping() {
|
||||
4 => 'application/cap',
|
||||
5 => 'application/cu-seeme',
|
||||
6 => 'application/dsptype',
|
||||
350 => 'application/epub+zip',
|
||||
7 => 'application/hta',
|
||||
8 => 'application/java-archive',
|
||||
9 => 'application/java-serialized-object',
|
||||
@@ -64,6 +65,7 @@ function file_default_mimetype_mapping() {
|
||||
25 => 'application/rss+xml',
|
||||
26 => 'application/rtf',
|
||||
27 => 'application/smil',
|
||||
349 => 'application/vnd.amazon.ebook',
|
||||
28 => 'application/vnd.cinderella',
|
||||
29 => 'application/vnd.google-earth.kml+xml',
|
||||
30 => 'application/vnd.google-earth.kmz',
|
||||
@@ -183,6 +185,8 @@ function file_default_mimetype_mapping() {
|
||||
144 => 'application/x-lzx',
|
||||
145 => 'application/x-maker',
|
||||
146 => 'application/x-mif',
|
||||
351 => 'application/x-mobipocket-ebook',
|
||||
352 => 'application/x-mobipocket-ebook',
|
||||
147 => 'application/x-ms-wmd',
|
||||
148 => 'application/x-ms-wmz',
|
||||
149 => 'application/x-msdos-program',
|
||||
@@ -228,8 +232,10 @@ function file_default_mimetype_mapping() {
|
||||
188 => 'audio/mpeg',
|
||||
189 => 'audio/ogg',
|
||||
190 => 'audio/prs.sid',
|
||||
356 => 'audio/webm',
|
||||
191 => 'audio/x-aiff',
|
||||
192 => 'audio/x-gsm',
|
||||
354 => 'audio/x-matroska',
|
||||
193 => 'audio/x-mpegurl',
|
||||
194 => 'audio/x-ms-wax',
|
||||
195 => 'audio/x-ms-wma',
|
||||
@@ -301,6 +307,7 @@ function file_default_mimetype_mapping() {
|
||||
261 => 'image/vnd.djvu',
|
||||
262 => 'image/vnd.microsoft.icon',
|
||||
263 => 'image/vnd.wap.wbmp',
|
||||
355 => 'image/webp',
|
||||
264 => 'image/x-cmu-raster',
|
||||
265 => 'image/x-coreldraw',
|
||||
266 => 'image/x-coreldrawpattern',
|
||||
@@ -337,6 +344,7 @@ function file_default_mimetype_mapping() {
|
||||
297 => 'text/vnd.sun.j2me.app-descriptor',
|
||||
298 => 'text/vnd.wap.wml',
|
||||
299 => 'text/vnd.wap.wmlscript',
|
||||
358 => 'text/vtt',
|
||||
300 => 'text/x-bibtex',
|
||||
301 => 'text/x-boo',
|
||||
302 => 'text/x-c++hdr',
|
||||
@@ -371,9 +379,11 @@ function file_default_mimetype_mapping() {
|
||||
331 => 'video/ogg',
|
||||
332 => 'video/quicktime',
|
||||
333 => 'video/vnd.mpegurl',
|
||||
357 => 'video/webm',
|
||||
347 => 'video/x-flv',
|
||||
334 => 'video/x-la-asf',
|
||||
348 => 'video/x-m4v',
|
||||
353 => 'video/x-matroska',
|
||||
335 => 'video/x-mng',
|
||||
336 => 'video/x-ms-asf',
|
||||
337 => 'video/x-ms-wm',
|
||||
@@ -854,6 +864,16 @@ function file_default_mimetype_mapping() {
|
||||
'f4b' => 346,
|
||||
'flv' => 347,
|
||||
'm4v' => 348,
|
||||
'azw' => 349,
|
||||
'epub' => 350,
|
||||
'mobi' => 351,
|
||||
'prc' => 352,
|
||||
'mkv' => 353,
|
||||
'mka' => 354,
|
||||
'webp' => 355,
|
||||
'weba' => 356,
|
||||
'webm' => 357,
|
||||
'vtt' => 358,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@@ -72,7 +72,8 @@ class FileTransferSSH extends FileTransfer implements FileTransferChmodInterface
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw new FileTransferException('Cannot check @path.', NULL, array('@path' => $path));
|
||||
}
|
||||
}
|
||||
@@ -85,7 +86,8 @@ class FileTransferSSH extends FileTransfer implements FileTransferChmodInterface
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw new FileTransferException('Cannot check @path.', NULL, array('@path' => $path));
|
||||
}
|
||||
}
|
||||
|
@@ -938,7 +938,7 @@ function drupal_process_form($form_id, &$form, &$form_state) {
|
||||
// after the batch is processed.
|
||||
}
|
||||
|
||||
// Set a flag to indicate the the form has been processed and executed.
|
||||
// Set a flag to indicate that the form has been processed and executed.
|
||||
$form_state['executed'] = TRUE;
|
||||
|
||||
// Redirect the form based on values in $form_state.
|
||||
@@ -2451,6 +2451,17 @@ function form_type_password_confirm_value($element, $input = FALSE) {
|
||||
$element += array('#default_value' => array());
|
||||
return $element['#default_value'] + array('pass1' => '', 'pass2' => '');
|
||||
}
|
||||
$value = array('pass1' => '', 'pass2' => '');
|
||||
// Throw out all invalid array keys; we only allow pass1 and pass2.
|
||||
foreach ($value as $allowed_key => $default) {
|
||||
// These should be strings, but allow other scalars since they might be
|
||||
// valid input in programmatic form submissions. Any nested array values
|
||||
// are ignored.
|
||||
if (isset($input[$allowed_key]) && is_scalar($input[$allowed_key])) {
|
||||
$value[$allowed_key] = (string) $input[$allowed_key];
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2494,6 +2505,27 @@ function form_type_select_value($element, $input = FALSE) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the value for a textarea form element.
|
||||
*
|
||||
* @param array $element
|
||||
* The form element whose value is being populated.
|
||||
* @param mixed $input
|
||||
* The incoming input to populate the form element. If this is FALSE,
|
||||
* the element's default value should be returned.
|
||||
*
|
||||
* @return string
|
||||
* The data that will appear in the $element_state['values'] collection
|
||||
* for this element. Return nothing to use the default.
|
||||
*/
|
||||
function form_type_textarea_value($element, $input = FALSE) {
|
||||
if ($input !== FALSE) {
|
||||
// This should be a string, but allow other scalars since they might be
|
||||
// valid input in programmatic form submissions.
|
||||
return is_scalar($input) ? (string) $input : '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the value for a textfield form element.
|
||||
*
|
||||
@@ -2509,9 +2541,12 @@ function form_type_select_value($element, $input = FALSE) {
|
||||
*/
|
||||
function form_type_textfield_value($element, $input = FALSE) {
|
||||
if ($input !== FALSE && $input !== NULL) {
|
||||
// Equate $input to the form value to ensure it's marked for
|
||||
// validation.
|
||||
return str_replace(array("\r", "\n"), '', $input);
|
||||
// This should be a string, but allow other scalars since they might be
|
||||
// valid input in programmatic form submissions.
|
||||
if (!is_scalar($input)) {
|
||||
$input = '';
|
||||
}
|
||||
return str_replace(array("\r", "\n"), '', (string) $input);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2699,17 +2734,43 @@ function theme_select($variables) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a select form element's options array into HTML.
|
||||
* Converts an array of options into HTML, for use in select list form elements.
|
||||
*
|
||||
* @param $element
|
||||
* An associative array containing the properties of the element.
|
||||
* @param $choices
|
||||
* Mixed: Either an associative array of items to list as choices, or an
|
||||
* object with an 'option' member that is an associative array. This
|
||||
* parameter is only used internally and should not be passed.
|
||||
* This function calls itself recursively to obtain the values for each optgroup
|
||||
* within the list of options and when the function encounters an object with
|
||||
* an 'options' property inside $element['#options'].
|
||||
*
|
||||
* @return
|
||||
* An HTML string of options for the select form element.
|
||||
* @param array $element
|
||||
* An associative array containing the following key-value pairs:
|
||||
* - #multiple: Optional Boolean indicating if the user may select more than
|
||||
* one item.
|
||||
* - #options: An associative array of options to render as HTML. Each array
|
||||
* value can be a string, an array, or an object with an 'option' property:
|
||||
* - A string or integer key whose value is a translated string is
|
||||
* interpreted as a single HTML option element. Do not use placeholders
|
||||
* that sanitize data: doing so will lead to double-escaping. Note that
|
||||
* the key will be visible in the HTML and could be modified by malicious
|
||||
* users, so don't put sensitive information in it.
|
||||
* - A translated string key whose value is an array indicates a group of
|
||||
* options. The translated string is used as the label attribute for the
|
||||
* optgroup. Do not use placeholders to sanitize data: doing so will lead
|
||||
* to double-escaping. The array should contain the options you wish to
|
||||
* group and should follow the syntax of $element['#options'].
|
||||
* - If the function encounters a string or integer key whose value is an
|
||||
* object with an 'option' property, the key is ignored, the contents of
|
||||
* the option property are interpreted as $element['#options'], and the
|
||||
* resulting HTML is added to the output.
|
||||
* - #value: Optional integer, string, or array representing which option(s)
|
||||
* to pre-select when the list is first displayed. The integer or string
|
||||
* must match the key of an option in the '#options' list. If '#multiple' is
|
||||
* TRUE, this can be an array of integers or strings.
|
||||
* @param array|null $choices
|
||||
* (optional) Either an associative array of options in the same format as
|
||||
* $element['#options'] above, or NULL. This parameter is only used internally
|
||||
* and is not intended to be passed in to the initial function call.
|
||||
*
|
||||
* @return string
|
||||
* An HTML string of options and optgroups for use in a select form element.
|
||||
*/
|
||||
function form_select_options($element, $choices = NULL) {
|
||||
if (!isset($choices)) {
|
||||
@@ -2722,7 +2783,7 @@ function form_select_options($element, $choices = NULL) {
|
||||
$options = '';
|
||||
foreach ($choices as $key => $choice) {
|
||||
if (is_array($choice)) {
|
||||
$options .= '<optgroup label="' . $key . '">';
|
||||
$options .= '<optgroup label="' . check_plain($key) . '">';
|
||||
$options .= form_select_options($element, $choice);
|
||||
$options .= '</optgroup>';
|
||||
}
|
||||
@@ -3285,6 +3346,8 @@ function form_process_container($element, &$form_state) {
|
||||
*/
|
||||
function theme_container($variables) {
|
||||
$element = $variables['element'];
|
||||
// Ensure #attributes is set.
|
||||
$element += array('#attributes' => array());
|
||||
|
||||
// Special handling for form elements.
|
||||
if (isset($element['#array_parents'])) {
|
||||
|
@@ -420,7 +420,7 @@ abstract class DatabaseTasks {
|
||||
}
|
||||
}
|
||||
if (!empty($message)) {
|
||||
$message = '<p>In order for Drupal to work, and to continue with the installation process, you must resolve all issues reported below. For more help with configuring your database server, see the <a href="http://drupal.org/getting-started/install">installation handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.</p>' . $message;
|
||||
$message = 'Resolve all issues below to continue the installation. For help configuring your database server, see the <a href="http://drupal.org/getting-started/install">installation handbook</a>, or contact your hosting provider.' . $message;
|
||||
throw new DatabaseTaskException($message);
|
||||
}
|
||||
}
|
||||
@@ -653,6 +653,13 @@ function drupal_rewrite_settings($settings = array(), $prefix = '') {
|
||||
if ($fp && fwrite($fp, $buffer) === FALSE) {
|
||||
throw new Exception(st('Failed to modify %settings. Verify the file permissions.', array('%settings' => $settings_file)));
|
||||
}
|
||||
else {
|
||||
// The existing settings.php file might have been included already. In
|
||||
// case an opcode cache is enabled, the rewritten contents of the file
|
||||
// will not be reflected in this process. Ensure to invalidate the file
|
||||
// in case an opcode cache is enabled.
|
||||
drupal_clear_opcode_cache(DRUPAL_ROOT . '/' . $settings_file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Exception(st('Failed to open %settings. Verify the file permissions.', array('%settings' => $default_settings)));
|
||||
|
@@ -297,7 +297,7 @@ function language_negotiation_get_switch_links($type, $path) {
|
||||
// Add support for WCAG 2.0's Language of Parts to add language identifiers.
|
||||
// http://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-other-lang-id.html
|
||||
foreach ($result as $langcode => $link) {
|
||||
$result[$langcode]['attributes']['lang'] = $langcode;
|
||||
$result[$langcode]['attributes']['xml:lang'] = $langcode;
|
||||
}
|
||||
|
||||
if (!empty($result)) {
|
||||
|
@@ -398,7 +398,7 @@ function locale_language_switcher_session($type, $path) {
|
||||
$links[$langcode]['query'][$param] = $langcode;
|
||||
}
|
||||
else {
|
||||
$links[$langcode]['attributes']['class'][] = ' session-active';
|
||||
$links[$langcode]['attributes']['class'][] = 'session-active';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1931,7 +1931,7 @@ function _locale_translate_seek() {
|
||||
$groups[$string['group']],
|
||||
array('data' => check_plain(truncate_utf8($string['source'], 150, FALSE, TRUE)) . '<br /><small>' . $string['location'] . '</small>'),
|
||||
$string['context'],
|
||||
array('data' => _locale_translate_language_list($string['languages'], $limit_language), 'align' => 'center'),
|
||||
array('data' => _locale_translate_language_list($string, $limit_language), 'align' => 'center'),
|
||||
array('data' => l(t('edit'), "admin/config/regional/translate/edit/$lid", array('query' => drupal_get_destination())), 'class' => array('nowrap')),
|
||||
array('data' => l(t('delete'), "admin/config/regional/translate/delete/$lid", array('query' => drupal_get_destination())), 'class' => array('nowrap')),
|
||||
);
|
||||
@@ -2126,16 +2126,21 @@ function _locale_rebuild_js($langcode = NULL) {
|
||||
/**
|
||||
* List languages in search result table
|
||||
*/
|
||||
function _locale_translate_language_list($translation, $limit_language) {
|
||||
function _locale_translate_language_list($string, $limit_language) {
|
||||
// Add CSS.
|
||||
drupal_add_css(drupal_get_path('module', 'locale') . '/locale.css');
|
||||
|
||||
// Include both translated and not yet translated target languages in the
|
||||
// list. The source language is English for built-in strings and the default
|
||||
// language for other strings.
|
||||
$languages = language_list();
|
||||
unset($languages['en']);
|
||||
$default = language_default();
|
||||
$omit = $string['group'] == 'default' ? 'en' : $default->language;
|
||||
unset($languages[$omit]);
|
||||
$output = '';
|
||||
foreach ($languages as $langcode => $language) {
|
||||
if (!$limit_language || $limit_language == $langcode) {
|
||||
$output .= (!empty($translation[$langcode])) ? $langcode . ' ' : "<em class=\"locale-untranslated\">$langcode</em> ";
|
||||
$output .= (!empty($string['languages'][$langcode])) ? $langcode . ' ' : "<em class=\"locale-untranslated\">$langcode</em> ";
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -92,7 +92,7 @@ function _lock_id() {
|
||||
* Acquire (or renew) a lock, but do not block if it fails.
|
||||
*
|
||||
* @param $name
|
||||
* The name of the lock.
|
||||
* The name of the lock. Limit of name's length is 255 characters.
|
||||
* @param $timeout
|
||||
* A number of seconds (float) before the lock expires (minimum of 0.001).
|
||||
*
|
||||
|
@@ -10,7 +10,7 @@
|
||||
*
|
||||
* $conf['mail_line_endings'] will override this setting.
|
||||
*/
|
||||
define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE ? "\r\n" : "\n");
|
||||
define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE) ? "\r\n" : "\n");
|
||||
|
||||
/**
|
||||
* Composes and optionally sends an e-mail message.
|
||||
|
@@ -456,7 +456,9 @@ function menu_get_item($path = NULL, $router_item = NULL) {
|
||||
// Rebuild if we know it's needed, or if the menu masks are missing which
|
||||
// occurs rarely, likely due to a race condition of multiple rebuilds.
|
||||
if (variable_get('menu_rebuild_needed', FALSE) || !variable_get('menu_masks', array())) {
|
||||
menu_rebuild();
|
||||
if (_menu_check_rebuild()) {
|
||||
menu_rebuild();
|
||||
}
|
||||
}
|
||||
$original_map = arg(NULL, $path);
|
||||
|
||||
@@ -2495,6 +2497,7 @@ function menu_link_get_preferred($path = NULL, $selected_menu = NULL) {
|
||||
$query->addField('ml', 'weight', 'link_weight');
|
||||
$query->fields('m');
|
||||
$query->condition('ml.link_path', $path_candidates, 'IN');
|
||||
$query->addTag('preferred_menu_links');
|
||||
|
||||
// Sort candidates by link path and menu name.
|
||||
$candidates = array();
|
||||
@@ -2692,6 +2695,21 @@ function menu_reset_static_cache() {
|
||||
drupal_static_reset('menu_link_get_preferred');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a menu_rebuild() is necessary.
|
||||
*/
|
||||
function _menu_check_rebuild() {
|
||||
// To absolutely ensure that the menu rebuild is required, re-load the
|
||||
// variables in case they were set by another process.
|
||||
$variables = variable_initialize();
|
||||
if (empty($variables['menu_rebuild_needed']) && !empty($variables['menu_masks'])) {
|
||||
unset($GLOBALS['conf']['menu_rebuild_needed']);
|
||||
$GLOBALS['conf']['menu_masks'] = $variables['menu_masks'];
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the database tables used by various menu functions.
|
||||
*
|
||||
@@ -2712,6 +2730,14 @@ function menu_rebuild() {
|
||||
// We choose to block here since otherwise the router item may not
|
||||
// be available in menu_execute_active_handler() resulting in a 404.
|
||||
lock_wait('menu_rebuild');
|
||||
|
||||
if (_menu_check_rebuild()) {
|
||||
// If we get here and menu_masks was not set, then it is possible a menu
|
||||
// is being reloaded, or that the process rebuilding the menu was unable
|
||||
// to complete successfully. A missing menu_masks variable could result
|
||||
// in a 404, so re-run the function.
|
||||
return menu_rebuild();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -2736,6 +2762,12 @@ function menu_rebuild() {
|
||||
$transaction->rollback();
|
||||
watchdog_exception('menu', $e);
|
||||
}
|
||||
// Explicitly commit the transaction now; this ensures that the database
|
||||
// operations during the menu rebuild are committed before the lock is made
|
||||
// available again, since locks may not always reside in the same database
|
||||
// connection. The lock is acquired outside of the transaction so should also
|
||||
// be released outside of it.
|
||||
unset($transaction);
|
||||
|
||||
lock_release('menu_rebuild');
|
||||
return TRUE;
|
||||
|
@@ -265,11 +265,11 @@ function _module_build_dependencies($files) {
|
||||
/**
|
||||
* Determines whether a given module exists.
|
||||
*
|
||||
* @param $module
|
||||
* @param string $module
|
||||
* The name of the module (without the .module extension).
|
||||
*
|
||||
* @return
|
||||
* TRUE if the module is both installed and enabled.
|
||||
* @return bool
|
||||
* TRUE if the module is both installed and enabled, FALSE otherwise.
|
||||
*/
|
||||
function module_exists($module) {
|
||||
$list = module_list();
|
||||
|
@@ -140,7 +140,7 @@ function _password_enforce_log2_boundaries($count_log2) {
|
||||
* @param $algo
|
||||
* The string name of a hashing algorithm usable by hash(), like 'sha256'.
|
||||
* @param $password
|
||||
* The plain-text password to hash.
|
||||
* Plain-text password up to 512 bytes (128 to 512 UTF-8 characters) to hash.
|
||||
* @param $setting
|
||||
* An existing hash or the output of _password_generate_salt(). Must be
|
||||
* at least 12 characters (the settings and salt).
|
||||
@@ -150,6 +150,10 @@ function _password_enforce_log2_boundaries($count_log2) {
|
||||
* The return string will be truncated at DRUPAL_HASH_LENGTH characters max.
|
||||
*/
|
||||
function _password_crypt($algo, $password, $setting) {
|
||||
// Prevent DoS attacks by refusing to hash large passwords.
|
||||
if (strlen($password) > 512) {
|
||||
return FALSE;
|
||||
}
|
||||
// The first 12 characters of an existing hash are its setting string.
|
||||
$setting = substr($setting, 0, 12);
|
||||
|
||||
|
@@ -79,7 +79,7 @@ function _drupal_session_read($sid) {
|
||||
// Handle the case of first time visitors and clients that don't store
|
||||
// cookies (eg. web crawlers).
|
||||
$insecure_session_name = substr(session_name(), 1);
|
||||
if (!isset($_COOKIE[session_name()]) && !isset($_COOKIE[$insecure_session_name])) {
|
||||
if (empty($sid) || (!isset($_COOKIE[session_name()]) && !isset($_COOKIE[$insecure_session_name]))) {
|
||||
$user = drupal_anonymous_user();
|
||||
return '';
|
||||
}
|
||||
|
@@ -46,10 +46,9 @@ class TableSort extends SelectQueryExtender {
|
||||
// Based on code from db_escape_table(), but this can also contain a dot.
|
||||
$field = preg_replace('/[^A-Za-z0-9_.]+/', '', $ts['sql']);
|
||||
|
||||
// Sort order can only be ASC or DESC.
|
||||
$sort = drupal_strtoupper($ts['sort']);
|
||||
$sort = in_array($sort, array('ASC', 'DESC')) ? $sort : '';
|
||||
$this->orderBy($field, $sort);
|
||||
// orderBy() will ensure that only ASC/DESC values are accepted, so we
|
||||
// don't need to sanitize that here.
|
||||
$this->orderBy($field, $ts['sort']);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
@@ -1029,6 +1029,7 @@ function theme($hook, $variables = array()) {
|
||||
}
|
||||
$hook = $candidate;
|
||||
}
|
||||
$theme_hook_original = $hook;
|
||||
|
||||
// If there's no implementation, check for more generic fallbacks. If there's
|
||||
// still no implementation, log an error and return an empty string.
|
||||
@@ -1090,6 +1091,8 @@ function theme($hook, $variables = array()) {
|
||||
$variables += array($info['render element'] => array());
|
||||
}
|
||||
|
||||
$variables['theme_hook_original'] = $theme_hook_original;
|
||||
|
||||
// Invoke the variable processors, if any. The processors may specify
|
||||
// alternate suggestions for which hook's template/function to use. If the
|
||||
// hook is a suggestion of a base hook, invoke the variable processors of
|
||||
@@ -1198,7 +1201,12 @@ function theme($hook, $variables = array()) {
|
||||
if (isset($info['path'])) {
|
||||
$template_file = $info['path'] . '/' . $template_file;
|
||||
}
|
||||
$output = $render_function($template_file, $variables);
|
||||
if (variable_get('theme_debug', FALSE)) {
|
||||
$output = _theme_render_template_debug($render_function, $template_file, $variables, $extension);
|
||||
}
|
||||
else {
|
||||
$output = $render_function($template_file, $variables);
|
||||
}
|
||||
}
|
||||
|
||||
// restore path_to_theme()
|
||||
@@ -1520,6 +1528,72 @@ function theme_render_template($template_file, $variables) {
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a template for any engine.
|
||||
*
|
||||
* Includes the possibility to get debug output by setting the
|
||||
* theme_debug variable to TRUE.
|
||||
*
|
||||
* @param string $template_function
|
||||
* The function to call for rendering the template.
|
||||
* @param string $template_file
|
||||
* The filename of the template to render.
|
||||
* @param array $variables
|
||||
* A keyed array of variables that will appear in the output.
|
||||
* @param string $extension
|
||||
* The extension used by the theme engine for template files.
|
||||
*
|
||||
* @return string
|
||||
* The output generated by the template including debug information.
|
||||
*/
|
||||
function _theme_render_template_debug($template_function, $template_file, $variables, $extension) {
|
||||
$output = array(
|
||||
'debug_prefix' => '',
|
||||
'debug_info' => '',
|
||||
'rendered_markup' => call_user_func($template_function, $template_file, $variables),
|
||||
'debug_suffix' => '',
|
||||
);
|
||||
$output['debug_prefix'] .= "\n\n<!-- THEME DEBUG -->";
|
||||
$output['debug_prefix'] .= "\n<!-- CALL: theme('" . check_plain($variables['theme_hook_original']) . "') -->";
|
||||
// If there are theme suggestions, reverse the array so more specific
|
||||
// suggestions are shown first.
|
||||
if (!empty($variables['theme_hook_suggestions'])) {
|
||||
$variables['theme_hook_suggestions'] = array_reverse($variables['theme_hook_suggestions']);
|
||||
}
|
||||
// Add debug output for directly called suggestions like
|
||||
// '#theme' => 'comment__node__article'.
|
||||
if (strpos($variables['theme_hook_original'], '__') !== FALSE) {
|
||||
$derived_suggestions[] = $hook = $variables['theme_hook_original'];
|
||||
while ($pos = strrpos($hook, '__')) {
|
||||
$hook = substr($hook, 0, $pos);
|
||||
$derived_suggestions[] = $hook;
|
||||
}
|
||||
// Get the value of the base hook (last derived suggestion) and append it
|
||||
// to the end of all theme suggestions.
|
||||
$base_hook = array_pop($derived_suggestions);
|
||||
$variables['theme_hook_suggestions'] = array_merge($derived_suggestions, $variables['theme_hook_suggestions']);
|
||||
$variables['theme_hook_suggestions'][] = $base_hook;
|
||||
}
|
||||
if (!empty($variables['theme_hook_suggestions'])) {
|
||||
$current_template = basename($template_file);
|
||||
$suggestions = $variables['theme_hook_suggestions'];
|
||||
// Only add the original theme hook if it wasn't a directly called
|
||||
// suggestion.
|
||||
if (strpos($variables['theme_hook_original'], '__') === FALSE) {
|
||||
$suggestions[] = $variables['theme_hook_original'];
|
||||
}
|
||||
foreach ($suggestions as &$suggestion) {
|
||||
$template = strtr($suggestion, '_', '-') . $extension;
|
||||
$prefix = ($template == $current_template) ? 'x' : '*';
|
||||
$suggestion = $prefix . ' ' . $template;
|
||||
}
|
||||
$output['debug_info'] .= "\n<!-- FILE NAME SUGGESTIONS:\n " . check_plain(implode("\n ", $suggestions)) . "\n-->";
|
||||
}
|
||||
$output['debug_info'] .= "\n<!-- BEGIN OUTPUT from '" . check_plain($template_file) . "' -->\n";
|
||||
$output['debug_suffix'] .= "\n<!-- END OUTPUT from '" . check_plain($template_file) . "' -->\n\n";
|
||||
return implode('', $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables a given list of themes.
|
||||
*
|
||||
@@ -1617,7 +1691,7 @@ function theme_status_messages($variables) {
|
||||
$output .= " </ul>\n";
|
||||
}
|
||||
else {
|
||||
$output .= $messages[0];
|
||||
$output .= reset($messages);
|
||||
}
|
||||
$output .= "</div>\n";
|
||||
}
|
||||
@@ -1690,8 +1764,6 @@ function theme_links($variables) {
|
||||
$output = '';
|
||||
|
||||
if (count($links) > 0) {
|
||||
$output = '';
|
||||
|
||||
// Treat the heading first if it is present to prepend it to the
|
||||
// list of links.
|
||||
if (!empty($heading)) {
|
||||
@@ -2550,6 +2622,9 @@ function template_preprocess_page(&$variables) {
|
||||
if (!isset($variables['page'][$region_key])) {
|
||||
$variables['page'][$region_key] = array();
|
||||
}
|
||||
if ($region_content = drupal_get_region_content($region_key)) {
|
||||
$variables['page'][$region_key][]['#markup'] = $region_content;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up layout variable.
|
||||
|
@@ -116,11 +116,15 @@ function _unicode_check() {
|
||||
if (ini_get('mbstring.encoding_translation') != 0) {
|
||||
return array(UNICODE_ERROR, $t('Multibyte string input conversion in PHP is active and must be disabled. Check the php.ini <em>mbstring.encoding_translation</em> setting. Please refer to the <a href="@url">PHP mbstring documentation</a> for more information.', array('@url' => 'http://www.php.net/mbstring')));
|
||||
}
|
||||
if (ini_get('mbstring.http_input') != 'pass') {
|
||||
return array(UNICODE_ERROR, $t('Multibyte string input conversion in PHP is active and must be disabled. Check the php.ini <em>mbstring.http_input</em> setting. Please refer to the <a href="@url">PHP mbstring documentation</a> for more information.', array('@url' => 'http://www.php.net/mbstring')));
|
||||
}
|
||||
if (ini_get('mbstring.http_output') != 'pass') {
|
||||
return array(UNICODE_ERROR, $t('Multibyte string output conversion in PHP is active and must be disabled. Check the php.ini <em>mbstring.http_output</em> setting. Please refer to the <a href="@url">PHP mbstring documentation</a> for more information.', array('@url' => 'http://www.php.net/mbstring')));
|
||||
// mbstring.http_input and mbstring.http_output are deprecated and empty by
|
||||
// default in PHP 5.6.
|
||||
if (version_compare(PHP_VERSION, '5.6.0') == -1) {
|
||||
if (ini_get('mbstring.http_input') != 'pass') {
|
||||
return array(UNICODE_ERROR, $t('Multibyte string input conversion in PHP is active and must be disabled. Check the php.ini <em>mbstring.http_input</em> setting. Please refer to the <a href="@url">PHP mbstring documentation</a> for more information.', array('@url' => 'http://www.php.net/mbstring')));
|
||||
}
|
||||
if (ini_get('mbstring.http_output') != 'pass') {
|
||||
return array(UNICODE_ERROR, $t('Multibyte string output conversion in PHP is active and must be disabled. Check the php.ini <em>mbstring.http_output</em> setting. Please refer to the <a href="@url">PHP mbstring documentation</a> for more information.', array('@url' => 'http://www.php.net/mbstring')));
|
||||
}
|
||||
}
|
||||
|
||||
// Set appropriate configuration
|
||||
|
@@ -178,7 +178,41 @@ function xmlrpc_message_parse($xmlrpc_message) {
|
||||
xml_set_element_handler($xmlrpc_message->_parser, 'xmlrpc_message_tag_open', 'xmlrpc_message_tag_close');
|
||||
xml_set_character_data_handler($xmlrpc_message->_parser, 'xmlrpc_message_cdata');
|
||||
xmlrpc_message_set($xmlrpc_message);
|
||||
if (!xml_parse($xmlrpc_message->_parser, $xmlrpc_message->message)) {
|
||||
|
||||
// Strip XML declaration.
|
||||
$header = preg_replace('/<\?xml.*?\?'.'>/s', '', substr($xmlrpc_message->message, 0, 100), 1);
|
||||
$xml = trim(substr_replace($xmlrpc_message->message, $header, 0, 100));
|
||||
if ($xml == '') {
|
||||
return FALSE;
|
||||
}
|
||||
// Strip DTD.
|
||||
$header = preg_replace('/^<!DOCTYPE[^>]*+>/i', '', substr($xml, 0, 200), 1);
|
||||
$xml = trim(substr_replace($xml, $header, 0, 200));
|
||||
if ($xml == '') {
|
||||
return FALSE;
|
||||
}
|
||||
// Confirm the XML now starts with a valid root tag. A root tag can end in [> \t\r\n]
|
||||
$root_tag = substr($xml, 0, strcspn(substr($xml, 0, 20), "> \t\r\n"));
|
||||
// Reject a second DTD.
|
||||
if (strtoupper($root_tag) == '<!DOCTYPE') {
|
||||
return FALSE;
|
||||
}
|
||||
if (!in_array($root_tag, array('<methodCall', '<methodResponse', '<fault'))) {
|
||||
return FALSE;
|
||||
}
|
||||
// Skip parsing if there is an unreasonably large number of tags.
|
||||
try {
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadXML($xml);
|
||||
if ($dom->getElementsByTagName('*')->length > variable_get('xmlrpc_message_maximum_tag_count', 30000)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!xml_parse($xmlrpc_message->_parser, $xml)) {
|
||||
return FALSE;
|
||||
}
|
||||
xml_parser_free($xmlrpc_message->_parser);
|
||||
|
@@ -9,7 +9,9 @@
|
||||
* Invokes XML-RPC methods on this server.
|
||||
*
|
||||
* @param array $callbacks
|
||||
* Array of external XML-RPC method names with the callbacks they map to.
|
||||
* Either an associative array of external XML-RPC method names as keys with
|
||||
* the callbacks they map to as values, or a more complex structure
|
||||
* describing XML-RPC callbacks as returned from hook_xmlrpc().
|
||||
*/
|
||||
function xmlrpc_server($callbacks) {
|
||||
$xmlrpc_server = new stdClass();
|
||||
|
Reference in New Issue
Block a user