diff --git a/actions/DisplayAction.php b/actions/DisplayAction.php
index 080da52e..3ad8495f 100644
--- a/actions/DisplayAction.php
+++ b/actions/DisplayAction.php
@@ -13,13 +13,6 @@ class DisplayAction implements ActionInterface
public function execute(array $request)
{
- if (Configuration::getConfig('system', 'enable_maintenance_mode')) {
- return new Response(render(__DIR__ . '/../templates/error.html.php', [
- 'title' => '503 Service Unavailable',
- 'message' => 'RSS-Bridge is down for maintenance.',
- ]), 503);
- }
-
$cacheKey = 'http_' . json_encode($request);
/** @var Response $cachedResponse */
$cachedResponse = $this->cache->get($cacheKey);
@@ -118,6 +111,7 @@ class DisplayAction implements ActionInterface
}
$feed = $bridge->getFeed();
} catch (\Exception $e) {
+ // Probably an exception inside a bridge
if ($e instanceof HttpException) {
// Reproduce (and log) these responses regardless of error output and report limit
if ($e->getCode() === 429) {
diff --git a/actions/SetBridgeCacheAction.php b/actions/SetBridgeCacheAction.php
index 2e9d7147..e4d245df 100644
--- a/actions/SetBridgeCacheAction.php
+++ b/actions/SetBridgeCacheAction.php
@@ -11,9 +11,30 @@ class SetBridgeCacheAction implements ActionInterface
public function execute(array $request)
{
- $authenticationMiddleware = new ApiAuthenticationMiddleware();
- $authenticationMiddleware($request);
+ // Authentication
+ $accessTokenInConfig = Configuration::getConfig('authentication', 'access_token');
+ if (!$accessTokenInConfig) {
+ return new Response('Access token is not set in this instance', 403, ['content-type' => 'text/plain']);
+ }
+ if (isset($request['access_token'])) {
+ $accessTokenGiven = $request['access_token'];
+ } else {
+ $header = trim($_SERVER['HTTP_AUTHORIZATION'] ?? '');
+ $position = strrpos($header, 'Bearer ');
+ if ($position !== false) {
+ $accessTokenGiven = substr($header, $position + 7);
+ } else {
+ $accessTokenGiven = '';
+ }
+ }
+ if (!$accessTokenGiven) {
+ return new Response('No access token given', 403, ['content-type' => 'text/plain']);
+ }
+ if (! hash_equals($accessTokenInConfig, $accessTokenGiven)) {
+ return new Response('Incorrect access token', 403, ['content-type' => 'text/plain']);
+ }
+ // Begin actual work
$key = $request['key'] ?? null;
if (!$key) {
returnClientError('You must specify key!');
diff --git a/index.php b/index.php
index 126200da..029b673c 100644
--- a/index.php
+++ b/index.php
@@ -1,18 +1,22 @@
$e]), 500);
+ $response->send();
RssBridge::getLogger()->error('Uncaught Exception', ['e' => $e]);
- http_response_code(500);
- exit(render(__DIR__ . '/templates/exception.html.php', ['e' => $e]));
});
set_error_handler(function ($code, $message, $file, $line) {
if ((error_reporting() & $code) === 0) {
+ // Deprecation messages and other masked errors are typically ignored here
return false;
}
// In the future, uncomment this:
@@ -39,11 +43,37 @@ register_shutdown_function(function () {
);
RssBridge::getLogger()->error($message);
if (Debug::isEnabled()) {
+ // This output can interfere with json output etc
+ // This output is written at the bottom
print sprintf("
%s
\n", e($message));
}
}
});
-$rssBridge = new RssBridge();
+$errors = Configuration::checkInstallation();
+if ($errors) {
+ http_response_code(500);
+ print '' . implode("\n", $errors) . '
';
+ exit;
+}
-$rssBridge->main($argv ?? []);
+$customConfig = [];
+if (file_exists(__DIR__ . '/config.ini.php')) {
+ $customConfig = parse_ini_file(__DIR__ . '/config.ini.php', true, INI_SCANNER_TYPED);
+}
+Configuration::loadConfiguration($customConfig, getenv());
+
+// Consider: ini_set('error_reporting', E_ALL & ~E_DEPRECATED);
+
+date_default_timezone_set(Configuration::getConfig('system', 'timezone'));
+
+try {
+ $rssBridge = new RssBridge();
+ $response = $rssBridge->main($argv ?? []);
+ $response->send();
+} catch (\Throwable $e) {
+ // Probably an exception inside an action
+ RssBridge::getLogger()->error('Exception in RssBridge::main()', ['e' => $e]);
+ http_response_code(500);
+ print render(__DIR__ . '/templates/exception.html.php', ['e' => $e]);
+}
diff --git a/lib/ApiAuthenticationMiddleware.php b/lib/ApiAuthenticationMiddleware.php
deleted file mode 100644
index 62886314..00000000
--- a/lib/ApiAuthenticationMiddleware.php
+++ /dev/null
@@ -1,40 +0,0 @@
-exit('Access token is not set in this instance', 403);
- }
-
- if (isset($request['access_token'])) {
- $accessTokenGiven = $request['access_token'];
- } else {
- $header = trim($_SERVER['HTTP_AUTHORIZATION'] ?? '');
- $position = strrpos($header, 'Bearer ');
-
- if ($position !== false) {
- $accessTokenGiven = substr($header, $position + 7);
- } else {
- $accessTokenGiven = '';
- }
- }
-
- if (!$accessTokenGiven) {
- $this->exit('No access token given', 403);
- }
-
- if ($accessTokenGiven != $accessTokenInConfig) {
- $this->exit('Incorrect access token', 403);
- }
- }
-
- private function exit($message, $code)
- {
- http_response_code($code);
- header('content-type: text/plain');
- die($message);
- }
-}
diff --git a/lib/AuthenticationMiddleware.php b/lib/AuthenticationMiddleware.php
deleted file mode 100644
index a91420f8..00000000
--- a/lib/AuthenticationMiddleware.php
+++ /dev/null
@@ -1,39 +0,0 @@
-renderAuthenticationDialog();
- exit;
- }
- if (
- Configuration::getConfig('authentication', 'username') === $user
- && Configuration::getConfig('authentication', 'password') === $password
- ) {
- return;
- }
- print $this->renderAuthenticationDialog();
- exit;
- }
-
- private function renderAuthenticationDialog(): string
- {
- http_response_code(401);
- header('WWW-Authenticate: Basic realm="RSS-Bridge"');
- return render(__DIR__ . '/../templates/error.html.php', [
- 'message' => 'Please authenticate in order to access this instance!',
- ]);
- }
-}
diff --git a/lib/BridgeCard.php b/lib/BridgeCard.php
index a82f8e5a..8dc2472a 100644
--- a/lib/BridgeCard.php
+++ b/lib/BridgeCard.php
@@ -23,6 +23,7 @@ final class BridgeCard
$icon = $bridge->getIcon();
$description = $bridge->getDescription();
$parameters = $bridge->getParameters();
+
if (Configuration::getConfig('proxy', 'url') && Configuration::getConfig('proxy', 'by_bridge')) {
$parameters['global']['_noproxy'] = [
'name' => 'Disable proxy (' . (Configuration::getConfig('proxy', 'name') ?: Configuration::getConfig('proxy', 'url')) . ')',
@@ -93,32 +94,6 @@ CARD;
return $card;
}
- /**
- * Get the form header for a bridge card
- *
- * @param class-string $bridgeClassName The bridge name
- * @param bool $isHttps If disabled, adds a warning to the form
- * @return string The form header
- */
- private static function getFormHeader($bridgeClassName, $isHttps = false, $parameterName = '')
- {
- $form = <<
-
-
-EOD;
-
- if (!empty($parameterName)) {
- $form .= sprintf('', $parameterName);
- }
-
- if (!$isHttps) {
- $form .= 'Warning: This bridge is not fetching its content through a secure connection
';
- }
-
- return $form;
- }
-
/**
* Get the form body for a bridge
*
@@ -152,19 +127,10 @@ EOD;
$inputEntry['defaultValue'] = '';
}
- $idArg = 'arg-'
- . urlencode($bridgeClassName)
- . '-'
- . urlencode($parameterName)
- . '-'
- . urlencode($id);
+ $idArg = 'arg-' . urlencode($bridgeClassName) . '-' . urlencode($parameterName) . '-' . urlencode($id);
- $form .= ''
- . PHP_EOL;
+ $inputName = filter_var($inputEntry['name'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
+ $form .= '' . PHP_EOL;
if (!isset($inputEntry['type']) || $inputEntry['type'] === 'text') {
$form .= self::getTextInput($inputEntry, $idArg, $id);
@@ -206,96 +172,59 @@ EOD;
}
/**
- * Get input field attributes
+ * Get the form header for a bridge card
*
- * @param array $entry The current entry
- * @return string The input field attributes
+ * @param class-string $bridgeClassName The bridge name
+ * @param bool $isHttps If disabled, adds a warning to the form
+ * @return string The form header
*/
- private static function getInputAttributes($entry)
+ private static function getFormHeader($bridgeClassName, $isHttps = false, $parameterName = '')
{
- $retVal = '';
+ $form = <<
+
+
+EOD;
- if (isset($entry['required']) && $entry['required'] === true) {
- $retVal .= ' required';
+ if (!empty($parameterName)) {
+ $form .= sprintf('', $parameterName);
}
- if (isset($entry['pattern'])) {
- $retVal .= ' pattern="' . $entry['pattern'] . '"';
+ if (!$isHttps) {
+ $form .= 'Warning: This bridge is not fetching its content through a secure connection
';
}
- return $retVal;
+ return $form;
}
- /**
- * Get text input
- *
- * @param array $entry The current entry
- * @param string $id The field ID
- * @param string $name The field name
- * @return string The text input field
- */
- private static function getTextInput($entry, $id, $name)
+ public static function getTextInput(array $entry, string $id, string $name): string
{
- return ''
- . PHP_EOL;
+ $defaultValue = filter_var($entry['defaultValue'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
+ $exampleValue = filter_var($entry['exampleValue'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
+ $attributes = self::getInputAttributes($entry);
+
+ return sprintf('' . "\n", $attributes, $id, $defaultValue, $exampleValue, $name);
}
- /**
- * Get number input
- *
- * @param array $entry The current entry
- * @param string $id The field ID
- * @param string $name The field name
- * @return string The number input field
- */
- private static function getNumberInput($entry, $id, $name)
+ public static function getNumberInput(array $entry, string $id, string $name): string
{
- return ''
- . PHP_EOL;
+ $defaultValue = filter_var($entry['defaultValue'], FILTER_SANITIZE_NUMBER_INT);
+ $exampleValue = filter_var($entry['exampleValue'], FILTER_SANITIZE_NUMBER_INT);
+ $attributes = self::getInputAttributes($entry);
+
+ return sprintf('' . "\n", $attributes, $id, $defaultValue, $exampleValue, $name);
}
- /**
- * Get list input
- *
- * @param array $entry The current entry
- * @param string $id The field ID
- * @param string $name The field name
- * @return string The list input field
- */
- private static function getListInput($entry, $id, $name)
+ public static function getListInput(array $entry, string $id, string $name): string
{
- if (isset($entry['required']) && $entry['required'] === true) {
+ $required = $entry['required'] ?? null;
+ if ($required) {
Debug::log('The "required" attribute is not supported for lists.');
unset($entry['required']);
}
- $list = '