diff --git a/ecrire/inc/distant.php b/ecrire/inc/distant.php index 0683aa26c5cd25184ffaaa2acaf3be56d4d1db1f..b4fbf8b582b49838c3b3c6e96517ed1f3e167a75 100644 --- a/ecrire/inc/distant.php +++ b/ecrire/inc/distant.php @@ -12,7 +12,7 @@ /** * Ce fichier gère l'obtention de données distantes - * + * * @package SPIP\Core\Distant **/ if (!defined('_ECRIRE_INC_VERSION')) return; @@ -22,7 +22,7 @@ if (!defined('_INC_DISTANT_CONTENT_ENCODING')) define('_INC_DISTANT_CONTENT_ENCO if (!defined('_INC_DISTANT_USER_AGENT')) define('_INC_DISTANT_USER_AGENT', 'SPIP-' . $GLOBALS['spip_version_affichee'] . " (" . $GLOBALS['home_server'] . ")"); if (!defined('_INC_DISTANT_MAX_SIZE')) define('_INC_DISTANT_MAX_SIZE',2097152); -define('_REGEXP_COPIE_LOCALE', ',' . +define('_REGEXP_COPIE_LOCALE', ',' . preg_replace('@^https?:@', 'https?:', (isset($GLOBALS['meta']["adresse_site"]) ? $GLOBALS['meta']["adresse_site"] : '')) . "/?spip.php[?]action=acceder_document.*file=(.*)$,"); @@ -295,13 +295,20 @@ function recuperer_url($url, $options = array()){ if (!$fopen) { $res = recuperer_entetes_complets($handle, $options['if_modified_since']); if(!$res) { + fclose($handle); + $t = @parse_url($url); + $host = $t['host']; // Chinoisierie inexplicable pour contrer // les actions liberticides de l'empire du milieu - if ($res = @file_get_contents($url)){ - $result['status'] = 200; - $result['page'] = $res; - return $result; + if (!need_proxy($host) + AND $res = @file_get_contents($url)){ + $res = array( + 'status' => 200, + 'page' => $res, + ); } + else + return false; } elseif ($res['location'] AND $options['follow_location']){ $options['follow_location']--; @@ -315,9 +322,14 @@ function recuperer_url($url, $options = array()){ spip_log("HTTP status ".$res['status']." pour $url"); } $result['status'] = $res['status']; - $result['headers'] = $res['headers']; - $result['last_modified'] = $res['last_modified']; - $result['location'] = $res['location']; + if (isset($res['headers'])) + $result['headers'] = $res['headers']; + if (isset($res['last_modified'])) + $result['last_modified'] = $res['last_modified']; + if (isset($res['location'])) + $result['location'] = $res['location']; + if (isset($res['page'])) + $result['page'] = $res['page']; } // on ne veut que les entetes @@ -332,27 +344,30 @@ function recuperer_url($url, $options = array()){ if (preg_match(",\bContent-Encoding: .*gzip,is", $result['headers'])) $gz = (_DIR_TMP . md5(uniqid(mt_rand())) . '.tmp.gz'); - $res = recuperer_body($handle, $options['taille_max'], $gz ? $gz : $copy); - fclose($handle); - if ($copy){ - $result['length'] = $res; - $result['file'] = $copy; - } - elseif($res) { - $result['page'] = &$res; - $result['length'] = strlen($result['page']); - - // Decompresser au besoin - if ($gz){ - $result['page'] = implode('', gzfile($gz)); - supprimer_fichier($gz); + if (!$result['page']){ + $res = recuperer_body($handle, $options['taille_max'], $gz ? $gz : $copy); + fclose($handle); + if ($copy){ + $result['length'] = $res; + $result['file'] = $copy; } + elseif($res) { + $result['page'] = &$res; + $result['length'] = strlen($result['page']); + } + if (!$result['page']) + return $result; - // Faut-il l'importer dans notre charset local ? - if ($options['transcoder']){ - include_spip('inc/charsets'); - $result['page'] = transcoder_page($result['page'], $result['headers']); - } + // Decompresser au besoin + if ($gz){ + $result['page'] = implode('', gzfile($gz)); + supprimer_fichier($gz); + } + + // Faut-il l'importer dans notre charset local ? + if ($options['transcoder']){ + include_spip('inc/charsets'); + $result['page'] = transcoder_page($result['page'], $result['headers']); } return $result; @@ -1010,7 +1025,8 @@ function init_http($method, $url, $refuse_gz = false, $referer = '', $datas = "" $f = lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $refuse_gz, $referer, $datas, $vers, $date); if (!$f){ // fallback : fopen - if (!_request('tester_proxy')){ + if (!need_proxy($host) + AND !_request('tester_proxy')){ $f = @fopen($url, "rb"); spip_log("connexion vers $url par simple fopen"); $fopen = true; @@ -1059,10 +1075,19 @@ function lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $ $http_proxy = need_proxy($host); if ($user) $user = urlencode($user[0]) . ":" . urlencode($user[1]); + $connect = ""; if ($http_proxy){ - $path = (($scheme=='ssl') ? 'https://' : "$scheme://") - . (!$user ? '' : "$user@") - . "$host" . (($port!=80) ? ":$port" : "") . $path; + if (defined('_PROXY_HTTPS_VIA_CONNECT') AND $scheme=="ssl"){ + $path_host = (!$user ? '' : "$user@") . $host . (($port!=80) ? ":$port" : ""); + $connect = "CONNECT " .$path_host." $vers\r\n" + ."Host: $path_host\r\n" + ."Proxy-Connection: Keep-Alive\r\n"; + } + else { + $path = (($scheme=='ssl') ? 'https://' : "$scheme://") + . (!$user ? '' : "$user@") + . "$host" . (($port!=80) ? ":$port" : "") . $path; + } $t2 = @parse_url($http_proxy); $first_host = $t2['host']; if (!($port = $t2['port'])) $port = 80; @@ -1072,9 +1097,34 @@ function lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $ else $first_host = $noproxy . $host; - $f = @fsockopen($first_host, $port); - spip_log("Recuperer $path sur $first_host:$port par $f"); - if (!$f) return false; + if ($connect){ + $streamContext = stream_context_create(array('ssl' => array('verify_peer' => false, 'allow_self_signed' => true))); + $f = @stream_socket_client("tcp://$first_host:$port", $nError, $sError, 10, STREAM_CLIENT_CONNECT, $streamContext); + spip_log("Recuperer $path sur $first_host:$port par $f (via CONNECT)","connect"); + if (!$f) return false; + stream_set_timeout($f, 10); + + fputs($f, $connect); + fputs($f, "\r\n"); + $res = fread($f, 1024); + if (!$res + OR !count($res = explode(' ',$res)) + OR $res[1]!=='200'){ + spip_log("Echec CONNECT sur $first_host:$port","connect"._LOG_INFO_IMPORTANTE); + fclose($f); + return false; + } + // important, car sinon on lit trop vite et les donnees ne sont pas encore dispo + stream_set_blocking($f, true); + // envoyer le handshake + stream_socket_enable_crypto($f, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT); + spip_log("OK CONNECT sur $first_host:$port","connect"); + } + else { + $f = @fsockopen($first_host, $port); + spip_log("Recuperer $path sur $first_host:$port par $f"); + if (!$f) return false; + } $site = isset($GLOBALS['meta']["adresse_site"]) ? $GLOBALS['meta']["adresse_site"] : ''; @@ -1094,4 +1144,3 @@ function lance_requete($method, $scheme, $user, $host, $path, $port, $noproxy, $ return $f; } -?>