From 066ef1d7db079fe9617ab2108b5bce2ed068b6eb Mon Sep 17 00:00:00 2001 From: logmanoriginal Date: Sat, 21 Jul 2018 17:27:38 +0200 Subject: [PATCH] [contents] Add Cloudflare challenge detection Adds detection for servers responding with Cloudflare challenges, throwing a server error if detected: "The server responded with a Cloudflare challenge, which is not supported by RSS-Bridge! If this error persists longer than a week, please consider opening an issue on GitHub!" This is supposed to support maintainers to identify broken bridges for sites with Cloudflare enabled permanently. It doesn't circumvent the protection in any form or shape! The Cloudflare challenge is detected by analyzing the last response header received from the server. If the HTTP Code is not 200 (OK) and the server name contains 'cloudflare' ('Server: cloudflare'), RSS-Bridge assumes the server responded with a challenge. The header parsing is based on https://stackoverflow.com/a/18682872 --- lib/contents.php | 64 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/lib/contents.php b/lib/contents.php index 416fb7d..2c5944b 100644 --- a/lib/contents.php +++ b/lib/contents.php @@ -21,15 +21,36 @@ function getContents($url, $header = array(), $opts = array()){ curl_setopt($ch, CURLOPT_PROXY, PROXY_URL); } - $content = curl_exec($ch); + // We always want the resonse header as part of the data! + curl_setopt($ch, CURLOPT_HEADER, true); + + $data = curl_exec($ch); $curlError = curl_error($ch); $curlErrno = curl_errno($ch); - curl_close($ch); - if($content === false) + if($data === false) debugMessage('Cant\'t download ' . $url . ' cUrl error: ' . $curlError . ' (' . $curlErrno . ')'); - return $content; + $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); + $header = substr($data, 0, $headerSize); + $headers = parseResponseHeader($header); + $finalHeader = end($headers); + + error_log(json_encode($headers)); + + if(array_key_exists('http_code', $finalHeader) + && strpos($finalHeader['http_code'], '200') === false + && array_key_exists('Server', $finalHeader) + && strpos($finalHeader['Server'], 'cloudflare') !== false) { + returnServerError(<<< EOD +The server responded with a Cloudflare challenge, which is not supported by RSS-Bridge!
+If this error persists longer than a week, please consider opening an issue on GitHub! +EOD + ); + } + + curl_close($ch); + return substr($data, $headerSize); } function getSimpleHTMLDOM($url, @@ -98,3 +119,38 @@ $defaultSpanText = DEFAULT_SPAN_TEXT){ $defaultBRText, $defaultSpanText); } + +/** + * Parses the provided response header into an associative array + * + * Based on https://stackoverflow.com/a/18682872 + */ +function parseResponseHeader($header) { + + $headers = array(); + $requests = explode("\r\n\r\n", trim($header)); + + foreach ($requests as $request) { + + $header = array(); + + foreach (explode("\r\n", $request) as $i => $line) { + + if($i === 0) { + $header['http_code'] = $line; + } else { + + list ($key, $value) = explode(': ', $line); + $header[$key] = $value; + + } + + } + + $headers[] = $header; + + } + + return $headers; + +}