View source
<?php
define('HTTP_REQUEST_PCRE_LINK_TAG', '/<link((?:[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]+[^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x2F\\x3E][^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x2F\\x3D\\x3E]*(?:[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]*=[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x22\\x27\\x3E][^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x3E]*)?))?)*)[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]*(>(.*)<\\/link>|(\\/)?>)/si');
define('HTTP_REQUEST_PCRE_TAG_ATTRIBUTES', '/[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]+([^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x2F\\x3E][^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x2F\\x3D\\x3E]*)(?:[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]*=[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x22\\x27\\x3E][^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x3E]*)?))?/');
class HRCurlException extends Exception {
}
function http_request_get_common_syndication($url, $settings = NULL) {
$accept_invalid_cert = isset($settings['accept_invalid_cert']) ? $settings['accept_invalid_cert'] : FALSE;
$download = http_request_get($url, NULL, NULL, $accept_invalid_cert);
if ($download->code != 200) {
return FALSE;
}
$downloaded_string = $download->data;
if (http_request_is_feed($download->headers['content-type'], $downloaded_string)) {
return $url;
}
$discovered_feeds = http_request_find_feeds($downloaded_string);
foreach ($discovered_feeds as $feed_url) {
$absolute = http_request_create_absolute_url($feed_url, $url);
if (!empty($absolute)) {
return $absolute;
}
}
}
function http_request_get($url, $username = NULL, $password = NULL, $accept_invalid_cert = FALSE, $timeout = NULL) {
static $download_cache = array();
if (isset($download_cache[$url])) {
return $download_cache[$url];
}
$request_timeout = !empty($timeout) ? $timeout : variable_get('http_request_timeout', 30);
if (!$username && valid_url($url, TRUE)) {
$url_parts = parse_url($url);
if (!empty($url_parts['user'])) {
$password = $url_parts['pass'];
$username = $url_parts['user'];
}
}
$curl = http_request_use_curl();
$headers = array();
if ($cache = cache_get('feeds_http_download_' . md5($url))) {
$last_result = $cache->data;
$last_headers = array_change_key_case($last_result->headers);
if (!empty($last_headers['etag'])) {
if ($curl) {
$headers[] = 'If-None-Match: ' . $last_headers['etag'];
}
else {
$headers['If-None-Match'] = $last_headers['etag'];
}
}
if (!empty($last_headers['last-modified'])) {
if ($curl) {
$headers[] = 'If-Modified-Since: ' . $last_headers['last-modified'];
}
else {
$headers['If-Modified-Since'] = $last_headers['last-modified'];
}
}
if (!empty($username) && !$curl) {
$headers['Authorization'] = 'Basic ' . base64_encode("{$username}:{$password}");
}
}
$url = strtr($url, array(
'feed://' => 'http://',
'webcal://' => 'http://',
));
if ($curl) {
$headers[] = 'User-Agent: Drupal (+http://drupal.org/)';
$result = new stdClass();
$result->headers = array();
$uri = parse_url($url);
if (!isset($uri['scheme'])) {
$result->error = 'missing schema';
$result->code = -1002;
}
else {
switch ($uri['scheme']) {
case 'http':
case 'https':
break;
default:
$result->error = 'invalid schema ' . $uri['scheme'];
$result->code = -1003;
break;
}
}
if (empty($result->error)) {
$download = curl_init($url);
curl_setopt($download, CURLOPT_FOLLOWLOCATION, TRUE);
if (!empty($username)) {
curl_setopt($download, CURLOPT_USERPWD, "{$username}:{$password}");
curl_setopt($download, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
}
curl_setopt($download, CURLOPT_HTTPHEADER, $headers);
curl_setopt($download, CURLOPT_HEADER, TRUE);
curl_setopt($download, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($download, CURLOPT_ENCODING, '');
curl_setopt($download, CURLOPT_TIMEOUT, $request_timeout);
if ($accept_invalid_cert) {
curl_setopt($download, CURLOPT_SSL_VERIFYPEER, 0);
}
$header = '';
$data = curl_exec($download);
if (curl_error($download)) {
throw new HRCurlException(t('cURL error (@code) @error for @url', array(
'@code' => curl_errno($download),
'@error' => curl_error($download),
'@url' => $url,
)), curl_errno($download));
}
$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));
array_shift($header_lines);
while ($line = trim(array_shift($header_lines))) {
list($header, $value) = explode(':', $line, 2);
$header = strtolower($header);
if (isset($result->headers[$header]) && $header == 'set-cookie') {
$result->headers[$header] .= ',' . trim($value);
}
else {
$result->headers[$header] = trim($value);
}
}
$result->code = curl_getinfo($download, CURLINFO_HTTP_CODE);
curl_close($download);
}
}
else {
$result = drupal_http_request($url, $headers, 'GET', NULL, 3, $request_timeout);
$result->headers = isset($result->headers) ? $result->headers : array();
}
$result->code = isset($result->code) ? $result->code : 200;
if ($result->code == 304) {
if (isset($last_result)) {
$last_result->from_cache = TRUE;
return $last_result;
}
else {
cache_clear_all('feeds_http_download_' . md5($url), 'cache');
return http_request_get($url, $username, $password, $accept_invalid_cert, $request_timeout);
}
}
cache_set('feeds_http_download_' . md5($url), $result);
$download_cache[$url] = $result;
return $result;
}
function http_request_use_curl() {
if (variable_get('feeds_never_use_curl', FALSE)) {
return FALSE;
}
$basedir = ini_get("open_basedir");
return function_exists('curl_init') && !ini_get('safe_mode') && empty($basedir);
}
function http_request_clear_cache($url) {
cache_clear_all('feeds_http_download_' . md5($url), 'cache');
}
function http_request_is_feed($content_type, $data) {
$pos = strpos($content_type, ';');
if ($pos !== FALSE) {
$content_type = substr($content_type, 0, $pos);
}
$content_type = strtolower($content_type);
if (strpos($content_type, 'xml') !== FALSE) {
return TRUE;
}
return FALSE;
}
function http_request_find_feeds($html) {
$matches = array();
preg_match_all(HTTP_REQUEST_PCRE_LINK_TAG, $html, $matches);
$links = $matches[1];
$valid_links = array();
foreach ($links as $link_tag) {
$attributes = array();
$candidate = array();
preg_match_all(HTTP_REQUEST_PCRE_TAG_ATTRIBUTES, $link_tag, $attributes, PREG_SET_ORDER);
foreach ($attributes as $attribute) {
if (!empty($attribute[1]) && !empty($attribute[2])) {
$candidate[drupal_strtolower($attribute[1])] = drupal_strtolower(decode_entities($attribute[2]));
}
}
if (isset($candidate['rel']) && $candidate['rel'] == 'alternate') {
if (isset($candidate['href']) && isset($candidate['type']) && strpos($candidate['type'], 'xml') !== FALSE) {
$valid_links[] = $candidate['href'];
}
}
}
return $valid_links;
}
function http_request_create_absolute_url($url, $base_url) {
$url = trim($url);
if (valid_url($url, TRUE)) {
return $url;
}
if (valid_url($url, FALSE)) {
$parsed_url = parse_url($base_url);
$path = dirname($parsed_url['path']);
if ($url[0] == '/') {
$cparts = array_filter(explode("/", $url));
}
else {
$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 = implode("/", $cparts);
$absolute_url = '';
if (isset($parsed_url['scheme'])) {
$absolute_url = $parsed_url['scheme'] . '://';
}
if (isset($parsed_url['user'])) {
$absolute_url .= $parsed_url['user'];
if (isset($pass)) {
$absolute_url .= ':' . $parsed_url['pass'];
}
$absolute_url .= '@';
}
if (isset($parsed_url['host'])) {
$absolute_url .= $parsed_url['host'] . '/';
}
$absolute_url .= $path;
if (valid_url($absolute_url, TRUE)) {
return $absolute_url;
}
}
return FALSE;
}