Simplify LinkManager::check_link usage.

This commit is contained in:
levlam 2022-05-31 01:41:01 +03:00
parent de34ffb530
commit bf0caca138
5 changed files with 51 additions and 31 deletions

View File

@ -143,8 +143,7 @@ void set_menu_button(Td *td, UserId user_id, td_api::object_ptr<td_api::botMenuB
} }
auto r_url = LinkManager::check_link(menu_button->url_, true, !G()->is_test_dc()); auto r_url = LinkManager::check_link(menu_button->url_, true, !G()->is_test_dc());
if (r_url.is_error()) { if (r_url.is_error()) {
return promise.set_error(Status::Error(400, PSLICE() << "Menu button web app URL '" << menu_button->url_ return promise.set_error(Status::Error(400, PSLICE() << "Menu button Web App " << r_url.error().message()));
<< "' is invalid: " << r_url.error().message()));
} }
input_bot_menu_button = telegram_api::make_object<telegram_api::botMenuButton>(menu_button->text_, r_url.ok()); input_bot_menu_button = telegram_api::make_object<telegram_api::botMenuButton>(menu_button->text_, r_url.ok());
} }

View File

@ -708,7 +708,28 @@ static bool tolower_begins_with(Slice str, Slice prefix) {
return true; return true;
} }
Result<string> LinkManager::check_link(Slice link, bool http_only, bool https_only) { Result<string> LinkManager::check_link(CSlice link, bool http_only, bool https_only) {
auto result = check_link_impl(link, http_only, https_only);
if (result.is_ok()) {
return std::move(result);
}
auto error = result.move_as_error();
if (check_utf8(link)) {
return Status::Error(400, PSLICE() << "URL '" << link << "' is invalid: " << error.message());
} else {
return Status::Error(400, PSLICE() << "URL is invalid: " << error.message());
}
}
string LinkManager::get_checked_link(Slice link, bool http_only, bool https_only) {
auto result = check_link_impl(link, http_only, https_only);
if (result.is_ok()) {
return result.move_as_ok();
}
return string();
}
Result<string> LinkManager::check_link_impl(Slice link, bool http_only, bool https_only) {
bool is_tg = false; bool is_tg = false;
bool is_ton = false; bool is_ton = false;
if (tolower_begins_with(link, "tg:")) { if (tolower_begins_with(link, "tg:")) {

View File

@ -47,7 +47,10 @@ class LinkManager final : public Actor {
}; };
// checks whether the link is a valid tg, ton or HTTP(S) URL and returns it in a canonical form // checks whether the link is a valid tg, ton or HTTP(S) URL and returns it in a canonical form
static Result<string> check_link(Slice link, bool http_only = false, bool https_only = false); static Result<string> check_link(CSlice link, bool http_only = false, bool https_only = false);
// same as check_link, but returns an empty string instead of an error
static string get_checked_link(Slice link, bool http_only = false, bool https_only = false);
// checks whether the link is a supported tg or t.me link and parses it // checks whether the link is a supported tg or t.me link and parses it
static unique_ptr<InternalLink> parse_internal_link(Slice link); static unique_ptr<InternalLink> parse_internal_link(Slice link);
@ -128,6 +131,8 @@ class LinkManager final : public Actor {
static unique_ptr<InternalLink> get_internal_link_message_draft(Slice url, Slice text); static unique_ptr<InternalLink> get_internal_link_message_draft(Slice url, Slice text);
static Result<string> check_link_impl(Slice link, bool http_only, bool https_only);
Td *td_; Td *td_;
ActorShared<> parent_; ActorShared<> parent_;

View File

@ -1876,9 +1876,9 @@ Result<vector<MessageEntity>> parse_markdown(string &text) {
if (user_id.is_valid()) { if (user_id.is_valid()) {
entities.emplace_back(entity_offset, entity_length, user_id); entities.emplace_back(entity_offset, entity_length, user_id);
} else { } else {
auto r_url = LinkManager::check_link(url); url = LinkManager::get_checked_link(url);
if (r_url.is_ok()) { if (!url.empty()) {
entities.emplace_back(MessageEntity::Type::TextUrl, entity_offset, entity_length, r_url.move_as_ok()); entities.emplace_back(MessageEntity::Type::TextUrl, entity_offset, entity_length, std::move(url));
} }
} }
break; break;
@ -2092,11 +2092,11 @@ static Result<vector<MessageEntity>> do_parse_markdown_v2(CSlice text, string &r
} }
user_id = LinkManager::get_link_user_id(url); user_id = LinkManager::get_link_user_id(url);
if (!user_id.is_valid()) { if (!user_id.is_valid()) {
auto r_url = LinkManager::check_link(url); url = LinkManager::get_checked_link(url);
if (r_url.is_error()) { if (url.empty()) {
skip_entity = true; skip_entity = true;
} else { } else {
argument = r_url.move_as_ok(); argument = std::move(url);
} }
} }
break; break;
@ -2169,7 +2169,7 @@ static vector<Slice> find_text_url_entities_v3(Slice text) {
if (url_end < size) { if (url_end < size) {
Slice url = text.substr(url_begin + 1, url_end - url_begin - 1); Slice url = text.substr(url_begin + 1, url_end - url_begin - 1);
if (LinkManager::check_link(url).is_ok()) { if (!LinkManager::get_checked_link(url).empty()) {
result.push_back(text.substr(text_begin, text_end - text_begin + 1)); result.push_back(text.substr(text_begin, text_end - text_begin + 1));
result.push_back(text.substr(url_begin, url_end - url_begin + 1)); result.push_back(text.substr(url_begin, url_end - url_begin + 1));
} }
@ -2241,7 +2241,7 @@ static FormattedText parse_text_url_entities_v3(Slice text, const vector<Message
Slice url = parsed_part_text.substr(url_begin_pos + 1, url_end_pos - url_begin_pos - 1); Slice url = parsed_part_text.substr(url_begin_pos + 1, url_end_pos - url_begin_pos - 1);
auto url_utf16_length = text_length(url); auto url_utf16_length = text_length(url);
result.entities.emplace_back(MessageEntity::Type::TextUrl, result_text_utf16_length, text_url_utf16_length, result.entities.emplace_back(MessageEntity::Type::TextUrl, result_text_utf16_length, text_url_utf16_length,
LinkManager::check_link(url).move_as_ok()); LinkManager::get_checked_link(url));
result.text.append(text_url.begin(), text_url.size()); result.text.append(text_url.begin(), text_url.size());
result_text_utf16_length += text_url_utf16_length; result_text_utf16_length += text_url_utf16_length;
@ -3075,9 +3075,9 @@ static Result<vector<MessageEntity>> do_parse_html(CSlice text, string &result)
if (user_id.is_valid()) { if (user_id.is_valid()) {
entities.emplace_back(entity_offset, entity_length, user_id); entities.emplace_back(entity_offset, entity_length, user_id);
} else { } else {
auto r_url = LinkManager::check_link(url); url = LinkManager::get_checked_link(url);
if (r_url.is_ok()) { if (!url.empty()) {
entities.emplace_back(MessageEntity::Type::TextUrl, entity_offset, entity_length, r_url.move_as_ok()); entities.emplace_back(MessageEntity::Type::TextUrl, entity_offset, entity_length, std::move(url));
} }
} }
} else if (tag_name == "pre") { } else if (tag_name == "pre") {
@ -3284,7 +3284,7 @@ Result<vector<MessageEntity>> get_message_entities(const ContactsManager *contac
} }
auto r_url = LinkManager::check_link(entity->url_); auto r_url = LinkManager::check_link(entity->url_);
if (r_url.is_error()) { if (r_url.is_error()) {
return Status::Error(400, PSTRING() << "Wrong URL entity specified: " << r_url.error().message()); return Status::Error(400, PSTRING() << "Entity " << r_url.error().message());
} }
entities.emplace_back(MessageEntity::Type::TextUrl, offset, length, r_url.move_as_ok()); entities.emplace_back(MessageEntity::Type::TextUrl, offset, length, r_url.move_as_ok());
break; break;
@ -3418,8 +3418,7 @@ vector<MessageEntity> get_message_entities(const ContactsManager *contacts_manag
auto entity = static_cast<const telegram_api::messageEntityTextUrl *>(server_entity.get()); auto entity = static_cast<const telegram_api::messageEntityTextUrl *>(server_entity.get());
auto r_url = LinkManager::check_link(entity->url_); auto r_url = LinkManager::check_link(entity->url_);
if (r_url.is_error()) { if (r_url.is_error()) {
LOG(ERROR) << "Wrong URL entity: \"" << entity->url_ << "\": " << r_url.error().message() << " from " LOG(ERROR) << "Entity " << r_url.error().message() << " from " << source;
<< source;
continue; continue;
} }
entities.emplace_back(MessageEntity::Type::TextUrl, entity->offset_, entity->length_, r_url.move_as_ok()); entities.emplace_back(MessageEntity::Type::TextUrl, entity->offset_, entity->length_, r_url.move_as_ok());
@ -3540,7 +3539,7 @@ vector<MessageEntity> get_message_entities(vector<tl_object_ptr<secret_api::Mess
} }
auto r_url = LinkManager::check_link(entity->url_); auto r_url = LinkManager::check_link(entity->url_);
if (r_url.is_error()) { if (r_url.is_error()) {
LOG(WARNING) << "Wrong URL entity: \"" << entity->url_ << "\": " << r_url.error().message(); LOG(WARNING) << "Entity " << r_url.error().message();
continue; continue;
} }
entities.emplace_back(MessageEntity::Type::TextUrl, entity->offset_, entity->length_, r_url.move_as_ok()); entities.emplace_back(MessageEntity::Type::TextUrl, entity->offset_, entity->length_, r_url.move_as_ok());

View File

@ -442,18 +442,17 @@ static Result<KeyboardButton> get_keyboard_button(tl_object_ptr<td_api::keyboard
} }
case td_api::keyboardButtonTypeWebApp::ID: { case td_api::keyboardButtonTypeWebApp::ID: {
if (!request_buttons_allowed) { if (!request_buttons_allowed) {
return Status::Error(400, "Web app can be used in private chats only"); return Status::Error(400, "Web App buttons can be used in private chats only");
} }
auto button_type = move_tl_object_as<td_api::keyboardButtonTypeWebApp>(button->type_); auto button_type = move_tl_object_as<td_api::keyboardButtonTypeWebApp>(button->type_);
auto user_id = LinkManager::get_link_user_id(button_type->url_); auto user_id = LinkManager::get_link_user_id(button_type->url_);
if (user_id.is_valid()) { if (user_id.is_valid()) {
return Status::Error(400, "Link to a user can't be used in web app URL buttons"); return Status::Error(400, "Link to a user can't be used in Web App URL buttons");
} }
auto r_url = LinkManager::check_link(button_type->url_, true, !G()->is_test_dc()); auto r_url = LinkManager::check_link(button_type->url_, true, !G()->is_test_dc());
if (r_url.is_error()) { if (r_url.is_error()) {
return Status::Error(400, PSLICE() << "Inline keyboard button web app URL '" << button_type->url_ return Status::Error(400, PSLICE() << "Keyboard button Web App " << r_url.error().message());
<< "' is invalid: " << r_url.error().message());
} }
current_button.type = KeyboardButton::Type::WebView; current_button.type = KeyboardButton::Type::WebView;
current_button.url = std::move(button_type->url_); current_button.url = std::move(button_type->url_);
@ -491,8 +490,7 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
} }
auto r_url = LinkManager::check_link(button_type->url_); auto r_url = LinkManager::check_link(button_type->url_);
if (r_url.is_error()) { if (r_url.is_error()) {
return Status::Error(400, PSLICE() << "Inline keyboard button URL '" << button_type->url_ return Status::Error(400, PSLICE() << "Inline keyboard button " << r_url.error().message());
<< "' is invalid: " << r_url.error().message());
} }
current_button.type = InlineKeyboardButton::Type::Url; current_button.type = InlineKeyboardButton::Type::Url;
current_button.data = r_url.move_as_ok(); current_button.data = r_url.move_as_ok();
@ -541,8 +539,7 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
} }
auto r_url = LinkManager::check_link(button_type->url_, true); auto r_url = LinkManager::check_link(button_type->url_, true);
if (r_url.is_error()) { if (r_url.is_error()) {
return Status::Error(400, PSLICE() << "Inline keyboard button login URL '" << button_type->url_ return Status::Error(400, PSLICE() << "Inline keyboard button login " << r_url.error().message());
<< "' is invalid: " << r_url.error().message());
} }
current_button.type = InlineKeyboardButton::Type::UrlAuth; current_button.type = InlineKeyboardButton::Type::UrlAuth;
current_button.data = r_url.move_as_ok(); current_button.data = r_url.move_as_ok();
@ -573,17 +570,16 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
auto button_type = move_tl_object_as<td_api::inlineKeyboardButtonTypeWebApp>(button->type_); auto button_type = move_tl_object_as<td_api::inlineKeyboardButtonTypeWebApp>(button->type_);
auto user_id = LinkManager::get_link_user_id(button_type->url_); auto user_id = LinkManager::get_link_user_id(button_type->url_);
if (user_id.is_valid()) { if (user_id.is_valid()) {
return Status::Error(400, "Link to a user can't be used in web app URL buttons"); return Status::Error(400, "Link to a user can't be used in Web App URL buttons");
} }
auto r_url = LinkManager::check_link(button_type->url_, true, !G()->is_test_dc()); auto r_url = LinkManager::check_link(button_type->url_, true, !G()->is_test_dc());
if (r_url.is_error()) { if (r_url.is_error()) {
return Status::Error(400, PSLICE() << "Inline keyboard button web app URL '" << button_type->url_ return Status::Error(400, PSLICE() << "Inline keyboard button Web App " << r_url.error().message());
<< "' is invalid: " << r_url.error().message());
} }
current_button.type = InlineKeyboardButton::Type::WebView; current_button.type = InlineKeyboardButton::Type::WebView;
current_button.data = r_url.move_as_ok(); current_button.data = r_url.move_as_ok();
if (!clean_input_string(current_button.data)) { if (!clean_input_string(current_button.data)) {
return Status::Error(400, "Inline keyboard button web app URL must be encoded in UTF-8"); return Status::Error(400, "Inline keyboard button Web App URL must be encoded in UTF-8");
} }
break; break;
} }