core: Add Debug::isEnabled() and Debug::isSecure()

Also adds documentation to Debug.php!

* Debug::isEnabled()

Checks if the DEBUG file exists on disk on the first call (stored in
memory for the duration of the instance). Returns true if debug mode
is enabled for the client.

This function also sets the internal flag for Debug::isSecure()!

* Debug::isSecure()

Returns true if debuging is enabled for specific IP addresses, false
otherwise. This is checked on the first call of Debug::isEnabled().
If you call this function before Debug::isEnabled(), the default value
is false.
This commit is contained in:
logmanoriginal 2018-11-10 20:44:23 +01:00
parent c63af2e7ad
commit a0490e3673
5 changed files with 87 additions and 36 deletions

View file

@ -1,31 +1,4 @@
<?php <?php
/*
Create a file named 'DEBUG' for enabling debug mode.
For further security, you may put whitelisted IP addresses in the file,
one IP per line. Empty file allows anyone(!).
Debugging allows displaying PHP error messages and bypasses the cache: this
can allow a malicious client to retrieve data about your server and hammer
a provider throught your rss-bridge instance.
*/
if(file_exists('DEBUG')) {
$debug_whitelist = trim(file_get_contents('DEBUG'));
$debug_enabled = empty($debug_whitelist)
|| in_array($_SERVER['REMOTE_ADDR'],
explode("\n", str_replace("\r", '', $debug_whitelist)
)
);
if($debug_enabled) {
ini_set('display_errors', '1');
error_reporting(E_ALL);
define('DEBUG', true);
if (empty($debug_whitelist)) {
define('DEBUG_INSECURE', true);
}
}
}
require_once __DIR__ . '/lib/rssbridge.php'; require_once __DIR__ . '/lib/rssbridge.php';
Configuration::verifyInstallation(); Configuration::verifyInstallation();
@ -221,7 +194,7 @@ try {
if($mtime !== false if($mtime !== false
&& (time() - $cache_timeout < $mtime) && (time() - $cache_timeout < $mtime)
&& (!defined('DEBUG') || DEBUG !== true)) { // Load cached data && !Debug::isEnabled()) { // Load cached data
// Send "Not Modified" response if client supports it // Send "Not Modified" response if client supports it
// Implementation based on https://stackoverflow.com/a/10847262 // Implementation based on https://stackoverflow.com/a/10847262

View file

@ -57,16 +57,16 @@ EOD;
private static function getHeader() { private static function getHeader() {
$warning = ''; $warning = '';
if(defined('DEBUG') && DEBUG === true) { if(Debug::isEnabled()) {
if(defined('DEBUG_INSECURE') && DEBUG_INSECURE === true) { if(!Debug::isSecure()) {
$warning .= <<<EOD $warning .= <<<EOD
<section class="critical-warning">Warning : Debug mode is active from any location, <section class="critical-warning">Warning : Debug mode is active from any location,
make sure only you can access RSS-Bridge.</section> make sure only you can access RSS-Bridge.</section>
EOD; EOD;
} else { } else {
$warning .= <<<EOD $warning .= <<<EOD
<section class="warning">Warning : Debug mode is active from your IP address, <section class="warning">Warning : Debug mode is active from your IP address,
your requests will bypass the cache.</section> your requests will bypass the cache.</section>
EOD; EOD;
} }
} }

View file

@ -1,8 +1,85 @@
<?php <?php
/**
* Implements functions for debugging purposes. Debugging can be enabled by
* placing a file named 'DEBUG' in PATH_ROOT.
*
* The file specifies a whitelist of IP addresses on which debug mode will be
* enabled. An empty file enables debug mode for everyone (highly discouraged
* for public servers!). Each line in the file specifies one client in the
* whitelist. For example:
*
* 192.168.1.72
* 127.0.0.1
* ::1
*
* Notice: If you are running RSS-Bridge on your local machine, you need to add
* localhost (either 127.0.0.1 for IPv4 or ::1 for IPv6) to your whitelist!
*
* Warning: In debug mode your server may display sensitive information! For
* security reasons it is recommended to whitelist only specific IP addresses.
*/
class Debug { class Debug {
/**
* Indicates if debug mode is enabled.
* Use Debug::isEnabled() instead of accessing this parameter directly!
*/
private static $enabled = false;
/**
* Indicates if debug mode is secure (not enabled for everyone).
* Use Debug::isSecure() instead of accessing this parameter directly!
*/
private static $secure = false;
/**
* @return bool Indicates if debug mode is enabled
*/
public static function isEnabled() {
static $firstCall = true; // Initialized on first call
if($firstCall && file_exists(PATH_ROOT . 'DEBUG')) {
$debug_whitelist = trim(file_get_contents(PATH_ROOT . 'DEBUG'));
Debug::$enabled = empty($debug_whitelist) || in_array($_SERVER['REMOTE_ADDR'],
explode("\n", str_replace("\r", '', $debug_whitelist)
)
);
if(Debug::$enabled) {
ini_set('display_errors', '1');
error_reporting(E_ALL);
Debug::$secure = !empty($debug_whitelist);
}
$firstCall = false; // Skip check on next call
}
return Debug::$enabled;
}
/**
* Returns true if debug mode has been enabled for specific IP addresses
* only, false otherwise.
*
* Notice: The security flag is set by Debug::isEnabled(). If this function
* is called before Debug::isEnabled(), the default value is false!
*
* @return bool Indicates if debug mode is secure
*/
public static function isSecure() {
return Debug::$secure;
}
/**
* Adds a debug message to error_log if debug mode is enabled
*/
public static function log($text) { public static function log($text) {
if(!DEBUG) { if(!Debug::isEnabled()) {
return; return;
} }

View file

@ -123,7 +123,7 @@ $defaultSpanText = DEFAULT_SPAN_TEXT){
$time = $cache->getTime(); $time = $cache->getTime();
if($time !== false if($time !== false
&& (time() - $duration < $time) && (time() - $duration < $time)
&& (!defined('DEBUG') || DEBUG !== true)) { // Contents within duration && Debug::isEnabled()) { // Contents within duration
$content = $cache->loadData(); $content = $cache->loadData();
} else { // Content not within duration } else { // Content not within duration
$content = getContents($url, $header, $opts); $content = getContents($url, $header, $opts);

View file

@ -1,5 +1,6 @@
<?php <?php
define('PATH_ROOT', __DIR__ . '/../'); // Path to root folder
define('PATH_LIB', __DIR__ . '/../lib/'); // Path to core library define('PATH_LIB', __DIR__ . '/../lib/'); // Path to core library
define('PATH_LIB_VENDOR', __DIR__ . '/../vendor/'); // Path to vendor library define('PATH_LIB_VENDOR', __DIR__ . '/../vendor/'); // Path to vendor library
define('PATH_LIB_BRIDGES', __DIR__ . '/../bridges/'); // Path to bridges library define('PATH_LIB_BRIDGES', __DIR__ . '/../bridges/'); // Path to bridges library