X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=application%2FHttpUtils.php;h=e9282506188f4d19969e9a49ac27664171c79938;hb=62f5a7581380da7885025498de10e9a20c45b358;hp=27a39d3df223be0f457e8f3966a5b1bd7db7aefd;hpb=d0d3623172f47006607cf16dfb68f1ac394dd2cc;p=github%2Fshaarli%2FShaarli.git diff --git a/application/HttpUtils.php b/application/HttpUtils.php index 27a39d3d..e9282506 100644 --- a/application/HttpUtils.php +++ b/application/HttpUtils.php @@ -1,11 +1,13 @@ idnToAscii(); @@ -75,8 +77,12 @@ function get_http_response($url, $timeout = 30, $maxBytes = 4194304) curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_USERAGENT, $userAgent); + if (is_callable($curlWriteFunction)) { + curl_setopt($ch, CURLOPT_WRITEFUNCTION, $curlWriteFunction); + } + // Max download size management - curl_setopt($ch, CURLOPT_BUFFERSIZE, 1024); + curl_setopt($ch, CURLOPT_BUFFERSIZE, 1024*16); curl_setopt($ch, CURLOPT_NOPROGRESS, false); curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function($arg0, $arg1, $arg2, $arg3, $arg4 = 0) use ($maxBytes) @@ -122,7 +128,7 @@ function get_http_response($url, $timeout = 30, $maxBytes = 4194304) $content = substr($response, $headSize); $headers = array(); foreach (preg_split('~[\r\n]+~', $rawHeadersLastRedir) as $line) { - if (empty($line) or ctype_space($line)) { + if (empty($line) || ctype_space($line)) { continue; } $splitLine = explode(': ', $line, 2); @@ -297,13 +303,40 @@ function server_url($server) // Keep forwarded port if (strpos($server['HTTP_X_FORWARDED_PORT'], ',') !== false) { $ports = explode(',', $server['HTTP_X_FORWARDED_PORT']); - $port = ':' . trim($ports[0]); + $port = trim($ports[0]); + } else { + $port = $server['HTTP_X_FORWARDED_PORT']; + } + + // This is a workaround for proxies that don't forward the scheme properly. + // Connecting over port 443 has to be in HTTPS. + // See https://github.com/shaarli/Shaarli/issues/1022 + if ($port == '443') { + $scheme = 'https'; + } + + if (($scheme == 'http' && $port != '80') + || ($scheme == 'https' && $port != '443') + ) { + $port = ':' . $port; } else { - $port = ':' . $server['HTTP_X_FORWARDED_PORT']; + $port = ''; } } - return $scheme.'://'.$server['SERVER_NAME'].$port; + if (isset($server['HTTP_X_FORWARDED_HOST'])) { + // Keep forwarded host + if (strpos($server['HTTP_X_FORWARDED_HOST'], ',') !== false) { + $hosts = explode(',', $server['HTTP_X_FORWARDED_HOST']); + $host = trim($hosts[0]); + } else { + $host = $server['HTTP_X_FORWARDED_HOST']; + } + } else { + $host = $server['SERVER_NAME']; + } + + return $scheme.'://'.$host.$port; } // SSL detection @@ -355,3 +388,88 @@ function page_url($server) } return index_url($server); } + +/** + * Retrieve the initial IP forwarded by the reverse proxy. + * + * Inspired from: https://github.com/zendframework/zend-http/blob/master/src/PhpEnvironment/RemoteAddress.php + * + * @param array $server $_SERVER array which contains HTTP headers. + * @param array $trustedIps List of trusted IP from the configuration. + * + * @return string|bool The forwarded IP, or false if none could be extracted. + */ +function getIpAddressFromProxy($server, $trustedIps) +{ + $forwardedIpHeader = 'HTTP_X_FORWARDED_FOR'; + if (empty($server[$forwardedIpHeader])) { + return false; + } + + $ips = preg_split('/\s*,\s*/', $server[$forwardedIpHeader]); + $ips = array_diff($ips, $trustedIps); + if (empty($ips)) { + return false; + } + + return array_pop($ips); +} + + +/** + * Return an identifier based on the advertised client IP address(es) + * + * This aims at preventing session hijacking from users behind the same proxy + * by relying on HTTP headers. + * + * See: + * - https://secure.php.net/manual/en/reserved.variables.server.php + * - https://stackoverflow.com/questions/3003145/how-to-get-the-client-ip-address-in-php + * - https://stackoverflow.com/questions/12233406/preventing-session-hijacking + * - https://stackoverflow.com/questions/21354859/trusting-x-forwarded-for-to-identify-a-visitor + * + * @param array $server The $_SERVER array + * + * @return string An identifier based on client IP address information + */ +function client_ip_id($server) +{ + $ip = $server['REMOTE_ADDR']; + + if (isset($server['HTTP_X_FORWARDED_FOR'])) { + $ip = $ip . '_' . $server['HTTP_X_FORWARDED_FOR']; + } + if (isset($server['HTTP_CLIENT_IP'])) { + $ip = $ip . '_' . $server['HTTP_CLIENT_IP']; + } + return $ip; +} + + +/** + * Returns true if Shaarli's currently browsed in HTTPS. + * Supports reverse proxies (if the headers are correctly set). + * + * @param array $server $_SERVER. + * + * @return bool true if HTTPS, false otherwise. + */ +function is_https($server) +{ + + if (isset($server['HTTP_X_FORWARDED_PORT'])) { + // Keep forwarded port + if (strpos($server['HTTP_X_FORWARDED_PORT'], ',') !== false) { + $ports = explode(',', $server['HTTP_X_FORWARDED_PORT']); + $port = trim($ports[0]); + } else { + $port = $server['HTTP_X_FORWARDED_PORT']; + } + + if ($port == '443') { + return true; + } + } + + return ! empty($server['HTTPS']); +}