From ef1f3cbcef50aecc126c4d29946407e0710ff97d Mon Sep 17 00:00:00 2001 From: wn_ Date: Tue, 17 Jun 2025 17:52:06 +0000 Subject: Show some HTML content as a hover tip when the 'feed URL' returned HTML without feeds. Also tweak the 'Feeds::_subscribe()' documentation a bit. --- classes/Feeds.php | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'classes/Feeds.php') diff --git a/classes/Feeds.php b/classes/Feeds.php index 7b0fc60cc..242801891 100644 --- a/classes/Feeds.php +++ b/classes/Feeds.php @@ -985,19 +985,23 @@ class Feeds extends Handler_Protected { } /** - * @return array (code => Status code, message => error message if available) + * @return array{code: int, message?: string}|array{code: int, feeds: array}|array{code: int, feed_id: int} + * code - status code (see below) + * message - optional error message + * feeds - list of discovered feed URLs + * feed_id - ID of the existing or added feed * - * 0 - OK, Feed already exists - * 1 - OK, Feed added - * 2 - Invalid URL - * 3 - URL content is HTML, no feeds available - * 4 - URL content is HTML which contains multiple feeds. - * Here you should call extractfeedurls in rpc-backend - * to get all possible feeds. - * 5 - Couldn't download the URL content. - * 6 - Content is an invalid XML. - * 7 - Error while creating feed database entry. - * 8 - Permission denied (ACCESS_LEVEL_READONLY). + * 0 - OK, Feed already exists + * 1 - OK, Feed added + * 2 - Invalid URL + * 3 - URL content is HTML, no feeds available + * 4 - URL content is HTML which contains multiple feeds. + * Here you should call extractfeedurls in rpc-backend + * to get all possible feeds. + * 5 - Couldn't download the URL content. + * 6 - Content is an invalid XML. + * 7 - Error while creating feed database entry. + * 8 - Permission denied (ACCESS_LEVEL_READONLY). */ static function _subscribe(string $url, int $cat_id = 0, string $auth_login = '', string $auth_pass = '', int $update_interval = 0): array { @@ -1038,7 +1042,7 @@ class Feeds extends Handler_Protected { $feedUrls = self::_get_feeds_from_html($url, $contents); if (count($feedUrls) == 0) { - return array("code" => 3); + return array("code" => 3, "message" => truncate_string($contents, 1000, '…')); } else if (count($feedUrls) > 1) { return array("code" => 4, "feeds" => $feedUrls); } -- cgit v1.2.3-54-g00ecf From 5b0d3257337c0296eba66537b87c9143d89a160f Mon Sep 17 00:00:00 2001 From: wn_ Date: Tue, 17 Jun 2025 17:59:10 +0000 Subject: Escape error content displayed when subscribing fails (as it might contain HTML). --- classes/Feeds.php | 2 +- js/CommonDialogs.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'classes/Feeds.php') diff --git a/classes/Feeds.php b/classes/Feeds.php index 242801891..a58c42e34 100644 --- a/classes/Feeds.php +++ b/classes/Feeds.php @@ -1035,7 +1035,7 @@ class Feeds extends Handler_Protected { UrlHelper::$fetch_last_error .= " (feed behind Cloudflare)"; } - return array("code" => 5, "message" => UrlHelper::$fetch_last_error); + return array("code" => 5, "message" => truncate_string(UrlHelper::$fetch_last_error, 1000, '…')); } if (str_contains(UrlHelper::$fetch_last_content_type, "html") && self::_is_html($contents)) { diff --git a/js/CommonDialogs.js b/js/CommonDialogs.js index dcf25a566..124c8a17d 100644 --- a/js/CommonDialogs.js +++ b/js/CommonDialogs.js @@ -195,7 +195,7 @@ const CommonDialogs = { } break; case 5: - dialog.show_error(__("Couldn't download the specified URL: %s").replace("%s", rc['message'])); + dialog.show_error(__("Couldn't download the specified URL: %s").replace("%s", App.escapeHtml(rc['message']))); break; case 6: dialog.show_error(__("XML validation failed: %s").replace("%s", rc['message'])); -- cgit v1.2.3-54-g00ecf From 692c7a89498730fc1491f93dc403bc133a03f271 Mon Sep 17 00:00:00 2001 From: wn_ Date: Tue, 17 Jun 2025 18:02:57 +0000 Subject: Remove unused subscription return code 6 --- classes/Feeds.php | 2 +- js/CommonDialogs.js | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'classes/Feeds.php') diff --git a/classes/Feeds.php b/classes/Feeds.php index a58c42e34..6284b1b8f 100644 --- a/classes/Feeds.php +++ b/classes/Feeds.php @@ -999,7 +999,7 @@ class Feeds extends Handler_Protected { * Here you should call extractfeedurls in rpc-backend * to get all possible feeds. * 5 - Couldn't download the URL content. - * 6 - Content is an invalid XML. + * 6 - currently unused * 7 - Error while creating feed database entry. * 8 - Permission denied (ACCESS_LEVEL_READONLY). */ diff --git a/js/CommonDialogs.js b/js/CommonDialogs.js index 124c8a17d..eaa0249e8 100644 --- a/js/CommonDialogs.js +++ b/js/CommonDialogs.js @@ -197,9 +197,6 @@ const CommonDialogs = { case 5: dialog.show_error(__("Couldn't download the specified URL: %s").replace("%s", App.escapeHtml(rc['message']))); break; - case 6: - dialog.show_error(__("XML validation failed: %s").replace("%s", rc['message'])); - break; case 7: dialog.show_error(__("Error while creating feed database entry.")); break; -- cgit v1.2.3-54-g00ecf From 09c11df764a5485e2a6a670d3218f2f7dadaa9d1 Mon Sep 17 00:00:00 2001 From: wn_ Date: Thu, 19 Jun 2025 20:37:49 +0000 Subject: Clean up displaying subscription error info, log more detailed info to the event log. --- classes/Feeds.php | 15 ++++++++++++--- js/CommonDialogs.js | 10 ++++------ 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'classes/Feeds.php') diff --git a/classes/Feeds.php b/classes/Feeds.php index 6284b1b8f..8f1fa5d9f 100644 --- a/classes/Feeds.php +++ b/classes/Feeds.php @@ -1013,7 +1013,10 @@ class Feeds extends Handler_Protected { $url = UrlHelper::validate($url); - if (!$url) return ["code" => 2]; + if (!$url) { + Logger::log(E_USER_NOTICE, "An attempt to subscribe to '{$url}' failed due to URL validation (User: '{$user->login}'; ID: {$user->id})."); + return ["code" => 2]; + } PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_PRE_SUBSCRIBE, /** @phpstan-ignore closure.unusedUse, closure.unusedUse, closure.unusedUse */ @@ -1035,14 +1038,20 @@ class Feeds extends Handler_Protected { UrlHelper::$fetch_last_error .= " (feed behind Cloudflare)"; } - return array("code" => 5, "message" => truncate_string(UrlHelper::$fetch_last_error, 1000, '…')); + Logger::log(E_USER_NOTICE, "An attempt to subscribe to '{$url}' failed (User: '{$user->login}'; ID: {$user->id}).", + truncate_string(UrlHelper::$fetch_last_error, 500, '…')); + + return array("code" => 5, "message" => truncate_string(clean(UrlHelper::$fetch_last_error), 250, '…')); } if (str_contains(UrlHelper::$fetch_last_content_type, "html") && self::_is_html($contents)) { $feedUrls = self::_get_feeds_from_html($url, $contents); if (count($feedUrls) == 0) { - return array("code" => 3, "message" => truncate_string($contents, 1000, '…')); + Logger::log(E_USER_NOTICE, "An attempt to subscribe to '{$url}' failed due to content being HTML without detected feed URLs (User: '{$user->login}'; ID: {$user->id}).", + truncate_string($contents, 500, '…')); + + return array("code" => 3, "message" => truncate_string(clean($contents), 250, '…')); } else if (count($feedUrls) > 1) { return array("code" => 4, "feeds" => $feedUrls); } diff --git a/js/CommonDialogs.js b/js/CommonDialogs.js index eaa0249e8..1215d567d 100644 --- a/js/CommonDialogs.js +++ b/js/CommonDialogs.js @@ -118,10 +118,10 @@ const CommonDialogs = { `, - show_error: function (msg) { + show_error: function (msg, additional_info) { const elem = App.byId("fadd_error_message"); - elem.innerHTML = msg; + elem.innerHTML = `${msg}${additional_info ? `

${__('Additional information')}

${additional_info}` : ''}`; Element.show(elem); }, @@ -168,9 +168,7 @@ const CommonDialogs = { dialog.show_error(__("Specified URL seems to be invalid.")); break; case 3: - dialog.show_error(` - ${__("Specified URL doesn't seem to contain any feeds.")} - `); + dialog.show_error(__("Specified URL doesn't seem to contain any feeds."), App.escapeHtml(rc['message'])); break; case 4: { @@ -195,7 +193,7 @@ const CommonDialogs = { } break; case 5: - dialog.show_error(__("Couldn't download the specified URL: %s").replace("%s", App.escapeHtml(rc['message']))); + dialog.show_error(__("Couldn't download the specified URL."), App.escapeHtml(rc['message'])); break; case 7: dialog.show_error(__("Error while creating feed database entry.")); -- cgit v1.2.3-54-g00ecf