[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
This commit is contained in:
logmanoriginal 2018-07-21 17:27:38 +02:00
parent 4facbf32e3
commit 066ef1d7db
1 changed files with 60 additions and 4 deletions

View File

@ -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!<br>
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;
}