diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index 401a884d4..3f5d6591f 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -151,6 +151,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 "lng_sure_add_admin_unban" = "This user is currently restricted or banned in this group. Are you sure you want to unban and promote them?";
 "lng_sure_ban_admin" = "This user is an admin in this group. Are you sure you want to go ahead and restrict them?";
 "lng_sure_ban_user_group" = "Ban {user} in the group?";
+"lng_sure_enable_socks" = "Are you sure you want to enable this proxy?\n\nServer: {server}\nPort: {port}\n\nYou can change your proxy server later in the Settings (Connection Type).";
+"lng_sure_enable" = "Enable";
 
 "lng_edit_deleted" = "This message was deleted";
 "lng_edit_too_long" = "Your message text is too long";
diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp
index 0f221becc..c72829863 100644
--- a/Telegram/SourceFiles/application.cpp
+++ b/Telegram/SourceFiles/application.cpp
@@ -286,9 +286,7 @@ void Application::readClients() {
 	if (!startUrl.isEmpty()) {
 		cSetStartUrl(startUrl);
 	}
-	if (auto main = App::main()) {
-		main->checkStartUrl();
-	}
+	Messenger::Instance().checkStartUrl();
 }
 
 void Application::removeClients() {
diff --git a/Telegram/SourceFiles/boxes/connection_box.cpp b/Telegram/SourceFiles/boxes/connection_box.cpp
index fac3d96dc..3360fe373 100644
--- a/Telegram/SourceFiles/boxes/connection_box.cpp
+++ b/Telegram/SourceFiles/boxes/connection_box.cpp
@@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 */
 #include "boxes/connection_box.h"
 
+#include "boxes/confirm_box.h"
 #include "lang/lang_keys.h"
 #include "storage/localstorage.h"
 #include "mainwidget.h"
@@ -30,6 +31,30 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "history/history_location_manager.h"
 #include "styles/style_boxes.h"
 
+void ConnectionBox::ShowApplyProxyConfirmation(const QMap<QString, QString> &fields) {
+	auto server = fields.value(qsl("server"));
+	auto port = fields.value(qsl("port")).toInt();
+	if (!server.isEmpty() && port != 0) {
+		auto weakBox = std::make_shared<QPointer<ConfirmBox>>(nullptr);
+		auto box = Ui::show(Box<ConfirmBox>(lng_sure_enable_socks(lt_server, server, lt_port, QString::number(port)), lang(lng_sure_enable), [fields, weakBox] {
+			auto p = ProxyData();
+			p.host = fields.value(qsl("server"));
+			p.user = fields.value(qsl("user"));
+			p.password = fields.value(qsl("pass"));
+			p.port = fields.value(qsl("port")).toInt();
+			Global::SetConnectionType(dbictTcpProxy);
+			Global::SetConnectionProxy(p);
+			Local::writeSettings();
+			Global::RefConnectionTypeChanged().notify();
+			MTP::restart();
+			reinitLocationManager();
+			reinitWebLoadManager();
+			if (*weakBox) (*weakBox)->closeBox();
+		}), KeepOtherLayers);
+		*weakBox = box;
+	}
+}
+
 ConnectionBox::ConnectionBox(QWidget *parent)
 : _hostInput(this, st::connectionHostInputField, langFactory(lng_connection_host_ph), Global::ConnectionProxy().host)
 , _portInput(this, st::connectionPortInputField, langFactory(lng_connection_port_ph), QString::number(Global::ConnectionProxy().port))
diff --git a/Telegram/SourceFiles/boxes/connection_box.h b/Telegram/SourceFiles/boxes/connection_box.h
index d93fe460a..db4d0a221 100644
--- a/Telegram/SourceFiles/boxes/connection_box.h
+++ b/Telegram/SourceFiles/boxes/connection_box.h
@@ -39,6 +39,8 @@ class ConnectionBox : public BoxContent {
 public:
 	ConnectionBox(QWidget *parent);
 
+	static void ShowApplyProxyConfirmation(const QMap<QString, QString> &fields);
+
 protected:
 	void prepare() override;
 	void setInnerFocus() override;
diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp
index d41fcaec4..6de786b7f 100644
--- a/Telegram/SourceFiles/boxes/share_box.cpp
+++ b/Telegram/SourceFiles/boxes/share_box.cpp
@@ -809,7 +809,7 @@ QVector<PeerData*> ShareBox::Inner::selected() const {
 	return result;
 }
 
-QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
+QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
 	auto shareHashData = QByteArray(0x10, Qt::Uninitialized);
 	auto shareHashDataInts = reinterpret_cast<int32*>(shareHashData.data());
 	auto channel = fullId.channel ? App::channelLoaded(fullId.channel) : static_cast<ChannelData*>(nullptr);
@@ -854,7 +854,7 @@ QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
 
 namespace {
 
-void shareGameScoreFromItem(HistoryItem *item) {
+void ShareGameScoreFromItem(HistoryItem *item) {
 	struct ShareGameScoreData {
 		ShareGameScoreData(const FullMsgId &msgId) : msgId(msgId) {
 		}
@@ -949,7 +949,7 @@ void shareGameScoreFromItem(HistoryItem *item) {
 
 } // namespace
 
-void shareGameScoreByHash(const QString &hash) {
+void ShareGameScoreByHash(const QString &hash) {
 	auto key128Size = 0x10;
 
 	auto hashEncrypted = QByteArray::fromBase64(hash.toLatin1(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
@@ -1000,12 +1000,12 @@ void shareGameScoreByHash(const QString &hash) {
 	}
 
 	if (auto item = App::histItemById(channelId, msgId)) {
-		shareGameScoreFromItem(item);
+		ShareGameScoreFromItem(item);
 	} else if (App::api()) {
 		auto resolveMessageAndShareScore = [msgId](ChannelData *channel) {
 			App::api()->requestMessageData(channel, msgId, [](ChannelData *channel, MsgId msgId) {
 				if (auto item = App::histItemById(channel, msgId)) {
-					shareGameScoreFromItem(item);
+					ShareGameScoreFromItem(item);
 				} else {
 					Ui::show(Box<InformBox>(lang(lng_edit_deleted)));
 				}
diff --git a/Telegram/SourceFiles/boxes/share_box.h b/Telegram/SourceFiles/boxes/share_box.h
index 00b3d586c..b4861b279 100644
--- a/Telegram/SourceFiles/boxes/share_box.h
+++ b/Telegram/SourceFiles/boxes/share_box.h
@@ -37,8 +37,8 @@ namespace Ui {
 class MultiSelect;
 } // namespace Ui
 
-QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId);
-void shareGameScoreByHash(const QString &hash);
+QString AppendShareGameScoreUrl(const QString &url, const FullMsgId &fullId);
+void ShareGameScoreByHash(const QString &hash);
 
 class ShareBox : public BoxContent, public RPCSender {
 	Q_OBJECT
diff --git a/Telegram/SourceFiles/core/click_handler_types.cpp b/Telegram/SourceFiles/core/click_handler_types.cpp
index d75389c9c..5f599644e 100644
--- a/Telegram/SourceFiles/core/click_handler_types.cpp
+++ b/Telegram/SourceFiles/core/click_handler_types.cpp
@@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "core/click_handler_types.h"
 
 #include "lang/lang_keys.h"
+#include "messenger.h"
 #include "platform/platform_specific.h"
 #include "boxes/confirm_box.h"
 #include "base/qthelp_regex.h"
@@ -58,6 +59,8 @@ QString tryConvertUrlToLocal(QString url) {
 				|| previewedUrl.startsWith(qstr("https://"), Qt::CaseInsensitive)) {
 				return previewedUrl;
 			}
+		} else if (auto socksMatch = regex_match(qsl("socks/?\\?(.+)(#|$)"), query, matchOptions)) {
+			return qsl("tg://socks?") + socksMatch->captured(1);
 		} else if (auto usernameMatch = regex_match(qsl("^([a-zA-Z0-9\\.\\_]+)(/?\\?|/?$|/(\\d+)/?(?:\\?|$))"), query, matchOptions)) {
 			auto params = query.mid(usernameMatch->captured(0).size()).toString();
 			auto postParam = QString();
@@ -83,7 +86,7 @@ void UrlClickHandler::doOpen(QString url) {
 	url = tryConvertUrlToLocal(url);
 
 	if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
-		App::openLocalUrl(url);
+		Messenger::Instance().openLocalUrl(url);
 	} else {
 		QDesktopServices::openUrl(url);
 	}
@@ -113,7 +116,7 @@ void HiddenUrlClickHandler::doOpen(QString url) {
 	auto urlText = tryConvertUrlToLocal(url);
 
 	if (urlText.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
-		App::openLocalUrl(urlText);
+		Messenger::Instance().openLocalUrl(urlText);
 	} else {
 		auto parsedUrl = QUrl::fromUserInput(urlText);
 		auto displayUrl = parsedUrl.isValid() ? parsedUrl.toDisplayString() : urlText;
@@ -128,7 +131,7 @@ void BotGameUrlClickHandler::onClick(Qt::MouseButton button) const {
 	auto urlText = tryConvertUrlToLocal(url());
 
 	if (urlText.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
-		App::openLocalUrl(urlText);
+		Messenger::Instance().openLocalUrl(urlText);
 	} else if (!_bot || _bot->isVerified() || Local::isBotTrusted(_bot)) {
 		doOpen(urlText);
 	} else {
diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp
index ad5754db6..19122e3c6 100644
--- a/Telegram/SourceFiles/facades.cpp
+++ b/Telegram/SourceFiles/facades.cpp
@@ -167,10 +167,6 @@ void stickersBox(const QString &name) {
 	if (MainWidget *m = main()) m->stickersBox(MTP_inputStickerSetShortName(MTP_string(name)));
 }
 
-void openLocalUrl(const QString &url) {
-	if (MainWidget *m = main()) m->openLocalUrl(url);
-}
-
 bool forward(const PeerId &peer, ForwardWhatMessages what) {
 	if (MainWidget *m = main()) return m->onForward(peer, what);
 	return false;
diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h
index 60d9be41e..9002cfd04 100644
--- a/Telegram/SourceFiles/facades.h
+++ b/Telegram/SourceFiles/facades.h
@@ -73,7 +73,6 @@ void searchByHashtag(const QString &tag, PeerData *inPeer);
 void openPeerByName(const QString &username, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
 void joinGroupByHash(const QString &hash);
 void stickersBox(const QString &name);
-void openLocalUrl(const QString &url);
 bool forward(const PeerId &peer, ForwardWhatMessages what);
 void removeDialog(History *history);
 void showSettings();
diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index 8868401f2..00d8a0c23 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -3510,7 +3510,7 @@ void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotC
 		} else if (answerData.has_url()) {
 			auto url = qs(answerData.vurl);
 			if (info.game) {
-				url = appendShareGameScoreUrl(url, info.msgId);
+				url = AppendShareGameScoreUrl(url, info.msgId);
 				BotGameUrlClickHandler(info.bot, url).onClick(Qt::LeftButton);
 				if (item && (!item->history()->peer->isChannel() || item->history()->peer->isMegagroup())) {
 					updateSendAction(item->history(), SendAction::Type::PlayGame);
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index 823686d4b..d6b9b0601 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -51,8 +51,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "boxes/sticker_set_box.h"
 #include "boxes/contacts_box.h"
 #include "boxes/download_path_box.h"
-#include "boxes/confirm_phone_box.h"
-#include "boxes/share_box.h"
 #include "storage/localstorage.h"
 #include "shortcuts.h"
 #include "media/media_audio.h"
@@ -4088,81 +4086,13 @@ void MainWidget::start(const MTPUser *self) {
 	Local::readSavedGifs();
 	_history->start();
 
-	checkStartUrl();
+	Messenger::Instance().checkStartUrl();
 }
 
 bool MainWidget::started() {
 	return _started;
 }
 
-void MainWidget::checkStartUrl() {
-	if (!cStartUrl().isEmpty() && App::self() && !App::passcoded()) {
-		auto url = cStartUrl();
-		cSetStartUrl(QString());
-
-		openLocalUrl(url);
-	}
-}
-
-void MainWidget::openLocalUrl(const QString &url) {
-	auto urlTrimmed = url.trimmed();
-	if (urlTrimmed.size() > 8192) urlTrimmed = urlTrimmed.mid(0, 8192);
-
-	if (!urlTrimmed.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
-		return;
-	}
-	auto command = urlTrimmed.midRef(qstr("tg://").size());
-
-	using namespace qthelp;
-	auto matchOptions = RegExOption::CaseInsensitive;
-	if (auto joinChatMatch = regex_match(qsl("^join/?\\?invite=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"), command, matchOptions)) {
-		joinGroupByHash(joinChatMatch->captured(1));
-	} else if (auto stickerSetMatch = regex_match(qsl("^addstickers/?\\?set=([a-zA-Z0-9\\.\\_]+)(&|$)"), command, matchOptions)) {
-		stickersBox(MTP_inputStickerSetShortName(MTP_string(stickerSetMatch->captured(1))));
-	} else if (auto shareUrlMatch = regex_match(qsl("^msg_url/?\\?(.+)(#|$)"), command, matchOptions)) {
-		auto params = url_parse_params(shareUrlMatch->captured(1), UrlParamNameTransform::ToLower);
-		auto url = params.value(qsl("url"));
-		if (!url.isEmpty()) {
-			shareUrlLayer(url, params.value("text"));
-		}
-	} else if (auto confirmPhoneMatch = regex_match(qsl("^confirmphone/?\\?(.+)(#|$)"), command, matchOptions)) {
-		auto params = url_parse_params(confirmPhoneMatch->captured(1), UrlParamNameTransform::ToLower);
-		auto phone = params.value(qsl("phone"));
-		auto hash = params.value(qsl("hash"));
-		if (!phone.isEmpty() && !hash.isEmpty()) {
-			ConfirmPhoneBox::start(phone, hash);
-		}
-	} else if (auto usernameMatch = regex_match(qsl("^resolve/?\\?(.+)(#|$)"), command, matchOptions)) {
-		auto params = url_parse_params(usernameMatch->captured(1), UrlParamNameTransform::ToLower);
-		auto domain = params.value(qsl("domain"));
-		if (regex_match(qsl("^[a-zA-Z0-9\\.\\_]+$"), domain, matchOptions)) {
-			auto start = qsl("start");
-			auto startToken = params.value(start);
-			if (startToken.isEmpty()) {
-				start = qsl("startgroup");
-				startToken = params.value(start);
-				if (startToken.isEmpty()) {
-					start = QString();
-				}
-			}
-			auto post = (start == qsl("startgroup")) ? ShowAtProfileMsgId : ShowAtUnreadMsgId;
-			auto postParam = params.value(qsl("post"));
-			if (auto postId = postParam.toInt()) {
-				post = postId;
-			}
-			auto gameParam = params.value(qsl("game"));
-			if (!gameParam.isEmpty() && regex_match(qsl("^[a-zA-Z0-9\\.\\_]+$"), gameParam, matchOptions)) {
-				startToken = gameParam;
-				post = ShowAtGameShareMsgId;
-			}
-			openPeerByName(domain, post, startToken);
-		}
-	} else if (auto shareGameScoreMatch = regex_match(qsl("^share_game_score/?\\?(.+)(#|$)"), command, matchOptions)) {
-		auto params = url_parse_params(shareGameScoreMatch->captured(1), UrlParamNameTransform::ToLower);
-		shareGameScoreByHash(params.value(qsl("hash")));
-	}
-}
-
 void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QString &startToken) {
 	App::wnd()->hideMediaview();
 
diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h
index b5cfcbb92..bef68aa61 100644
--- a/Telegram/SourceFiles/mainwidget.h
+++ b/Telegram/SourceFiles/mainwidget.h
@@ -168,8 +168,6 @@ public:
 
 	void start(const MTPUser *self = nullptr);
 
-	void checkStartUrl();
-	void openLocalUrl(const QString &str);
 	void openPeerByName(const QString &name, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
 	void joinGroupByHash(const QString &hash);
 	void stickersBox(const MTPInputStickerSet &set);
diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp
index 3f279e141..1b4cd18f0 100644
--- a/Telegram/SourceFiles/mainwindow.cpp
+++ b/Telegram/SourceFiles/mainwindow.cpp
@@ -218,7 +218,7 @@ void MainWindow::clearPasscode() {
 	} else {
 		t_assert(_main != nullptr);
 		_main->showAnimated(bg, true);
-		_main->checkStartUrl();
+		Messenger::Instance().checkStartUrl();
 	}
 }
 
@@ -609,9 +609,7 @@ bool MainWindow::eventFilter(QObject *object, QEvent *e) {
 			QString url = static_cast<QFileOpenEvent*>(e)->url().toEncoded().trimmed();
 			if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
 				cSetStartUrl(url.mid(0, 8192));
-				if (_main) {
-					_main->checkStartUrl();
-				}
+				Messenger::Instance().checkStartUrl();
 			}
 			activate();
 		}
diff --git a/Telegram/SourceFiles/messenger.cpp b/Telegram/SourceFiles/messenger.cpp
index 4a6e53abe..173bdb3de 100644
--- a/Telegram/SourceFiles/messenger.cpp
+++ b/Telegram/SourceFiles/messenger.cpp
@@ -45,6 +45,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "ui/widgets/tooltip.h"
 #include "storage/serialize_common.h"
 #include "window/window_controller.h"
+#include "base/qthelp_regex.h"
+#include "base/qthelp_url.h"
+#include "boxes/connection_box.h"
+#include "boxes/confirm_phone_box.h"
+#include "boxes/share_box.h"
 
 namespace {
 
@@ -651,6 +656,98 @@ QString Messenger::createInternalLinkFull(const QString &query) const {
 	return Global::InternalLinksDomain() + query;
 }
 
+void Messenger::checkStartUrl() {
+	if (!cStartUrl().isEmpty() && !App::passcoded()) {
+		auto url = cStartUrl();
+		cSetStartUrl(QString());
+		if (!openLocalUrl(url)) {
+			cSetStartUrl(url);
+		}
+	}
+}
+
+bool Messenger::openLocalUrl(const QString &url) {
+	auto urlTrimmed = url.trimmed();
+	if (urlTrimmed.size() > 8192) urlTrimmed = urlTrimmed.mid(0, 8192);
+
+	if (!urlTrimmed.startsWith(qstr("tg://"), Qt::CaseInsensitive) || App::passcoded()) {
+		return false;
+	}
+	auto command = urlTrimmed.midRef(qstr("tg://").size());
+
+	using namespace qthelp;
+	auto matchOptions = RegExOption::CaseInsensitive;
+	if (auto joinChatMatch = regex_match(qsl("^join/?\\?invite=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"), command, matchOptions)) {
+		if (auto main = App::main()) {
+			main->joinGroupByHash(joinChatMatch->captured(1));
+			return true;
+		}
+	} else if (auto stickerSetMatch = regex_match(qsl("^addstickers/?\\?set=([a-zA-Z0-9\\.\\_]+)(&|$)"), command, matchOptions)) {
+		if (auto main = App::main()) {
+			main->stickersBox(MTP_inputStickerSetShortName(MTP_string(stickerSetMatch->captured(1))));
+			return true;
+		}
+	} else if (auto shareUrlMatch = regex_match(qsl("^msg_url/?\\?(.+)(#|$)"), command, matchOptions)) {
+		if (auto main = App::main()) {
+			auto params = url_parse_params(shareUrlMatch->captured(1), UrlParamNameTransform::ToLower);
+			auto url = params.value(qsl("url"));
+			if (!url.isEmpty()) {
+				main->shareUrlLayer(url, params.value("text"));
+				return true;
+			}
+		}
+	} else if (auto confirmPhoneMatch = regex_match(qsl("^confirmphone/?\\?(.+)(#|$)"), command, matchOptions)) {
+		if (auto main = App::main()) {
+			auto params = url_parse_params(confirmPhoneMatch->captured(1), UrlParamNameTransform::ToLower);
+			auto phone = params.value(qsl("phone"));
+			auto hash = params.value(qsl("hash"));
+			if (!phone.isEmpty() && !hash.isEmpty()) {
+				ConfirmPhoneBox::start(phone, hash);
+				return true;
+			}
+		}
+	} else if (auto usernameMatch = regex_match(qsl("^resolve/?\\?(.+)(#|$)"), command, matchOptions)) {
+		if (auto main = App::main()) {
+			auto params = url_parse_params(usernameMatch->captured(1), UrlParamNameTransform::ToLower);
+			auto domain = params.value(qsl("domain"));
+			if (regex_match(qsl("^[a-zA-Z0-9\\.\\_]+$"), domain, matchOptions)) {
+				auto start = qsl("start");
+				auto startToken = params.value(start);
+				if (startToken.isEmpty()) {
+					start = qsl("startgroup");
+					startToken = params.value(start);
+					if (startToken.isEmpty()) {
+						start = QString();
+					}
+				}
+				auto post = (start == qsl("startgroup")) ? ShowAtProfileMsgId : ShowAtUnreadMsgId;
+				auto postParam = params.value(qsl("post"));
+				if (auto postId = postParam.toInt()) {
+					post = postId;
+				}
+				auto gameParam = params.value(qsl("game"));
+				if (!gameParam.isEmpty() && regex_match(qsl("^[a-zA-Z0-9\\.\\_]+$"), gameParam, matchOptions)) {
+					startToken = gameParam;
+					post = ShowAtGameShareMsgId;
+				}
+				main->openPeerByName(domain, post, startToken);
+				return true;
+			}
+		}
+	} else if (auto shareGameScoreMatch = regex_match(qsl("^share_game_score/?\\?(.+)(#|$)"), command, matchOptions)) {
+		if (auto main = App::main()) {
+			auto params = url_parse_params(shareGameScoreMatch->captured(1), UrlParamNameTransform::ToLower);
+			ShareGameScoreByHash(params.value(qsl("hash")));
+			return true;
+		}
+	} else if (auto socksMatch = regex_match(qsl("^socks/?\\?(.+)(#|$)"), command, matchOptions)) {
+		auto params = url_parse_params(socksMatch->captured(1), UrlParamNameTransform::ToLower);
+		ConnectionBox::ShowApplyProxyConfirmation(params);
+		return true;
+	}
+	return false;
+}
+
 FileUploader *Messenger::uploader() {
 	if (!_uploader && !App::quitting()) _uploader = new FileUploader();
 	return _uploader;
diff --git a/Telegram/SourceFiles/messenger.h b/Telegram/SourceFiles/messenger.h
index f89cf105a..501c51231 100644
--- a/Telegram/SourceFiles/messenger.h
+++ b/Telegram/SourceFiles/messenger.h
@@ -128,9 +128,12 @@ public:
 		return *_audio;
 	}
 
+	// Internal links.
 	void setInternalLinkDomain(const QString &domain) const;
 	QString createInternalLink(const QString &query) const;
 	QString createInternalLinkFull(const QString &query) const;
+	void checkStartUrl();
+	bool openLocalUrl(const QString &url);
 
 	FileUploader *uploader();
 	void uploadProfilePhoto(const QImage &tosend, const PeerId &peerId);