diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | actions/DisplayAction.php | 8 | ||||
-rw-r--r-- | actions/FrontpageAction.php | 1 | ||||
-rw-r--r-- | bridges/SchweinfurtBuergerinformationenBridge.php | 4 | ||||
-rw-r--r-- | config.default.ini.php | 7 | ||||
-rw-r--r-- | docs/04_For_Developers/05_Debug_mode.md | 20 | ||||
-rw-r--r-- | docs/images/debug_mode.png | bin | 21735 -> 0 bytes | |||
-rw-r--r-- | lib/Configuration.php | 16 | ||||
-rw-r--r-- | lib/Debug.php | 99 | ||||
-rw-r--r-- | lib/FeedExpander.php | 4 | ||||
-rw-r--r-- | lib/Logger.php | 15 | ||||
-rw-r--r-- | lib/RssBridge.php | 2 | ||||
-rw-r--r-- | lib/bootstrap.php | 1 | ||||
-rw-r--r-- | lib/contents.php | 7 | ||||
-rw-r--r-- | lib/html.php | 33 | ||||
-rw-r--r-- | static/style.css | 32 | ||||
-rw-r--r-- | templates/base.html.php | 8 | ||||
-rw-r--r-- | templates/frontpage.html.php | 14 |
18 files changed, 119 insertions, 156 deletions
@@ -183,9 +183,9 @@ Add the bridge name to `whitelist.txt`: ### How to enable debug mode -Create a file named `DEBUG`: +Set in `config.ini.php`: - touch DEBUG + enable_debug_mode = true Learn more in [debug mode](https://rss-bridge.github.io/rss-bridge/For_Developers/Debug_mode.html). diff --git a/actions/DisplayAction.php b/actions/DisplayAction.php index 3a262674..c71be5dd 100644 --- a/actions/DisplayAction.php +++ b/actions/DisplayAction.php @@ -107,7 +107,7 @@ class DisplayAction implements ActionInterface && (time() - $cache_timeout < $mtime) && !Debug::isEnabled() ) { - // At this point we found the feed in the cache + // At this point we found the feed in the cache and debug mode is disabled if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { // The client wants to know if the feed has changed since its last check @@ -118,7 +118,7 @@ class DisplayAction implements ActionInterface } } - // Fetch the cached feed from the cache and prepare it + // Load the feed from cache and prepare it $cached = $cache->loadData(); if (isset($cached['items']) && isset($cached['extraInfos'])) { foreach ($cached['items'] as $item) { @@ -127,7 +127,7 @@ class DisplayAction implements ActionInterface $infos = $cached['extraInfos']; } } else { - // At this point we did NOT find the feed in the cache. So invoke the bridge! + // At this point we did NOT find the feed in the cache or debug mode is enabled. try { $bridge->setDatas($bridge_params); $bridge->collectData(); @@ -200,7 +200,7 @@ class DisplayAction implements ActionInterface $item->setURI(get_current_url()); $item->setTimestamp(time()); - // Create a item identifier for feed readers e.g. "staysafetv twitch videos_19389" + // Create an item identifier for feed readers e.g. "staysafetv twitch videos_19389" $item->setUid($bridge->getName() . '_' . $uniqueIdentifier); $content = render_template(__DIR__ . '/../templates/bridge-error.html.php', [ diff --git a/actions/FrontpageAction.php b/actions/FrontpageAction.php index f015062f..f7ba56e6 100644 --- a/actions/FrontpageAction.php +++ b/actions/FrontpageAction.php @@ -24,6 +24,7 @@ final class FrontpageAction implements ActionInterface } return render(__DIR__ . '/../templates/frontpage.html.php', [ + 'messages' => [], 'admin_email' => Configuration::getConfig('admin', 'email'), 'admin_telegram' => Configuration::getConfig('admin', 'telegram'), 'bridges' => $body, diff --git a/bridges/SchweinfurtBuergerinformationenBridge.php b/bridges/SchweinfurtBuergerinformationenBridge.php index c7c935fd..349a9d8a 100644 --- a/bridges/SchweinfurtBuergerinformationenBridge.php +++ b/bridges/SchweinfurtBuergerinformationenBridge.php @@ -43,10 +43,6 @@ class SchweinfurtBuergerinformationenBridge extends BridgeAbstract foreach ($articleIDs as $articleID) { $this->items[] = $this->generateItemFromArticle($articleID); - - if (Debug::isEnabled()) { - break; - } } } diff --git a/config.default.ini.php b/config.default.ini.php index f67f315f..3a347036 100644 --- a/config.default.ini.php +++ b/config.default.ini.php @@ -15,6 +15,13 @@ timezone = "UTC" ; Display a system message to users. message = "" +; Whether to enable debug mode. +enable_debug_mode = false + +; Enable debug mode only for these permitted ip addresses +; debug_mode_whitelist[] = 127.0.0.1 +; debug_mode_whitelist[] = 192.168.1.10 + [http] timeout = 60 useragent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0" diff --git a/docs/04_For_Developers/05_Debug_mode.md b/docs/04_For_Developers/05_Debug_mode.md index 482ff0f5..6bdb1d48 100644 --- a/docs/04_For_Developers/05_Debug_mode.md +++ b/docs/04_For_Developers/05_Debug_mode.md @@ -5,23 +5,29 @@ Enabling debug mode on a public server may result in malicious clients retrievin *** Debug mode enables error reporting and prevents loading data from the cache (data is still written to the cache). -To enable debug mode, create a file named 'DEBUG' in the root directory of RSS-Bridge (next to `index.php`). For further security, insert your IP address in the file. You can add multiple addresses, one per line. +To enable debug mode, set in `config.ini.php`: + + enable_debug_mode = true + +Allow only explicit ip addresses: + + debug_mode_whitelist[] = 127.0.0.1 + debug_mode_whitelist[] = 192.168.1.10 _Notice_: * An empty file enables debug mode for anyone! * The bridge whitelist still applies! (debug mode does **not** enable all bridges) -RSS-Bridge will give you a visual feedback when debug mode is enabled: - - +RSS-Bridge will give you a visual feedback when debug mode is enabled. While debug mode is active, RSS-Bridge will write additional data to your servers `error.log`. Debug mode is controlled by the static class `Debug`. It provides three core functions: -`Debug::isEnabled()`: Returns `true` if debug mode is enabled. -`Debug::isSecure()`: Returns `true` if your client is on the debug whitelist. -`Debug::log($message)`: Adds a message to `error.log`. It takes one parameter, which can be anything. For example: `Debug::log('Hello World!');` +* `Debug::isEnabled()`: Returns `true` if debug mode is enabled. +* `Debug::log($message)`: Adds a message to `error.log`. It takes one parameter, which can be anything. + +Example: `Debug::log('Hello World!');` **Notice**: `Debug::log($message)` calls `Debug::isEnabled()` internally. You don't have to do that manually.
\ No newline at end of file diff --git a/docs/images/debug_mode.png b/docs/images/debug_mode.png Binary files differdeleted file mode 100644 index 6ab8917b..00000000 --- a/docs/images/debug_mode.png +++ /dev/null diff --git a/lib/Configuration.php b/lib/Configuration.php index bdbd830b..6eec33f6 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -114,6 +114,15 @@ final class Configuration } } + if (file_exists(__DIR__ . '/../DEBUG')) { + // The debug mode has been moved to config. Preserve existing installs which has this DEBUG file. + self::setConfig('system', 'enable_debug_mode', true); + $debug = trim(file_get_contents(__DIR__ . '/../DEBUG')); + if ($debug) { + self::setConfig('system', 'debug_mode_whitelist', explode("\n", str_replace("\r", '', $debug))); + } + } + if ( !is_string(self::getConfig('system', 'timezone')) || !in_array(self::getConfig('system', 'timezone'), timezone_identifiers_list(DateTimeZone::ALL_WITH_BC)) @@ -121,6 +130,13 @@ final class Configuration self::throwConfigError('system', 'timezone'); } + if (!is_bool(self::getConfig('system', 'enable_debug_mode'))) { + self::throwConfigError('system', 'enable_debug_mode', 'Is not a valid Boolean'); + } + if (!is_array(self::getConfig('system', 'debug_mode_whitelist') ?: [])) { + self::throwConfigError('system', 'debug_mode_whitelist', 'Is not a valid array'); + } + if (!is_string(self::getConfig('proxy', 'url'))) { self::throwConfigError('proxy', 'url', 'Is not a valid string'); } diff --git a/lib/Debug.php b/lib/Debug.php index 9210ebc8..f6a8d105 100644 --- a/lib/Debug.php +++ b/lib/Debug.php @@ -1,106 +1,23 @@ <?php -/** - * This file is part of RSS-Bridge, a PHP project capable of generating RSS and - * Atom feeds for websites that don't have one. - * - * For the full license information, please view the UNLICENSE file distributed - * with this source code. - * - * @package Core - * @license http://unlicense.org/ UNLICENSE - * @link https://github.com/rss-bridge/rss-bridge - */ - -/** - * Implements functions for debugging purposes. Debugging can be enabled by - * placing a file named DEBUG in {@see 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 { /** - * Indicates if debug mode is enabled. - * - * Do not access this property directly! - * Use {@see Debug::isEnabled()} instead. - * - * @var bool + * Convenience function for Configuration::getConfig('system', 'enable_debug_mode') */ - private static $enabled = false; - - /** - * Indicates if debug mode is secure. - * - * Do not access this property directly! - * Use {@see Debug::isSecure()} instead. - * - * @var bool - */ - private static $secure = false; - - /** - * Returns true if debug mode is enabled - * - * If debug mode is enabled, sets `display_errors = 1` and `error_reporting = E_ALL` - * - * @return bool True if enabled. - */ - public static function isEnabled() + public static function isEnabled(): bool { - static $firstCall = true; // Initialized on first call - - if ($firstCall && file_exists(__DIR__ . '/../DEBUG')) { - $debug_whitelist = trim(file_get_contents(__DIR__ . '/../DEBUG')); - - self::$enabled = empty($debug_whitelist) || in_array( - $_SERVER['REMOTE_ADDR'], - explode("\n", str_replace("\r", '', $debug_whitelist)) - ); - - if (self::$enabled) { - self::$secure = !empty($debug_whitelist); - } - - $firstCall = false; // Skip check on next call + $ip = $_SERVER['REMOTE_ADDR']; + $enableDebugMode = Configuration::getConfig('system', 'enable_debug_mode'); + $debugModeWhitelist = Configuration::getConfig('system', 'debug_mode_whitelist') ?: []; + if ($enableDebugMode && ($debugModeWhitelist === [] || in_array($ip, $debugModeWhitelist))) { + return true; } - - return self::$enabled; - } - - /** - * Returns true if debug mode is enabled only for specific IP addresses. - * - * Notice: The security flag is set by {@see Debug::isEnabled()}. If this - * function is called before {@see Debug::isEnabled()}, the default value is - * false! - * - * @return bool True if debug mode is secure - */ - public static function isSecure() - { - return self::$secure; + return false; } public static function log($message) { - if (!self::isEnabled()) { - return; - } $e = new \Exception(); $trace = trace_from_exception($e); // Drop the current frame diff --git a/lib/FeedExpander.php b/lib/FeedExpander.php index edfe99d4..1bac6179 100644 --- a/lib/FeedExpander.php +++ b/lib/FeedExpander.php @@ -113,9 +113,7 @@ abstract class FeedExpander extends BridgeAbstract if ($rssContent === false) { $xmlErrors = libxml_get_errors(); foreach ($xmlErrors as $xmlError) { - if (Debug::isEnabled()) { - Debug::log(trim($xmlError->message)); - } + Logger::debug(trim($xmlError->message)); } if ($xmlErrors) { // Render only the first error into exception message diff --git a/lib/Logger.php b/lib/Logger.php index 9bbdd512..e15035fe 100644 --- a/lib/Logger.php +++ b/lib/Logger.php @@ -6,9 +6,7 @@ final class Logger { public static function debug(string $message, array $context = []) { - if (Debug::isEnabled()) { - self::log('DEBUG', $message, $context); - } + self::log('DEBUG', $message, $context); } public static function info(string $message, array $context = []): void @@ -28,6 +26,11 @@ final class Logger private static function log(string $level, string $message, array $context = []): void { + if (!Debug::isEnabled() && $level === 'DEBUG') { + // Don't log this debug log record because debug mode is disabled + return; + } + if (isset($context['e'])) { /** @var \Throwable $e */ $e = $context['e']; @@ -66,7 +69,13 @@ final class Logger $message, $context ? Json::encode($context) : '' ); + // Log to stderr/stdout whatever that is + // todo: extract to log handler error_log($text); + + // Log to file + // todo: extract to log handler + //file_put_contents('/tmp/rss-bridge.log', $text, FILE_APPEND); } } diff --git a/lib/RssBridge.php b/lib/RssBridge.php index 62e8acc5..e6f1c9e4 100644 --- a/lib/RssBridge.php +++ b/lib/RssBridge.php @@ -42,6 +42,7 @@ final class RssBridge ); Logger::warning($text); if (Debug::isEnabled()) { + // todo: extract to log handler print sprintf("<pre>%s</pre>\n", e($text)); } }); @@ -59,6 +60,7 @@ final class RssBridge ); Logger::error($message); if (Debug::isEnabled()) { + // todo: extract to log handler print sprintf("<pre>%s</pre>\n", e($message)); } } diff --git a/lib/bootstrap.php b/lib/bootstrap.php index 8e5cf69c..98c7b54d 100644 --- a/lib/bootstrap.php +++ b/lib/bootstrap.php @@ -40,6 +40,7 @@ const WHITELIST_DEFAULT = __DIR__ . '/../whitelist.default.txt'; const REPOSITORY = 'https://github.com/RSS-Bridge/rss-bridge/'; // Allow larger files for simple_html_dom +// todo: extract to config (if possible) const MAX_FILE_SIZE = 10000000; // Files diff --git a/lib/contents.php b/lib/contents.php index ebd4ee2c..a1630e3c 100644 --- a/lib/contents.php +++ b/lib/contents.php @@ -438,14 +438,17 @@ function getSimpleHTMLDOMCached( $time !== false && (time() - $duration < $time) && !Debug::isEnabled() - ) { // Contents within duration + ) { + // Contents within duration and debug mode is disabled $content = $cache->loadData(); - } else { // Content not within duration + } else { + // Contents not within duration, or debug mode is enabled $content = getContents( $url, $header ?? [], $opts ?? [] ); + // todo: fix bad if statement if ($content !== false) { $cache->saveData($content); } diff --git a/lib/html.php b/lib/html.php index 7f4f1201..ca0a411c 100644 --- a/lib/html.php +++ b/lib/html.php @@ -1,23 +1,34 @@ <?php /** - * This file is part of RSS-Bridge, a PHP project capable of generating RSS and - * Atom feeds for websites that don't have one. - * - * For the full license information, please view the UNLICENSE file distributed - * with this source code. - * - * @package Core - * @license http://unlicense.org/ UNLICENSE - * @link https://github.com/rss-bridge/rss-bridge + * Render template using base.html.php as base */ - function render(string $template, array $context = []): string { if ($template === 'base.html.php') { throw new \Exception('Do not render base.html.php into itself'); } - $context['system_message'] = Configuration::getConfig('system', 'message'); + $context['messages'] = $context['messages'] ?? []; + if (Configuration::getConfig('system', 'message')) { + $context['messages'][] = [ + 'body' => Configuration::getConfig('system', 'message'), + 'level' => 'info', + ]; + } + if (Debug::isEnabled()) { + $debugModeWhitelist = Configuration::getConfig('system', 'debug_mode_whitelist') ?: []; + if ($debugModeWhitelist === []) { + $context['messages'][] = [ + 'body' => 'Warning : Debug mode is active from any location, make sure only you can access RSS-Bridge.', + 'level' => 'error' + ]; + } else { + $context['messages'][] = [ + 'body' => 'Warning : Debug mode is active from your IP address, your requests will bypass the cache.', + 'level' => 'warning' + ]; + } + } $context['page'] = render_template($template, $context); return render_template('base.html.php', $context); } diff --git a/static/style.css b/static/style.css index 570ee014..a83e25e4 100644 --- a/static/style.css +++ b/static/style.css @@ -71,15 +71,34 @@ header { text-align: center; } -section.warning { +.alert-info { + margin-bottom: 15px; + color: white; + font-weight: bold; + background-color: rgb(33, 150, 243); + padding: 15px; + border-radius: 4px; + text-align: center; +} + +.alert-warning { background-color: #ffc600; color: #5f5f5f; + margin-bottom: 15px; + font-weight: bold; + padding: 15px; + border-radius: 4px; + text-align: center; } -section.critical-warning { +.alert-error { background-color: #cf3e3e; font-weight: bold; color: white; + margin-bottom: 15px; + padding: 15px; + border-radius: 4px; + text-align: center; } select, @@ -342,15 +361,6 @@ button { width: 200px; } -.alert { - margin-bottom: 15px; - color: white; - font-weight: bold; - background-color: rgb(33, 150, 243); - padding: 15px; - border-radius: 4px; -} - @media screen and (max-width: 767px) { .container { width: 100%; diff --git a/templates/base.html.php b/templates/base.html.php index 00728785..ca31823d 100644 --- a/templates/base.html.php +++ b/templates/base.html.php @@ -17,11 +17,11 @@ </a> </header> - <?php if ($system_message): ?> - <div class="alert"> - <?= raw($system_message) ?> + <?php foreach ($messages as $message): ?> + <div class="alert-<?= raw($message['level'] ?? 'info') ?>"> + <?= raw($message['body']) ?> </div> - <?php endif; ?> + <?php endforeach; ?> <?= raw($page) ?> </div> diff --git a/templates/frontpage.html.php b/templates/frontpage.html.php index 5daa63bd..63f4a2ab 100644 --- a/templates/frontpage.html.php +++ b/templates/frontpage.html.php @@ -4,20 +4,6 @@ document.addEventListener('DOMContentLoaded', rssbridge_list_search); </script> -<?php if (Debug::isEnabled()): ?> - <?php if (!Debug::isSecure()): ?> - <section class="critical-warning"> - Warning : Debug mode is active from any location, - make sure only you can access RSS-Bridge. - </section> - <?php else: ?> - <section class="warning"> - Warning : Debug mode is active from your IP address, - your requests will bypass the cache. - </section> - <?php endif; ?> -<?php endif; ?> - <section class="searchbar"> <h3>Search</h3> <input |