/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
- * Copyright (c) 2001-2017 *
+ * Copyright (c) 2001-2019 *
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
* *
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
return $local;
}
+/**
+ * Valider qu'une URL d'un document distant est bien distante
+ * et pas une url localhost qui permet d'avoir des infos sur le serveur
+ * inspiree de https://core.trac.wordpress.org/browser/trunk/src/wp-includes/http.php?rev=36435#L500
+ *
+ * @param string $url
+ * @param array $known_hosts
+ * url/hosts externes connus et acceptes
+ * @return false|string
+ * url ou false en cas d'echec
+ */
+function valider_url_distante($url, $known_hosts = array()) {
+ if (!function_exists('protocole_verifier')){
+ include_spip('inc/filtres_mini');
+ }
+
+ if (!protocole_verifier($url, array('http', 'https'))) {
+ return false;
+ }
+
+ $parsed_url = parse_url($url);
+ if (!$parsed_url or empty($parsed_url['host']) ) {
+ return false;
+ }
+
+ if (isset($parsed_url['user']) or isset($parsed_url['pass'])) {
+ return false;
+ }
+
+ if (false !== strpbrk($parsed_url['host'], ':#?[]')) {
+ return false;
+ }
+
+ if (!is_array($known_hosts)) {
+ $known_hosts = array($known_hosts);
+ }
+ $known_hosts[] = $GLOBALS['meta']['adresse_site'];
+ $known_hosts[] = url_de_base();
+ $known_hosts = pipeline('declarer_hosts_distants', $known_hosts);
+
+ $is_known_host = false;
+ foreach ($known_hosts as $known_host) {
+ $parse_known = parse_url($known_host);
+ if ($parse_known
+ and strtolower($parse_known['host']) === strtolower($parsed_url['host'])) {
+ $is_known_host = true;
+ break;
+ }
+ }
+
+ if (!$is_known_host) {
+ $host = trim($parsed_url['host'], '.');
+ if (preg_match('#^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $host)) {
+ $ip = $host;
+ } else {
+ $ip = gethostbyname($host);
+ if ($ip === $host) {
+ // Error condition for gethostbyname()
+ $ip = false;
+ }
+ }
+ if ($ip) {
+ $parts = array_map('intval', explode( '.', $ip ));
+ if (127 === $parts[0] or 10 === $parts[0] or 0 === $parts[0]
+ or ( 172 === $parts[0] and 16 <= $parts[1] and 31 >= $parts[1] )
+ or ( 192 === $parts[0] && 168 === $parts[1] )
+ ) {
+ return false;
+ }
+ }
+ }
+
+ if (empty($parsed_url['port'])) {
+ return $url;
+ }
+
+ $port = $parsed_url['port'];
+ if ($port === 80 or $port === 443 or $port === 8080) {
+ return $url;
+ }
+
+ if ($is_known_host) {
+ foreach ($known_hosts as $known_host) {
+ $parse_known = parse_url($known_host);
+ if ($parse_known
+ and !empty($parse_known['port'])
+ and strtolower($parse_known['host']) === strtolower($parsed_url['host'])
+ and $parse_known['port'] == $port) {
+ return $url;
+ }
+ }
+ }
+
+ return false;
+}
+
/**
* Preparer les donnes pour un POST
* si $donnees est une chaine
$result['page'] = &$res;
$result['length'] = strlen($result['page']);
}
+ $result['status'] = 200; // on a reussi, donc !
}
if (!$result['page']) {
return $result;
if (is_null($http_proxy)) {
$http_proxy = isset($GLOBALS['meta']['http_proxy']) ? $GLOBALS['meta']['http_proxy'] : null;
}
+ // rien a faire si pas de proxy :)
+ if (is_null($http_proxy) or !$http_proxy = trim($http_proxy)) {
+ return '';
+ }
+
if (is_null($http_noproxy)) {
$http_noproxy = isset($GLOBALS['meta']['http_noproxy']) ? $GLOBALS['meta']['http_noproxy'] : null;
}
+ // si pas d'exception, on retourne le proxy
+ if (is_null($http_noproxy) or !$http_noproxy = trim($http_noproxy)) {
+ return $http_proxy;
+ }
+
+ // si le host ou l'un des domaines parents est dans $http_noproxy on fait exception
+ // $http_noproxy peut contenir plusieurs domaines separes par des espaces ou retour ligne
+ $http_noproxy = str_replace("\n", " ", $http_noproxy);
+ $http_noproxy = str_replace("\r", " ", $http_noproxy);
+ $http_noproxy = " $http_noproxy ";
+ $domain = $host;
+ // si le domaine exact www.example.org est dans les exceptions
+ if (strpos($http_noproxy, " $domain ") !== false)
+ return '';
+
+ while (strpos($domain, '.') !== false) {
+ $domain = explode('.', $domain);
+ array_shift($domain);
+ $domain = implode('.', $domain);
+
+ // ou si un domaine parent commencant par un . est dans les exceptions (indiquant qu'il couvre tous les sous-domaines)
+ if (strpos($http_noproxy, " .$domain ") !== false) {
+ return '';
+ }
+ }
- $domain = substr($host, strpos($host, '.'));
-
- return ($http_proxy
- and (strpos(" $http_noproxy ", " $host ") === false
- and (strpos(" $http_noproxy ", " $domain ") === false)))
- ? $http_proxy : '';
+ // ok c'est pas une exception
+ return $http_proxy;
}
$scheme = 'http';
$noproxy = '';
} elseif ($t['scheme'] == 'https') {
- $scheme = 'tls';
- $noproxy = 'tls://';
+ $scheme = 'ssl';
+ $noproxy = 'ssl://';
if (!isset($t['port']) || !($port = $t['port'])) {
$t['port'] = 443;
}
$connect = '';
if ($http_proxy) {
- if (defined('_PROXY_HTTPS_VIA_CONNECT') and $scheme == 'tls') {
+ if (defined('_PROXY_HTTPS_VIA_CONNECT') and in_array($scheme , array('tls','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 == 'tls') ? 'https://' : "$scheme://")
+ $path = (in_array($scheme , array('tls','ssl')) ? 'https://' : "$scheme://")
. (!$user ? '' : "$user@")
. "$host" . (($port != 80) ? ":$port" : '') . $path;
}
$site = isset($GLOBALS['meta']['adresse_site']) ? $GLOBALS['meta']['adresse_site'] : '';
+ $host_port = $host;
+ if ($port != (in_array($scheme , array('tls','ssl')) ? 443 : 80)) {
+ $host_port .= ":$port";
+ }
$req = "$method $path $vers\r\n"
- . "Host: $host\r\n"
+ . "Host: $host_port\r\n"
. 'User-Agent: ' . _INC_DISTANT_USER_AGENT . "\r\n"
. ($refuse_gz ? '' : ('Accept-Encoding: ' . _INC_DISTANT_CONTENT_ENCODING . "\r\n"))
. (!$site ? '' : "Referer: $site/$referer\r\n")