Allow tg URLs in text links and url buttons.
GitOrigin-RevId: 9708c3016375564e737bf5a8f79494807d61c10f
This commit is contained in:
parent
537d96cc8e
commit
1ef5c89a91
@ -582,7 +582,7 @@ keyboardButton text:string type:KeyboardButtonType = KeyboardButton;
|
||||
|
||||
//@class InlineKeyboardButtonType @description Describes the type of an inline keyboard button
|
||||
|
||||
//@description A button that opens a specified URL @url URL to open
|
||||
//@description A button that opens a specified URL @url HTTP or tg:// URL to open
|
||||
inlineKeyboardButtonTypeUrl url:string = InlineKeyboardButtonType;
|
||||
|
||||
//@description A button that sends a special callback query to a bot @data Data to be sent to the bot via a callback query
|
||||
@ -1179,7 +1179,7 @@ textEntityTypePre = TextEntityType;
|
||||
//@description Text that must be formatted as if inside pre, and code HTML tags @language Programming language of the code; as defined by the sender
|
||||
textEntityTypePreCode language:string = TextEntityType;
|
||||
|
||||
//@description A text description shown instead of a raw URL @url URL to be opened when the link is clicked
|
||||
//@description A text description shown instead of a raw URL @url HTTP or tg:// URL to be opened when the link is clicked
|
||||
textEntityTypeTextUrl url:string = TextEntityType;
|
||||
|
||||
//@description A text shows instead of a raw mention of the user (e.g., when the user has no username) @user_id Identifier of the mentioned user
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/misc.h"
|
||||
|
||||
#include "td/utils/HttpUrl.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/unicode.h"
|
||||
@ -1329,10 +1328,10 @@ Result<vector<MessageEntity>> parse_markdown(string &text) {
|
||||
if (user_id.is_valid()) {
|
||||
entities.emplace_back(utf16_offset, utf16_entity_length, user_id);
|
||||
} else {
|
||||
auto r_http_url = parse_url(url);
|
||||
if (r_http_url.is_ok() && url.find('.') != string::npos) {
|
||||
auto r_url = check_url(url);
|
||||
if (r_url.is_ok()) {
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, utf16_offset, utf16_entity_length,
|
||||
r_http_url.ok().get_url());
|
||||
r_url.move_as_ok());
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1585,10 +1584,9 @@ Result<vector<MessageEntity>> parse_html(string &text) {
|
||||
if (user_id.is_valid()) {
|
||||
entities.emplace_back(utf16_offset, utf16_entity_length, user_id);
|
||||
} else {
|
||||
auto r_http_url = parse_url(url);
|
||||
if (r_http_url.is_ok() && url.find('.') != string::npos) {
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, utf16_offset, utf16_entity_length,
|
||||
r_http_url.ok().get_url());
|
||||
auto r_url = check_url(url);
|
||||
if (r_url.is_ok()) {
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, utf16_offset, utf16_entity_length, r_url.move_as_ok());
|
||||
}
|
||||
}
|
||||
} else if (tag_name == "pre") {
|
||||
@ -1746,12 +1744,11 @@ Result<vector<MessageEntity>> get_message_entities(const ContactsManager *contac
|
||||
if (!clean_input_string(entity_text_url->url_)) {
|
||||
return Status::Error(400, "MessageEntityTextUrl.url must be encoded in UTF-8");
|
||||
}
|
||||
auto r_http_url = parse_url(entity_text_url->url_);
|
||||
if (r_http_url.is_error()) {
|
||||
return Status::Error(400, PSTRING() << "Wrong message entity: " << r_http_url.error().message());
|
||||
auto r_url = check_url(entity_text_url->url_);
|
||||
if (r_url.is_error()) {
|
||||
return Status::Error(400, PSTRING() << "Wrong message entity: " << r_url.error().message());
|
||||
}
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity->offset_, entity->length_,
|
||||
r_http_url.ok().get_url());
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity->offset_, entity->length_, r_url.move_as_ok());
|
||||
break;
|
||||
}
|
||||
case td_api::textEntityTypeMentionName::ID: {
|
||||
@ -1843,14 +1840,14 @@ vector<MessageEntity> get_message_entities(const ContactsManager *contacts_manag
|
||||
case telegram_api::messageEntityTextUrl::ID: {
|
||||
// TODO const telegram_api::messageEntityTextUrl *
|
||||
auto entity_text_url = static_cast<telegram_api::messageEntityTextUrl *>(entity.get());
|
||||
auto r_http_url = parse_url(entity_text_url->url_);
|
||||
if (r_http_url.is_error()) {
|
||||
LOG(ERROR) << "Wrong URL entity: \"" << entity_text_url->url_ << "\": " << r_http_url.error().message()
|
||||
<< " from " << source;
|
||||
auto r_url = check_url(entity_text_url->url_);
|
||||
if (r_url.is_error()) {
|
||||
LOG(ERROR) << "Wrong URL entity: \"" << entity_text_url->url_ << "\": " << r_url.error().message() << " from "
|
||||
<< source;
|
||||
continue;
|
||||
}
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity_text_url->offset_, entity_text_url->length_,
|
||||
r_http_url.ok().get_url());
|
||||
r_url.move_as_ok());
|
||||
break;
|
||||
}
|
||||
case telegram_api::messageEntityMentionName::ID: {
|
||||
@ -1947,13 +1944,13 @@ vector<MessageEntity> get_message_entities(vector<tl_object_ptr<secret_api::Mess
|
||||
LOG(WARNING) << "Wrong URL entity: \"" << entity_text_url->url_ << '"';
|
||||
continue;
|
||||
}
|
||||
auto r_http_url = parse_url(entity_text_url->url_);
|
||||
if (r_http_url.is_error()) {
|
||||
LOG(WARNING) << "Wrong URL entity: \"" << entity_text_url->url_ << "\": " << r_http_url.error().message();
|
||||
auto r_url = check_url(entity_text_url->url_);
|
||||
if (r_url.is_error()) {
|
||||
LOG(WARNING) << "Wrong URL entity: \"" << entity_text_url->url_ << "\": " << r_url.error().message();
|
||||
continue;
|
||||
}
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity_text_url->offset_, entity_text_url->length_,
|
||||
r_http_url.ok().get_url());
|
||||
r_url.move_as_ok());
|
||||
break;
|
||||
}
|
||||
case secret_api::messageEntityMentionName::ID:
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/HttpUrl.h"
|
||||
#include "td/utils/logging.h"
|
||||
|
||||
namespace td {
|
||||
@ -363,8 +362,8 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
|
||||
switch (button_type_id) {
|
||||
case td_api::inlineKeyboardButtonTypeUrl::ID: {
|
||||
current_button.type = InlineKeyboardButton::Type::Url;
|
||||
TRY_RESULT(http_url, parse_url(static_cast<td_api::inlineKeyboardButtonTypeUrl *>(button->type_.get())->url_));
|
||||
current_button.data = http_url.get_url();
|
||||
TRY_RESULT(url, check_url(static_cast<td_api::inlineKeyboardButtonTypeUrl *>(button->type_.get())->url_));
|
||||
current_button.data = std::move(url);
|
||||
if (!clean_input_string(current_button.data)) {
|
||||
return Status::Error(400, "Inline keyboard button url must be encoded in UTF-8");
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "td/telegram/misc.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/HttpUrl.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/Slice.h"
|
||||
@ -274,4 +275,32 @@ string get_emoji_fingerprint(uint64 num) {
|
||||
return emojis[(num & 0x7FFFFFFFFFFFFFFF) % emojis.size()].str();
|
||||
}
|
||||
|
||||
Result<string> check_url(MutableSlice url) {
|
||||
bool is_tg = false;
|
||||
if (begins_with(url, "tg://")) {
|
||||
url.remove_prefix(5);
|
||||
is_tg = true;
|
||||
} else if (begins_with(url, "tg:")) {
|
||||
url.remove_prefix(3);
|
||||
is_tg = true;
|
||||
} else {
|
||||
is_tg = false;
|
||||
}
|
||||
TRY_RESULT(http_url, parse_url(url));
|
||||
if (is_tg) {
|
||||
if (begins_with(url, "http://") || http_url.protocol_ == HttpUrl::Protocol::HTTPS || !http_url.userinfo_.empty() || http_url.specified_port_ != 0 || http_url.is_ipv6_) {
|
||||
return Status::Error("Wrong tg URL");
|
||||
}
|
||||
|
||||
auto result = http_url.get_url();
|
||||
CHECK(begins_with(result, "http://"));
|
||||
return PSTRING() << "tg" << Slice(result).substr(4);
|
||||
}
|
||||
|
||||
if (url.find('.') == string::npos) {
|
||||
return Status::Error("Wrong HTTP URL");
|
||||
}
|
||||
return http_url.get_url();
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -7,6 +7,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
@ -31,4 +33,7 @@ int32 get_vector_hash(const vector<uint32> &numbers) TD_WARN_UNUSED_RESULT;
|
||||
// returns emoji corresponding to the specified number
|
||||
string get_emoji_fingerprint(uint64 num);
|
||||
|
||||
// checks whether url is a valid tg or HTTP(S) URL and returns its in a canonical form
|
||||
Result<string> check_url(MutableSlice url);
|
||||
|
||||
} // namespace td
|
||||
|
@ -29,11 +29,11 @@ string HttpUrl::get_url() const {
|
||||
result += userinfo_;
|
||||
result += '@';
|
||||
}
|
||||
if (is_ipv6) {
|
||||
if (is_ipv6_) {
|
||||
result += '[';
|
||||
}
|
||||
result += host_;
|
||||
if (is_ipv6) {
|
||||
if (is_ipv6_) {
|
||||
result += ']';
|
||||
}
|
||||
if (specified_port_ > 0) {
|
||||
|
@ -18,7 +18,7 @@ class HttpUrl {
|
||||
enum class Protocol { HTTP, HTTPS } protocol_;
|
||||
string userinfo_;
|
||||
string host_;
|
||||
bool is_ipv6;
|
||||
bool is_ipv6_;
|
||||
int specified_port_;
|
||||
int port_;
|
||||
string query_;
|
||||
|
Reference in New Issue
Block a user