Move check_url to LinkManager.

This commit is contained in:
levlam 2021-05-25 02:53:25 +03:00
parent 62db52a23e
commit 198af82254
6 changed files with 67 additions and 62 deletions

View File

@ -13,7 +13,9 @@
#include "td/telegram/telegram_api.h"
#include "td/utils/buffer.h"
#include "td/utils/HttpUrl.h"
#include "td/utils/logging.h"
#include "td/utils/SliceBuilder.h"
namespace td {
@ -155,6 +157,52 @@ void LinkManager::tear_down() {
parent_.reset();
}
static bool tolower_begins_with(Slice str, Slice prefix) {
if (prefix.size() > str.size()) {
return false;
}
for (size_t i = 0; i < prefix.size(); i++) {
if (to_lower(str[i]) != prefix[i]) {
return false;
}
}
return true;
}
Result<string> LinkManager::check_link(Slice link) {
bool is_tg = false;
bool is_ton = false;
if (tolower_begins_with(link, "tg:")) {
link.remove_prefix(3);
is_tg = true;
} else if (tolower_begins_with(link, "ton:")) {
link.remove_prefix(4);
is_ton = true;
}
if ((is_tg || is_ton) && begins_with(link, "//")) {
link.remove_prefix(2);
}
TRY_RESULT(http_url, parse_url(link));
if (is_tg || is_ton) {
if (tolower_begins_with(link, "http://") || http_url.protocol_ == HttpUrl::Protocol::Https ||
!http_url.userinfo_.empty() || http_url.specified_port_ != 0 || http_url.is_ipv6_) {
return Status::Error(is_tg ? Slice("Wrong tg URL") : Slice("Wrong ton URL"));
}
Slice query(http_url.query_);
CHECK(query[0] == '/');
if (query[1] == '?') {
query.remove_prefix(1);
}
return PSTRING() << (is_tg ? "tg" : "ton") << "://" << http_url.host_ << query;
}
if (http_url.host_.find('.') == string::npos && !http_url.is_ipv6_) {
return Status::Error("Wrong HTTP URL");
}
return http_url.get_url();
}
void LinkManager::get_login_url_info(DialogId dialog_id, MessageId message_id, int32 button_id,
Promise<td_api::object_ptr<td_api::LoginUrlInfo>> &&promise) {
TRY_RESULT_PROMISE(promise, url, td_->messages_manager_->get_login_button_url(dialog_id, message_id, button_id));

View File

@ -14,6 +14,8 @@
#include "td/actor/PromiseFuture.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
namespace td {
@ -29,6 +31,9 @@ class LinkManager : public Actor {
LinkManager &operator=(LinkManager &&) = delete;
~LinkManager() override;
// checks whether link is a valid tg, ton or HTTP(S) URL and returns it in a canonical form
static Result<string> check_link(Slice link);
void get_login_url_info(DialogId dialog_id, MessageId message_id, int32 button_id,
Promise<td_api::object_ptr<td_api::LoginUrlInfo>> &&promise);

View File

@ -8,6 +8,7 @@
#include "td/telegram/ContactsManager.h"
#include "td/telegram/Dependencies.h"
#include "td/telegram/LinkManager.h"
#include "td/telegram/misc.h"
#include "td/telegram/SecretChatActor.h"
@ -1676,7 +1677,7 @@ Result<vector<MessageEntity>> parse_markdown(string &text) {
if (user_id.is_valid()) {
entities.emplace_back(entity_offset, entity_length, user_id);
} else {
auto r_url = check_url(url);
auto r_url = LinkManager::check_link(url);
if (r_url.is_ok()) {
entities.emplace_back(MessageEntity::Type::TextUrl, entity_offset, entity_length, r_url.move_as_ok());
}
@ -1880,7 +1881,7 @@ static Result<vector<MessageEntity>> do_parse_markdown_v2(CSlice text, string &r
}
user_id = get_link_user_id(url);
if (!user_id.is_valid()) {
auto r_url = check_url(url);
auto r_url = LinkManager::check_link(url);
if (r_url.is_error()) {
skip_entity = true;
} else {
@ -1957,7 +1958,7 @@ static vector<Slice> find_text_url_entities_v3(Slice text) {
if (url_end < size) {
Slice url = text.substr(url_begin + 1, url_end - url_begin - 1);
if (check_url(url).is_ok()) {
if (LinkManager::check_link(url).is_ok()) {
result.push_back(text.substr(text_begin, text_end - text_begin + 1));
result.push_back(text.substr(url_begin, url_end - url_begin + 1));
}
@ -2029,7 +2030,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);
auto url_utf16_length = text_length(url);
result.entities.emplace_back(MessageEntity::Type::TextUrl, result_text_utf16_length, text_url_utf16_length,
check_url(url).move_as_ok());
LinkManager::check_link(url).move_as_ok());
result.text.append(text_url.begin(), text_url.size());
result_text_utf16_length += text_url_utf16_length;
@ -2832,7 +2833,7 @@ static Result<vector<MessageEntity>> do_parse_html(CSlice text, string &result)
if (user_id.is_valid()) {
entities.emplace_back(entity_offset, entity_length, user_id);
} else {
auto r_url = check_url(url);
auto r_url = LinkManager::check_link(url);
if (r_url.is_ok()) {
entities.emplace_back(MessageEntity::Type::TextUrl, entity_offset, entity_length, r_url.move_as_ok());
}
@ -3026,7 +3027,7 @@ 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_url = check_url(entity_text_url->url_);
auto r_url = LinkManager::check_link(entity_text_url->url_);
if (r_url.is_error()) {
return Status::Error(400, PSTRING() << "Wrong message entity: " << r_url.error().message());
}
@ -3146,7 +3147,7 @@ vector<MessageEntity> get_message_entities(const ContactsManager *contacts_manag
}
case telegram_api::messageEntityTextUrl::ID: {
auto entity_text_url = static_cast<const telegram_api::messageEntityTextUrl *>(entity.get());
auto r_url = check_url(entity_text_url->url_);
auto r_url = LinkManager::check_link(entity_text_url->url_);
if (r_url.is_error()) {
LOG(ERROR) << "Wrong URL entity: \"" << entity_text_url->url_ << "\": " << r_url.error().message() << " from "
<< source;
@ -3268,7 +3269,7 @@ vector<MessageEntity> get_message_entities(vector<tl_object_ptr<secret_api::Mess
LOG(WARNING) << "Wrong URL entity: \"" << entity_text_url->url_ << '"';
continue;
}
auto r_url = check_url(entity_text_url->url_);
auto r_url = LinkManager::check_link(entity_text_url->url_);
if (r_url.is_error()) {
LOG(WARNING) << "Wrong URL entity: \"" << entity_text_url->url_ << "\": " << r_url.error().message();
continue;

View File

@ -8,6 +8,7 @@
#include "td/telegram/ContactsManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/LinkManager.h"
#include "td/telegram/misc.h"
#include "td/telegram/Td.h"
#include "td/telegram/td_api.h"
@ -425,8 +426,9 @@ 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_ASSIGN(current_button.data,
check_url(static_cast<const td_api::inlineKeyboardButtonTypeUrl *>(button->type_.get())->url_));
TRY_RESULT_ASSIGN(
current_button.data,
LinkManager::check_link(static_cast<const td_api::inlineKeyboardButtonTypeUrl *>(button->type_.get())->url_));
if (!clean_input_string(current_button.data)) {
return Status::Error(400, "Inline keyboard button url must be encoded in UTF-8");
}
@ -467,7 +469,7 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
case td_api::inlineKeyboardButtonTypeLoginUrl::ID: {
current_button.type = InlineKeyboardButton::Type::UrlAuth;
auto login_url = td_api::move_object_as<td_api::inlineKeyboardButtonTypeLoginUrl>(button->type_);
TRY_RESULT_ASSIGN(current_button.data, check_url(login_url->url_));
TRY_RESULT_ASSIGN(current_button.data, LinkManager::check_link(login_url->url_));
current_button.forward_text = std::move(login_url->forward_text_);
if (!clean_input_string(current_button.data)) {
return Status::Error(400, "Inline keyboard button login url must be encoded in UTF-8");

View File

@ -8,10 +8,8 @@
#include "td/utils/algorithm.h"
#include "td/utils/common.h"
#include "td/utils/HttpUrl.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
#include "td/utils/utf8.h"
#include <cstring>
@ -306,52 +304,6 @@ string get_emoji_fingerprint(uint64 num) {
return emojis[static_cast<size_t>((num & 0x7FFFFFFFFFFFFFFF) % emojis.size())].str();
}
static bool tolower_begins_with(Slice str, Slice prefix) {
if (prefix.size() > str.size()) {
return false;
}
for (size_t i = 0; i < prefix.size(); i++) {
if (to_lower(str[i]) != prefix[i]) {
return false;
}
}
return true;
}
Result<string> check_url(Slice url) {
bool is_tg = false;
bool is_ton = false;
if (tolower_begins_with(url, "tg:")) {
url.remove_prefix(3);
is_tg = true;
} else if (tolower_begins_with(url, "ton:")) {
url.remove_prefix(4);
is_ton = true;
}
if ((is_tg || is_ton) && begins_with(url, "//")) {
url.remove_prefix(2);
}
TRY_RESULT(http_url, parse_url(url));
if (is_tg || is_ton) {
if (tolower_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(is_tg ? Slice("Wrong tg URL") : Slice("Wrong ton URL"));
}
Slice query(http_url.query_);
CHECK(query[0] == '/');
if (query[1] == '?') {
query.remove_prefix(1);
}
return PSTRING() << (is_tg ? "tg" : "ton") << "://" << http_url.host_ << query;
}
if (http_url.host_.find('.') == string::npos && !http_url.is_ipv6_) {
return Status::Error("Wrong HTTP URL");
}
return http_url.get_url();
}
string remove_emoji_modifiers(string emoji) {
static const Slice modifiers[] = {u8"\uFE0E" /* variation selector-15 */,
u8"\uFE0F" /* variation selector-16 */,

View File

@ -36,9 +36,6 @@ 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, ton or HTTP(S) URL and returns it in a canonical form
Result<string> check_url(Slice url);
// removes all emoji modifiers
string remove_emoji_modifiers(string emoji);