]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - application/HttpUtils.php
Extract the title/charset during page download, and check content type
[github/shaarli/Shaarli.git] / application / HttpUtils.php
index 27a39d3df223be0f457e8f3966a5b1bd7db7aefd..2edf5ce2df74bcb39fd5a1ce15c401302ff666c1 100644 (file)
@@ -3,9 +3,11 @@
  * GET an HTTP URL to retrieve its content
  * Uses the cURL library or a fallback method 
  *
- * @param string $url      URL to get (http://...)
- * @param int    $timeout  network timeout (in seconds)
- * @param int    $maxBytes maximum downloaded bytes (default: 4 MiB)
+ * @param string          $url               URL to get (http://...)
+ * @param int             $timeout           network timeout (in seconds)
+ * @param int             $maxBytes          maximum downloaded bytes (default: 4 MiB)
+ * @param callable|string $curlWriteFunction Optional callback called during the download (cURL CURLOPT_WRITEFUNCTION).
+ *                                           Can be used to add download conditions on the headers (response code, content type, etc.).
  *
  * @return array HTTP response headers, downloaded content
  *
@@ -29,7 +31,7 @@
  * @see http://stackoverflow.com/q/9183178
  * @see http://stackoverflow.com/q/1462720
  */
-function get_http_response($url, $timeout = 30, $maxBytes = 4194304)
+function get_http_response($url, $timeout = 30, $maxBytes = 4194304, $curlWriteFunction = null)
 {
     $urlObj = new Url($url);
     $cleanUrl = $urlObj->idnToAscii();
@@ -75,6 +77,10 @@ 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_NOPROGRESS,        false);
@@ -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,33 @@ 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'];
+            }
+
+            if (($scheme == 'http' && $port != '80')
+                || ($scheme == 'https' && $port != '443')
+            ) {
+                $port = ':' . $port;
+            } else {
+                $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 {
-                $port = ':' . $server['HTTP_X_FORWARDED_PORT'];
+                $host = $server['HTTP_X_FORWARDED_HOST'];
             }
+        } else {
+            $host = $server['SERVER_NAME'];
         }
 
-        return $scheme.'://'.$server['SERVER_NAME'].$port;
+        return $scheme.'://'.$host.$port;
     }
 
     // SSL detection
@@ -355,3 +381,57 @@ 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);
+}
+
+/**
+ * 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']);
+}