From fd2185168aa8eec9bc58715c681e67eb97bb4eb9 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 18 May 2026 16:25:40 +0400 Subject: [PATCH] Confirm telegra.ph external opening. --- .../SourceFiles/core/click_handler_types.cpp | 36 +++++++++++++++---- .../SourceFiles/core/click_handler_types.h | 1 + Telegram/SourceFiles/iv/iv_instance.cpp | 7 +++- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/Telegram/SourceFiles/core/click_handler_types.cpp b/Telegram/SourceFiles/core/click_handler_types.cpp index 3d8ba2377a..ad83bbdff8 100644 --- a/Telegram/SourceFiles/core/click_handler_types.cpp +++ b/Telegram/SourceFiles/core/click_handler_types.cpp @@ -87,6 +87,11 @@ constexpr auto kReminderSetToastDuration = 4 * crl::time(1000); return UrlRequiresConfirmation(url) || IsTelegramShortLinkHost(url); } +[[nodiscard]] bool RequiresConfirmationAfterIvFallback(const QUrl &url) { + const auto host = url.host().toLower(); + return (host == u"telegra.ph"_q) || (host == u"te.legra.ph"_q); +} + // Possible context owners: media viewer, profile, history widget. void SearchByHashtag(ClickContext context, const QString &tag) { @@ -253,9 +258,6 @@ void HiddenUrlClickHandler::Open(QString url, QVariant context) { return; } - const auto open = [=] { - UrlClickHandler::Open(url, context); - }; if (url.startsWith(u"tg://"_q, Qt::CaseInsensitive) || url.startsWith(u"internal:"_q, Qt::CaseInsensitive)) { UrlClickHandler::Open(url, QVariant::fromValue([&] { @@ -267,9 +269,31 @@ void HiddenUrlClickHandler::Open(QString url, QVariant context) { const auto parsedUrl = url.startsWith(u"tonsite://"_q) ? QUrl(url) : QUrl::fromUserInput(url); - if (HiddenUrlRequiresConfirmation(parsedUrl) - && !base::IsCtrlPressed()) { - const auto my = context.value(); + auto my = context.value(); + auto openContext = context; + const auto forceConfirmation = my.forceExternalUrlConfirmation + && my.ignoreIv; + const auto skipConfirmation = base::IsCtrlPressed(); + if (forceConfirmation) { + my.forceExternalUrlConfirmation = false; + openContext = QVariant::fromValue(my); + } + const auto confirmAfterIvFallback + = RequiresConfirmationAfterIvFallback(parsedUrl) + && !my.ignoreIv + && !skipConfirmation; + const auto canTryIv = (my.sessionWindow.get() != nullptr); + if (confirmAfterIvFallback && canTryIv) { + my.forceExternalUrlConfirmation = true; + openContext = QVariant::fromValue(my); + } + const auto open = [=] { + UrlClickHandler::Open(url, openContext); + }; + if (forceConfirmation + || (confirmAfterIvFallback && !canTryIv) + || (HiddenUrlRequiresConfirmation(parsedUrl) + && !skipConfirmation)) { if (!my.show) { Core::App().hideMediaView(); } diff --git a/Telegram/SourceFiles/core/click_handler_types.h b/Telegram/SourceFiles/core/click_handler_types.h index dc58aa806f..fc488070bc 100644 --- a/Telegram/SourceFiles/core/click_handler_types.h +++ b/Telegram/SourceFiles/core/click_handler_types.h @@ -56,6 +56,7 @@ struct ClickHandlerContext { bool skipBotAutoLogin = false; bool botStartAutoSubmit = false; bool ignoreIv = false; + bool forceExternalUrlConfirmation = false; bool dark = false; // Is filled from peer info. PeerData *peer = nullptr; diff --git a/Telegram/SourceFiles/iv/iv_instance.cpp b/Telegram/SourceFiles/iv/iv_instance.cpp index 0d9c79b3bc..dd7653b79c 100644 --- a/Telegram/SourceFiles/iv/iv_instance.cpp +++ b/Telegram/SourceFiles/iv/iv_instance.cpp @@ -1026,7 +1026,12 @@ void Instance::openWithIvPreferred( const auto openExternal = [=] { auto my = context.value(); my.ignoreIv = true; - UrlClickHandler::Open(uri, QVariant::fromValue(my)); + const auto updated = QVariant::fromValue(my); + if (my.forceExternalUrlConfirmation) { + HiddenUrlClickHandler::Open(uri, updated); + } else { + UrlClickHandler::Open(uri, updated); + } }; const auto parts = uri.split('#'); if (parts.isEmpty() || parts[0].isEmpty()) {