contrib modules security updates

This commit is contained in:
Bachir Soussi Chiadmi
2016-10-13 12:10:40 +02:00
parent ffd758abc9
commit 747127f643
732 changed files with 67976 additions and 23207 deletions

View File

@@ -24,8 +24,10 @@ define('HTTP_REQUEST_PCRE_TAG_ATTRIBUTES', '/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\
class HRCurlException extends Exception {}
/**
* Discover RSS or atom feeds at the given URL. If document in given URL is an
* HTML document, function attempts to discover RSS or Atom feeds.
* Discovers RSS or atom feeds at the given URL.
*
* If document in given URL is an HTML document, function attempts to discover
* RSS or Atom feeds.
*
* @param string $url
* The url of the feed to retrieve.
@@ -36,7 +38,7 @@ class HRCurlException extends Exception {}
* The discovered feed, or FALSE if the URL is not reachable or there was an
* error.
*/
function http_request_get_common_syndication($url, $settings = NULL) {
function http_request_get_common_syndication($url, $settings = array()) {
$accept_invalid_cert = isset($settings['accept_invalid_cert']) ? $settings['accept_invalid_cert'] : FALSE;
$download = http_request_get($url, NULL, NULL, $accept_invalid_cert);
@@ -47,12 +49,12 @@ function http_request_get_common_syndication($url, $settings = NULL) {
return FALSE;
}
// Drop the data into a seperate variable so all manipulations of the html
// Drop the data into a separate variable so all manipulations of the html
// will not effect the actual object that exists in the static cache.
// @see http_request_get.
$downloaded_string = $download->data;
// If this happens to be a feed then just return the url.
if (http_request_is_feed($download->headers['content-type'], $downloaded_string)) {
if (isset($download->headers['content-type']) && http_request_is_feed($download->headers['content-type'], $downloaded_string)) {
return $url;
}
@@ -77,11 +79,13 @@ function http_request_get_common_syndication($url, $settings = NULL) {
* If the URL uses authentication, supply the password.
* @param bool $accept_invalid_cert
* Whether to accept invalid certificates.
* @param integer $timeout
* Timeout in seconds to wait for an HTTP get request to finish.
*
* @return stdClass
* An object that describes the data downloaded from $url.
*/
function http_request_get($url, $username = NULL, $password = NULL, $accept_invalid_cert = FALSE) {
function http_request_get($url, $username = NULL, $password = NULL, $accept_invalid_cert = FALSE, $timeout = NULL) {
// Intra-pagedownload cache, avoid to download the same content twice within
// one page download (it's possible, compatible and parse calls).
static $download_cache = array();
@@ -89,12 +93,15 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
return $download_cache[$url];
}
// Determine request timeout.
$request_timeout = !empty($timeout) ? $timeout : variable_get('http_request_timeout', 30);
if (!$username && valid_url($url, TRUE)) {
// Handle password protected feeds.
$url_parts = parse_url($url);
if (!empty($url_parts['user'])) {
$password = $url_parts['pass'];
$username = $url_parts['user'];
$password = urldecode($url_parts['pass']);
$username = urldecode($url_parts['user']);
}
}
@@ -103,7 +110,7 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
// Only download and parse data if really needs refresh.
// Based on "Last-Modified" and "If-Modified-Since".
$headers = array();
if ($cache = cache_get('feeds_http_download_' . md5($url))) {
if ($cache = http_request_get_cache($url)) {
$last_result = $cache->data;
$last_headers = array_change_key_case($last_result->headers);
@@ -134,6 +141,7 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
if ($curl) {
$headers[] = 'User-Agent: Drupal (+http://drupal.org/)';
$result = new stdClass();
$result->headers = array();
// Parse the URL and make sure we can handle the schema.
// cURL can only support either http:// or https://.
@@ -149,6 +157,7 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
case 'https':
// Valid scheme.
break;
default:
$result->error = 'invalid schema ' . $uri['scheme'];
$result->code = -1003;
@@ -168,9 +177,26 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
curl_setopt($download, CURLOPT_HEADER, TRUE);
curl_setopt($download, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($download, CURLOPT_ENCODING, '');
curl_setopt($download, CURLOPT_TIMEOUT, variable_get('http_request_timeout', 30));
curl_setopt($download, CURLOPT_TIMEOUT, $request_timeout);
$proxy_server = variable_get('proxy_server');
if ($proxy_server && _drupal_http_use_proxy($uri['host'])) {
curl_setopt($download, CURLOPT_PROXY, $proxy_server);
curl_setopt($download, CURLOPT_PROXYPORT, variable_get('proxy_port', 8080));
// Proxy user/password.
if ($proxy_username = variable_get('proxy_username')) {
$username_password = $proxy_username . ':' . variable_get('proxy_password', '');
curl_setopt($download, CURLOPT_PROXYUSERPWD, $username_password);
curl_setopt($download, CURLOPT_PROXYAUTH, variable_get('proxy_auth_method', CURLAUTH_BASIC));
}
}
if ($accept_invalid_cert) {
curl_setopt($download, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($download, CURLOPT_SSL_VERIFYHOST, 0);
}
$header = '';
$data = curl_exec($download);
@@ -179,18 +205,35 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
t('cURL error (@code) @error for @url', array(
'@code' => curl_errno($download),
'@error' => curl_error($download),
'@url' => $url
'@url' => $url,
)), curl_errno($download)
);
}
// When using a proxy, remove extra data from the header which is not
// considered by CURLINFO_HEADER_SIZE (possibly cURL bug).
// This data is only added when to HTTP header when working with a proxy.
// Example string added: <HTTP/1.0 200 Connection established\r\n\r\n>
// This was fixed in libcurl version 7.30.0 (0x71e00) (April 12, 2013),
// so this workaround only removes the proxy-added headers if we are using
// an older version of libcurl.
$curl_ver = curl_version();
if ($proxy_server && $curl_ver['version_number'] < 0x71e00 && _drupal_http_use_proxy($uri['host'])) {
$http_header_break = "\r\n\r\n";
$response = explode($http_header_break, $data);
if (count($response) > 2) {
$data = substr($data, strlen($response[0] . $http_header_break), strlen($data));
}
}
$header_size = curl_getinfo($download, CURLINFO_HEADER_SIZE);
$header = substr($data, 0, $header_size - 1);
$result->data = substr($data, $header_size);
$headers = preg_split("/(\r\n){2}/", $header);
$header_lines = preg_split("/\r\n|\n|\r/", end($headers));
$result->headers = array();
array_shift($header_lines); // skip HTTP response status
// Skip HTTP response status.
array_shift($header_lines);
while ($line = trim(array_shift($header_lines))) {
list($header, $value) = explode(':', $line, 2);
@@ -212,7 +255,8 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
}
}
else {
$result = drupal_http_request($url, array('headers' => $headers, 'timeout' => variable_get('http_request_timeout', 30)));
$result = drupal_http_request($url, array('headers' => $headers, 'timeout' => $request_timeout));
$result->headers = isset($result->headers) ? $result->headers : array();
}
$result->code = isset($result->code) ? $result->code : 200;
@@ -227,13 +271,13 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
else {
// It's a tragedy, this file must exist and contain good data.
// In this case, clear cache and repeat.
cache_clear_all('feeds_http_download_' . md5($url), 'cache');
return http_request_get($url, $username, $password);
http_request_clear_cache($url);
return http_request_get($url, $username, $password, $accept_invalid_cert, $request_timeout);
}
}
// Set caches.
cache_set('feeds_http_download_' . md5($url), $result);
http_request_set_cache($url, $result);
$download_cache[$url] = $result;
return $result;
@@ -243,7 +287,7 @@ function http_request_get($url, $username = NULL, $password = NULL, $accept_inva
* Decides if it's possible to use cURL or not.
*
* @return bool
* TRUE if curl is available, FALSE otherwise.
* TRUE if cURL may be used, FALSE otherwise.
*/
function http_request_use_curl() {
// Allow site administrators to choose to not use cURL.
@@ -251,29 +295,67 @@ function http_request_use_curl() {
return FALSE;
}
// Check availability of cURL on the system.
$basedir = ini_get("open_basedir");
return function_exists('curl_init') && !ini_get('safe_mode') && empty($basedir);
// Check that the PHP cURL extension has been enabled.
if (!extension_loaded('curl')) {
return FALSE;
}
// cURL below PHP 5.6.0 must not have open_basedir or safe_mode enabled.
if (version_compare(PHP_VERSION, '5.6.0', '<')) {
return !ini_get('safe_mode') && !ini_get('open_basedir');
}
// cURL in PHP 5.6.0 and above re-enables CURLOPT_FOLLOWLOCATION with
// open_basedir so there is no need to check for this.
return TRUE;
}
/**
* Clear cache for a specific URL.
*
* @param string $url
* The URL to clear.
*/
function http_request_clear_cache($url) {
cache_clear_all('feeds_http_download_' . md5($url), 'cache');
cache_clear_all(hash('sha256', $url), 'cache_feeds_http');
}
/**
* Gets the cache for a specific URL.
*
* @param string $url
* The URL to find the cached item.
*
* @return object|false
* The cache or FALSE on failure.
*/
function http_request_get_cache($url) {
return cache_get(hash('sha256', $url), 'cache_feeds_http');
}
/**
* Sets the cache for a specific URL.
*
* @param string $url
* The URL to cache.
* @param stdClass $result
* The result of the HTTP request.
*/
function http_request_set_cache($url, stdClass $result) {
cache_set(hash('sha256', $url), $result, 'cache_feeds_http');
}
/**
* Returns if the provided $content_type is a feed.
*
* @param string $content_type
* The Content-Type header.
* The Content-Type header.
*
* @param string $data
* The actual data from the http request.
* The actual data from the http request.
*
* @return bool
* Returns TRUE if this is a parsable feed.
* Returns TRUE if this is a parsable feed.
*/
function http_request_is_feed($content_type, $data) {
$pos = strpos($content_type, ';');
@@ -294,10 +376,10 @@ function http_request_is_feed($content_type, $data) {
* Finds potential feed tags in the HTML document.
*
* @param string $html
* The html string to search.
* The html string to search.
*
* @return array
* An array of href to feeds.
* An array of href to feeds.
*/
function http_request_find_feeds($html) {
$matches = array();
@@ -313,7 +395,11 @@ function http_request_find_feeds($html) {
preg_match_all(HTTP_REQUEST_PCRE_TAG_ATTRIBUTES, $link_tag, $attributes, PREG_SET_ORDER);
foreach ($attributes as $attribute) {
// Find the key value pairs, attribute[1] is key and attribute[2] is the
// value.
// value. However, if the link tag used single quotes, the value might
// be in attribute[3] instead.
if (empty($attribute[2])) {
$attribute[2] = $attribute[3];
}
if (!empty($attribute[1]) && !empty($attribute[2])) {
$candidate[drupal_strtolower($attribute[1])] = drupal_strtolower(decode_entities($attribute[2]));
}
@@ -355,27 +441,48 @@ function http_request_create_absolute_url($url, $base_url) {
// Produces variables $scheme, $host, $user, $pass, $path, $query and
// $fragment.
$parsed_url = parse_url($base_url);
if ($parsed_url === FALSE) {
// Invalid $base_url.
return FALSE;
}
$path = dirname($parsed_url['path']);
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
if (strlen($path) > 0 && substr($path, -1) != '/') {
// Path ends not with '/', so remove all before previous '/'.
$path = dirname($path);
}
// Adding to the existing path.
$cparts = array();
if ($url{0} == '/') {
$cparts = array_filter(explode("/", $url));
}
else {
// Backtracking from the existing path.
$cparts = array_merge(array_filter(explode("/", $path)), array_filter(explode("/", $url)));
foreach ($cparts as $i => $part) {
if ($part == '.') {
$cparts[$i] = NULL;
}
if ($part == '..') {
$cparts[$i - 1] = NULL;
$cparts[$i] = NULL;
}
}
$cparts = array_filter($cparts);
$path_cparts = array_filter(explode("/", $path));
$url_cparts = array_filter(explode("/", $url));
$cparts = array_merge($path_cparts, $url_cparts);
}
$remove_parts = 0;
// Start from behind.
$reverse_cparts = array_reverse($cparts);
foreach ($reverse_cparts as $i => &$part) {
if ($part == '.') {
$part = NULL;
}
elseif ($part == '..') {
$part = NULL;
$remove_parts++;
}
elseif ($remove_parts > 0) {
// If the current part isn't "..", and we had ".." before, then delete
// the part.
$part = NULL;
$remove_parts--;
}
}
$cparts = array_filter(array_reverse($reverse_cparts));
$path = implode("/", $cparts);
// Build the prefix to the path.