telegram.me links open without confirmation box.

EmailClickHandler removed, only UrlClickHandler left.
Some errors lead to @spambot instead of site FAQ.
This commit is contained in:
John Preston 2016-04-06 17:19:25 +04:00
parent 1947d8e5be
commit 730dce2cdc
9 changed files with 80 additions and 86 deletions

View File

@ -118,7 +118,7 @@ void ConfirmBox::updateHover() {
QPoint m(mapFromGlobal(_lastMousePos));
textstyleSet(&st::boxTextStyle);
ClickHandlerPtr handler = _text.linkLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width(), (_text.maxWidth() < width()) ? style::al_center : style::al_left);
ClickHandlerPtr handler = _text.linkLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width(), style::al_left);
textstyleRestore();
ClickHandler::setActive(handler, this);
@ -183,11 +183,7 @@ ConfirmLinkBox::ConfirmLinkBox(const QString &url) : ConfirmBox(lang(lng_open_th
void ConfirmLinkBox::onOpenLink() {
Ui::hideLayer();
if (reMailStart().match(_url).hasMatch()) {
EmailClickHandler::doOpen(_url);
} else {
UrlClickHandler::doOpen(_url);
}
UrlClickHandler::doOpen(_url);
}
MaxInviteBox::MaxInviteBox(const QString &link) : AbstractBox(st::boxWidth)

View File

@ -33,6 +33,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "confirmbox.h"
QString cantInviteError() {
return lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.me/spambot"), lang(lng_cant_more_info)));
}
ContactsInner::ContactsInner(CreatingGroupType creating) : TWidget()
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _newItemHeight(creating == CreatingGroupNone ? st::contactsNewItemHeight : 0)
@ -1776,7 +1780,7 @@ bool ContactsBox::creationFail(const RPCError &error) {
_filter.showError();
return true;
} else if (error.type() == "PEER_FLOOD") {
Ui::showLayer(new InformBox(lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.org/faq?_hash=can-39t-send-messages-to-non-contacts"), lang(lng_cant_more_info)))), KeepOtherLayers);
Ui::showLayer(new InformBox(cantInviteError()), KeepOtherLayers);
return true;
} else if (error.type() == qstr("USER_RESTRICTED")) {
Ui::showLayer(new InformBox(lang(lng_cant_do_this)));

View File

@ -28,6 +28,8 @@ enum MembersFilter {
};
typedef QMap<UserData*, bool> MembersAlreadyIn;
QString cantInviteError();
class ConfirmBox;
class ContactsInner : public TWidget, public RPCSender {
Q_OBJECT
@ -51,7 +53,7 @@ public:
void mouseMoveEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
void resizeEvent(QResizeEvent *e);
void paintDialog(Painter &p, PeerData *peer, ContactData *data, bool sel);
void updateFilter(QString filter = QString());
@ -136,7 +138,7 @@ private:
UserData *_addAdmin;
mtpRequestId _addAdminRequestId;
ConfirmBox *_addAdminBox;
int32 _time;
DialogsIndexed *_contacts;

View File

@ -808,10 +808,8 @@ public:
} else {
lnk.reset(new HashtagClickHandler(data.url));
}
} else if (data.fullDisplayed < 0) { // email
lnk.reset(new EmailClickHandler(data.url));
} else {
lnk.reset(new UrlClickHandler(data.url, data.fullDisplayed > 0));
} else { // email or url
lnk.reset(new UrlClickHandler(data.url, data.fullDisplayed != 0));
}
_t->setLink(lnkIndex, lnk);
}
@ -959,52 +957,64 @@ namespace {
}
QString UrlClickHandler::copyToClipboardContextItem() const {
return lang(lng_context_copy_link);
return lang(isEmail() ? lng_context_copy_email : lng_context_copy_link);
}
void UrlClickHandler::doOpen(QString url) {
PopupTooltip::Hide();
namespace {
QString tryConvertUrlToLocal(const QString &url) {
QRegularExpressionMatch telegramMeUser = QRegularExpression(qsl("^https?://telegram\\.me/([a-zA-Z0-9\\.\\_]+)(/?\\?|/?$|/(\\d+)/?(?:\\?|$))"), QRegularExpression::CaseInsensitiveOption).match(url);
QRegularExpressionMatch telegramMeGroup = QRegularExpression(qsl("^https?://telegram\\.me/joinchat/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url);
QRegularExpressionMatch telegramMeStickers = QRegularExpression(qsl("^https?://telegram\\.me/addstickers/([a-zA-Z0-9\\.\\_]+)(\\?|$)"), QRegularExpression::CaseInsensitiveOption).match(url);
QRegularExpressionMatch telegramMeShareUrl = QRegularExpression(qsl("^https?://telegram\\.me/share/url\\?(.+)$"), QRegularExpression::CaseInsensitiveOption).match(url);
if (telegramMeGroup.hasMatch()) {
url = qsl("tg://join?invite=") + myUrlEncode(telegramMeGroup.captured(1));
return qsl("tg://join?invite=") + myUrlEncode(telegramMeGroup.captured(1));
} else if (telegramMeStickers.hasMatch()) {
url = qsl("tg://addstickers?set=") + myUrlEncode(telegramMeStickers.captured(1));
return qsl("tg://addstickers?set=") + myUrlEncode(telegramMeStickers.captured(1));
} else if (telegramMeShareUrl.hasMatch()) {
url = qsl("tg://msg_url?") + telegramMeShareUrl.captured(1);
return qsl("tg://msg_url?") + telegramMeShareUrl.captured(1);
} else if (telegramMeUser.hasMatch()) {
QString params = url.mid(telegramMeUser.captured(0).size()), postParam;
if (QRegularExpression(qsl("^/\\d+/?(?:\\?|$)")).match(telegramMeUser.captured(2)).hasMatch()) {
postParam = qsl("&post=") + telegramMeUser.captured(3);
}
url = qsl("tg://resolve/?domain=") + myUrlEncode(telegramMeUser.captured(1)) + postParam + (params.isEmpty() ? QString() : '&' + params);
return qsl("tg://resolve/?domain=") + myUrlEncode(telegramMeUser.captured(1)) + postParam + (params.isEmpty() ? QString() : '&' + params);
}
return url;
}
} // namespace
void UrlClickHandler::doOpen(QString url) {
PopupTooltip::Hide();
if (isEmail(url)) {
QUrl u(qstr("mailto:") + url);
if (!QDesktopServices::openUrl(u)) {
psOpenFile(u.toString(QUrl::FullyEncoded), true);
}
return;
}
if (QRegularExpression(qsl("^tg://[a-zA-Z0-9]+"), QRegularExpression::CaseInsensitiveOption).match(url).hasMatch()) {
url = tryConvertUrlToLocal(url);
if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
App::openLocalUrl(url);
} else {
QDesktopServices::openUrl(url);
}
}
QString EmailClickHandler::copyToClipboardContextItem() const {
return lang(lng_context_copy_email);
}
void EmailClickHandler::doOpen(QString email) {
PopupTooltip::Hide();
QUrl url(qstr("mailto:") + email);
if (!QDesktopServices::openUrl(url)) {
psOpenFile(url.toString(QUrl::FullyEncoded), true);
}
}
void HiddenUrlClickHandler::onClick(Qt::MouseButton button) const {
Ui::showLayer(new ConfirmLinkBox(url()));
QString u = url();
u = tryConvertUrlToLocal(u);
if (u.startsWith(qstr("tg://"))) {
App::openLocalUrl(u);
} else {
Ui::showLayer(new ConfirmLinkBox(u));
}
}
QString LocationClickHandler::copyToClipboardContextItem() const {
@ -1333,10 +1343,11 @@ public:
}
const ClickHandlerPtr &link(int32 x, int32 y, int32 w, style::align align) {
static const ClickHandlerPtr *zero = new ClickHandlerPtr(); // won't be deleted
StaticNeverFreedPointer<ClickHandlerPtr> zero(new ClickHandlerPtr());
_lnkX = x;
_lnkY = y;
_lnkResult = zero;
_lnkResult = zero.data();
if (!_t->isNull() && _lnkX >= 0 && _lnkX < w && _lnkY >= 0) {
draw(0, 0, w, align, _lnkY, _lnkY + 1);
}

View File

@ -481,8 +481,12 @@ protected:
class UrlClickHandler : public TextClickHandler {
public:
UrlClickHandler(const QString &url, bool fullDisplayed = true) : TextClickHandler(fullDisplayed), _url(url) {
QUrl u(_url), good(u.isValid() ? u.toEncoded() : QString());
_readable = good.isValid() ? good.toDisplayString() : _url;
if (isEmail()) {
_readable = _url;
} else {
QUrl u(_url), good(u.isValid() ? u.toEncoded() : QString());
_readable = good.isValid() ? good.toDisplayString() : _url;
}
}
QString copyToClipboardContextItem() const override;
@ -502,6 +506,10 @@ public:
protected:
QString url() const override {
if (isEmail()) {
return _url;
}
QUrl u(_url), good(u.isValid() ? u.toEncoded() : QString());
QString result(good.isValid() ? QString::fromUtf8(good.toEncoded()) : _url);
@ -515,6 +523,14 @@ protected:
}
private:
static bool isEmail(const QString &url) {
int at = url.indexOf('@'), slash = url.indexOf('/');
return ((at > 0) && (slash < 0 || slash > at));
}
bool isEmail() const {
return isEmail(_url);
}
QString _url, _readable;
};
@ -528,41 +544,6 @@ public:
};
class EmailClickHandler : public TextClickHandler {
public:
EmailClickHandler(const QString &email) : _email(email) {
}
QString copyToClipboardContextItem() const override;
QString text() const override {
return _email;
}
static void doOpen(QString email);
void onClick(Qt::MouseButton button) const override {
if (button == Qt::LeftButton || button == Qt::MiddleButton) {
doOpen(_email);
}
}
protected:
QString url() const override {
return _email;
}
private:
QString _email;
};
inline TextClickHandlerPtr clickHandlerFromUrl(const QString &url) {
int32 at = url.indexOf('@'), slash = url.indexOf('/');
if ((at > 0) && (slash < 0 || slash > at)) {
return MakeShared<EmailClickHandler>(url);
}
return MakeShared<UrlClickHandler>(url);
}
struct LocationCoords {
LocationCoords() : lat(0), lon(0) {
}

View File

@ -138,14 +138,14 @@ QString ItemBase::getResultUrl() const {
ClickHandlerPtr ItemBase::getResultUrlHandler() const {
if (!_result->_url.isEmpty()) {
return clickHandlerFromUrl(_result->_url);
return MakeShared<UrlClickHandler>(_result->_url);
}
return ClickHandlerPtr();
}
ClickHandlerPtr ItemBase::getResultContentUrlHandler() const {
if (!_result->_content_url.isEmpty()) {
return clickHandlerFromUrl(_result->_content_url);
return MakeShared<UrlClickHandler>(_result->_content_url);
}
return ClickHandlerPtr();
}

View File

@ -1109,17 +1109,17 @@ LayoutOverviewLink::LayoutOverviewLink(HistoryMedia *media, HistoryItem *parent)
_photol.reset(new DocumentOpenClickHandler(_page->doc));
} else if (_page->photo) {
if (_page->type == WebPageProfile || _page->type == WebPageVideo) {
_photol = clickHandlerFromUrl(_page->url);
_photol = MakeShared<UrlClickHandler>(_page->url);
} else if (_page->type == WebPagePhoto || _page->siteName == qstr("Twitter") || _page->siteName == qstr("Facebook")) {
_photol.reset(new PhotoOpenClickHandler(_page->photo));
} else {
_photol = clickHandlerFromUrl(_page->url);
_photol = MakeShared<UrlClickHandler>(_page->url);
}
} else {
_photol = clickHandlerFromUrl(_page->url);
_photol = MakeShared<UrlClickHandler>(_page->url);
}
} else if (!_links.isEmpty()) {
_photol = clickHandlerFromUrl(_links.front().lnk->text());
_photol = MakeShared<UrlClickHandler>(_links.front().lnk->text());
}
if (from >= till && _page) {
text = _page->description;
@ -1318,5 +1318,5 @@ void LayoutOverviewLink::getState(ClickHandlerPtr &link, HistoryCursorState &cur
LayoutOverviewLink::Link::Link(const QString &url, const QString &text)
: text(text)
, width(st::normalFont->width(text))
, lnk(clickHandlerFromUrl(url)) {
, lnk(MakeShared<UrlClickHandler>(url)) {
}

View File

@ -1163,7 +1163,7 @@ bool MainWidget::addParticipantFail(UserData *user, const RPCError &error) {
} else if (error.type() == "USER_ALREADY_PARTICIPANT" && user->botInfo) {
text = lang(lng_bot_already_in_group);
} else if (error.type() == "PEER_FLOOD") {
text = lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.org/faq?_hash=can-39t-send-messages-to-non-contacts"), lang(lng_cant_more_info)));
text = cantInviteError();
}
Ui::showLayer(new InformBox(text));
return false;
@ -1181,7 +1181,7 @@ bool MainWidget::addParticipantsFail(ChannelData *channel, const RPCError &error
} else if (error.type() == "USER_NOT_MUTUAL_CONTACT") { // trying to return user who does not have me in contacts
text = lang(channel->isMegagroup() ? lng_failed_add_not_mutual : lng_failed_add_not_mutual_channel);
} else if (error.type() == "PEER_FLOOD") {
text = lng_cant_invite_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.org/faq?_hash=can-39t-send-messages-to-non-contacts"), lang(lng_cant_more_info)));
text = cantInviteError();
}
Ui::showLayer(new InformBox(text));
return false;
@ -1288,7 +1288,7 @@ bool MainWidget::sendMessageFail(const RPCError &error) {
if (mtpIsFlood(error)) return false;
if (error.type() == qsl("PEER_FLOOD")) {
Ui::showLayer(new InformBox(lng_cant_send_to_not_contact(lt_more_info, textcmdLink(qsl("https://telegram.org/faq?_hash=can-39t-send-messages-to-non-contacts"), lang(lng_cant_more_info)))));
Ui::showLayer(new InformBox(cantInviteError()));
return true;
}
return false;

View File

@ -1062,8 +1062,8 @@ bool Window::eventFilter(QObject *obj, QEvent *e) {
case QEvent::FileOpen:
if (obj == Application::instance()) {
QString url = static_cast<QFileOpenEvent*>(e)->url().toEncoded();
if (!url.trimmed().midRef(0, 5).compare(qsl("tg://"), Qt::CaseInsensitive)) {
QString url = static_cast<QFileOpenEvent*>(e)->url().toEncoded().trimmed();
if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
cSetStartUrl(url);
if (!cStartUrl().isEmpty() && App::main() && App::self()) {
App::main()->openLocalUrl(cStartUrl());