Support multiple proxies in local storage.

This commit is contained in:
John Preston 2018-04-27 21:26:45 +04:00
parent 8e99135f37
commit 900d1ddb36
12 changed files with 205 additions and 146 deletions

View File

@ -313,9 +313,9 @@ void Application::refreshGlobalProxy() {
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY #ifndef TDESKTOP_DISABLE_NETWORK_PROXY
const auto proxy = [&] { const auto proxy = [&] {
if (Global::started()) { if (Global::started()) {
return Global::ConnectionType() == dbictAuto return Global::UseProxy()
? ProxyData() ? Global::SelectedProxy()
: Global::ConnectionProxy(); : ProxyData();
} }
return Sandbox::PreLaunchProxy(); return Sandbox::PreLaunchProxy();
}(); }();

View File

@ -28,14 +28,17 @@ void ConnectionBox::ShowApplyProxyConfirmation(
const QMap<QString, QString> &fields) { const QMap<QString, QString> &fields) {
const auto server = fields.value(qsl("server")); const auto server = fields.value(qsl("server"));
const auto port = fields.value(qsl("port")).toUInt(); const auto port = fields.value(qsl("port")).toUInt();
const auto secret = fields.value(qsl("secret")); auto proxy = ProxyData();
const auto valid = !server.isEmpty() proxy.type = type;
&& (port != 0) proxy.host = server;
&& (type != ProxyData::Type::Mtproto proxy.port = port;
|| ProxyData::ValidSecret(secret)) if (type == ProxyData::Type::Socks5) {
&& (type == ProxyData::Type::Socks5 proxy.user = fields.value(qsl("user"));
|| type == ProxyData::Type::Mtproto); proxy.password = fields.value(qsl("pass"));
if (valid) { } else if (type == ProxyData::Type::Mtproto) {
proxy.password = fields.value(qsl("secret"));
}
if (proxy) {
const auto box = std::make_shared<QPointer<ConfirmBox>>(); const auto box = std::make_shared<QPointer<ConfirmBox>>();
const auto text = lng_sure_enable_socks( const auto text = lng_sure_enable_socks(
lt_server, lt_server,
@ -43,18 +46,12 @@ void ConnectionBox::ShowApplyProxyConfirmation(
lt_port, lt_port,
QString::number(port)); QString::number(port));
*box = Ui::show(Box<ConfirmBox>(text, lang(lng_sure_enable), [=] { *box = Ui::show(Box<ConfirmBox>(text, lang(lng_sure_enable), [=] {
auto proxy = ProxyData(); auto &proxies = Global::RefProxiesList();
proxy.type = type; if (ranges::find(proxies, proxy) == end(proxies)) {
proxy.host = server; proxies.insert(begin(proxies), proxy);
proxy.port = port;
if (type == ProxyData::Type::Socks5) {
proxy.user = fields.value(qsl("user"));
proxy.password = fields.value(qsl("pass"));
} else if (type == ProxyData::Type::Mtproto) {
proxy.password = secret;
} }
Global::SetConnectionType(dbictTcpProxy); Global::SetSelectedProxy(proxy);
Global::SetConnectionProxy(proxy); Global::SetUseProxy(true);
Local::writeSettings(); Local::writeSettings();
Sandbox::refreshGlobalProxy(); Sandbox::refreshGlobalProxy();
Global::RefConnectionTypeChanged().notify(); Global::RefConnectionTypeChanged().notify();
@ -67,15 +64,14 @@ void ConnectionBox::ShowApplyProxyConfirmation(
} }
ConnectionBox::ConnectionBox(QWidget *parent) ConnectionBox::ConnectionBox(QWidget *parent)
: _hostInput(this, st::connectionHostInputField, langFactory(lng_connection_host_ph), Global::ConnectionProxy().host) : _hostInput(this, st::connectionHostInputField, langFactory(lng_connection_host_ph), Global::SelectedProxy().host)
, _portInput(this, st::connectionPortInputField, langFactory(lng_connection_port_ph), QString::number(Global::ConnectionProxy().port)) , _portInput(this, st::connectionPortInputField, langFactory(lng_connection_port_ph), QString::number(Global::SelectedProxy().port))
, _userInput(this, st::connectionUserInputField, langFactory(lng_connection_user_ph), Global::ConnectionProxy().user) , _userInput(this, st::connectionUserInputField, langFactory(lng_connection_user_ph), Global::SelectedProxy().user)
, _passwordInput(this, st::connectionPasswordInputField, langFactory(lng_connection_password_ph), Global::ConnectionProxy().password) , _passwordInput(this, st::connectionPasswordInputField, langFactory(lng_connection_password_ph), Global::SelectedProxy().password)
, _currentProxyType(Global::ConnectionProxy().type) , _typeGroup(std::make_shared<Ui::RadioenumGroup<Type>>(Global::SelectedProxy().type))
, _typeGroup(std::make_shared<Ui::RadioenumGroup<DBIConnectionType>>(Global::ConnectionType())) , _autoRadio(this, _typeGroup, Type::None, lang(lng_connection_auto_rb), st::defaultBoxCheckbox)
, _autoRadio(this, _typeGroup, dbictAuto, lang(lng_connection_auto_rb), st::defaultBoxCheckbox) , _httpProxyRadio(this, _typeGroup, Type::Http, lang(lng_connection_http_proxy_rb), st::defaultBoxCheckbox)
, _httpProxyRadio(this, _typeGroup, dbictHttpProxy, lang(lng_connection_http_proxy_rb), st::defaultBoxCheckbox) , _tcpProxyRadio(this, _typeGroup, Type::Socks5, lang(lng_connection_tcp_proxy_rb), st::defaultBoxCheckbox)
, _tcpProxyRadio(this, _typeGroup, dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), st::defaultBoxCheckbox)
, _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) { , _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) {
} }
@ -85,7 +81,7 @@ void ConnectionBox::prepare() {
addButton(langFactory(lng_connection_save), [this] { onSave(); }); addButton(langFactory(lng_connection_save), [this] { onSave(); });
addButton(langFactory(lng_cancel), [this] { closeBox(); }); addButton(langFactory(lng_cancel), [this] { closeBox(); });
_typeGroup->setChangedCallback([this](DBIConnectionType value) { typeChanged(value); }); _typeGroup->setChangedCallback([this](Type value) { typeChanged(value); });
connect(_hostInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_hostInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
connect(_portInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit())); connect(_portInput, SIGNAL(submitted(bool)), this, SLOT(onSubmit()));
@ -123,17 +119,15 @@ void ConnectionBox::updateControlsVisibility() {
} }
bool ConnectionBox::proxyFieldsVisible() const { bool ConnectionBox::proxyFieldsVisible() const {
return (_typeGroup->value() != dbictAuto) return (_typeGroup->value() == ProxyData::Type::Http
|| (!badProxyValue() || _typeGroup->value() == ProxyData::Type::Socks5);
&& (_currentProxyType == ProxyData::Type::Http
|| _currentProxyType == ProxyData::Type::Socks5));
} }
void ConnectionBox::setInnerFocus() { void ConnectionBox::setInnerFocus() {
if (_typeGroup->value() == dbictAuto) { if (proxyFieldsVisible()) {
setFocus();
} else {
_hostInput->setFocusFast(); _hostInput->setFocusFast();
} else {
setFocus();
} }
} }
@ -150,8 +144,8 @@ void ConnectionBox::updateControlsPosition() {
auto inputy = 0; auto inputy = 0;
auto fieldsVisible = proxyFieldsVisible(); auto fieldsVisible = proxyFieldsVisible();
auto fieldsBelowHttp = fieldsVisible && (type == dbictHttpProxy || (type == dbictAuto && _currentProxyType == ProxyData::Type::Http)); auto fieldsBelowHttp = fieldsVisible && (type == ProxyData::Type::Http);
auto fieldsBelowTcp = fieldsVisible && (type == dbictTcpProxy || (type == dbictAuto && _currentProxyType == ProxyData::Type::Socks5)); auto fieldsBelowTcp = fieldsVisible && (type == ProxyData::Type::Socks5);
if (fieldsBelowHttp) { if (fieldsBelowHttp) {
inputy = _httpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip; inputy = _httpProxyRadio->bottomNoMargins() + st::boxOptionInputSkip;
_tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListSkip); _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionInputSkip + 2 * _hostInput->height() + st::boxOptionListSkip);
@ -173,21 +167,16 @@ void ConnectionBox::updateControlsPosition() {
_tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y); _tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y);
} }
void ConnectionBox::typeChanged(DBIConnectionType type) { void ConnectionBox::typeChanged(Type type) {
if (type == dbictAuto) { if (!proxyFieldsVisible()) {
setFocus(); setFocus();
} }
updateControlsVisibility(); updateControlsVisibility();
if (type != dbictAuto) { if (proxyFieldsVisible()) {
_currentProxyType = (type == dbictTcpProxy)
? ProxyData::Type::Socks5
: (type == dbictHttpProxy)
? ProxyData::Type::Http
: ProxyData::Type::None;
if (!_hostInput->hasFocus() && !_portInput->hasFocus() && !_userInput->hasFocus() && !_passwordInput->hasFocus()) { if (!_hostInput->hasFocus() && !_portInput->hasFocus() && !_userInput->hasFocus() && !_passwordInput->hasFocus()) {
_hostInput->setFocusFast(); _hostInput->setFocusFast();
} }
if ((type == dbictHttpProxy) && !_portInput->getLastText().toInt()) { if ((type == Type::Http) && !_portInput->getLastText().toInt()) {
_portInput->setText(qsl("80")); _portInput->setText(qsl("80"));
_portInput->finishAnimating(); _portInput->finishAnimating();
} }
@ -196,11 +185,6 @@ void ConnectionBox::typeChanged(DBIConnectionType type) {
} }
void ConnectionBox::onFieldFocus() { void ConnectionBox::onFieldFocus() {
if (_currentProxyType == ProxyData::Type::Http) {
_typeGroup->setValue(dbictHttpProxy);
} else if (_currentProxyType == ProxyData::Type::Socks5) {
_typeGroup->setValue(dbictTcpProxy);
}
} }
void ConnectionBox::onSubmit() { void ConnectionBox::onSubmit() {
@ -240,12 +224,10 @@ void ConnectionBox::onSave() {
proxy.port = _portInput->getLastText().toUInt(); proxy.port = _portInput->getLastText().toUInt();
auto type = _typeGroup->value(); auto type = _typeGroup->value();
if (type == dbictAuto) { if (type == Type::None) {
if (proxy.host.isEmpty() || !proxy.port) { proxy = ProxyData();
proxy = ProxyData(); } else if (type == Type::Mtproto) {
} else { proxy = Global::SelectedProxy();
proxy.type = _currentProxyType;
}
} else { } else {
if (proxy.host.isEmpty()) { if (proxy.host.isEmpty()) {
_hostInput->showError(); _hostInput->showError();
@ -254,12 +236,10 @@ void ConnectionBox::onSave() {
_portInput->showError(); _portInput->showError();
return; return;
} }
proxy.type = (type == dbictTcpProxy) proxy.type = type;
? ProxyData::Type::Socks5
: ProxyData::Type::Http;
} }
Global::SetConnectionType(type); Global::SetSelectedProxy(proxy ? proxy : ProxyData());
Global::SetConnectionProxy(proxy); Global::SetUseProxy(proxy ? true : false);
if (cPlatform() == dbipWindows && Global::TryIPv6() != _tryIPv6->checked()) { if (cPlatform() == dbipWindows && Global::TryIPv6() != _tryIPv6->checked()) {
Global::SetTryIPv6(_tryIPv6->checked()); Global::SetTryIPv6(_tryIPv6->checked());
Local::writeSettings(); Local::writeSettings();

View File

@ -42,7 +42,9 @@ private slots:
void onSave(); void onSave();
private: private:
void typeChanged(DBIConnectionType type); using Type = ProxyData::Type;
void typeChanged(Type type);
void updateControlsVisibility(); void updateControlsVisibility();
void updateControlsPosition(); void updateControlsPosition();
bool badProxyValue() const; bool badProxyValue() const;
@ -52,11 +54,10 @@ private:
object_ptr<Ui::PortInput> _portInput; object_ptr<Ui::PortInput> _portInput;
object_ptr<Ui::InputField> _userInput; object_ptr<Ui::InputField> _userInput;
object_ptr<Ui::PasswordInput> _passwordInput; object_ptr<Ui::PasswordInput> _passwordInput;
ProxyData::Type _currentProxyType; std::shared_ptr<Ui::RadioenumGroup<Type>> _typeGroup;
std::shared_ptr<Ui::RadioenumGroup<DBIConnectionType>> _typeGroup; object_ptr<Ui::Radioenum<Type>> _autoRadio;
object_ptr<Ui::Radioenum<DBIConnectionType>> _autoRadio; object_ptr<Ui::Radioenum<Type>> _httpProxyRadio;
object_ptr<Ui::Radioenum<DBIConnectionType>> _httpProxyRadio; object_ptr<Ui::Radioenum<Type>> _tcpProxyRadio;
object_ptr<Ui::Radioenum<DBIConnectionType>> _tcpProxyRadio;
object_ptr<Ui::Checkbox> _tryIPv6; object_ptr<Ui::Checkbox> _tryIPv6;
}; };

View File

@ -236,6 +236,34 @@ namespace {
_MsStarter _msStarter; _MsStarter _msStarter;
} }
bool ProxyData::valid() const {
if (type == Type::None || host.isEmpty() || !port) {
return false;
} else if (type == Type::Mtproto && !ValidSecret(password)) {
return false;
}
return true;
}
ProxyData::operator bool() const {
return valid();
}
bool ProxyData::operator==(const ProxyData &other) const {
if (!valid()) {
return !other.valid();
}
return (type == other.type)
&& (host == other.host)
&& (port == other.port)
&& (user == other.user)
&& (password == other.password);
}
bool ProxyData::operator!=(const ProxyData &other) const {
return !(*this == other);
}
bool ProxyData::ValidSecret(const QString &secret) { bool ProxyData::ValidSecret(const QString &secret) {
return QRegularExpression("^[a-fA-F0-9]{32}$").match(secret).hasMatch(); return QRegularExpression("^[a-fA-F0-9]{32}$").match(secret).hasMatch();
} }

View File

@ -420,13 +420,6 @@ enum DBIWorkMode {
dbiwmWindowOnly = 2, dbiwmWindowOnly = 2,
}; };
enum DBIConnectionType {
dbictAuto = 0,
dbictHttpAuto = 1, // not used
dbictHttpProxy = 2,
dbictTcpProxy = 3,
};
struct ProxyData { struct ProxyData {
enum class Type { enum class Type {
None, None,
@ -440,6 +433,11 @@ struct ProxyData {
uint32 port = 0; uint32 port = 0;
QString user, password; QString user, password;
bool valid() const;
explicit operator bool() const;
bool operator==(const ProxyData &other) const;
bool operator!=(const ProxyData &other) const;
static bool ValidSecret(const QString &secret); static bool ValidSecret(const QString &secret);
}; };

View File

@ -563,9 +563,10 @@ struct Data {
Notify::ScreenCorner NotificationsCorner = Notify::ScreenCorner::BottomRight; Notify::ScreenCorner NotificationsCorner = Notify::ScreenCorner::BottomRight;
bool NotificationsDemoIsShown = false; bool NotificationsDemoIsShown = false;
DBIConnectionType ConnectionType = dbictAuto;
bool TryIPv6 = (cPlatform() == dbipWindows) ? false : true; bool TryIPv6 = (cPlatform() == dbipWindows) ? false : true;
ProxyData ConnectionProxy; std::vector<ProxyData> ProxiesList;
ProxyData SelectedProxy;
bool UseProxy = false;
base::Observable<void> ConnectionTypeChanged; base::Observable<void> ConnectionTypeChanged;
int AutoLock = 3600; int AutoLock = 3600;
@ -685,9 +686,10 @@ DefineVar(Global, int, NotificationsCount);
DefineVar(Global, Notify::ScreenCorner, NotificationsCorner); DefineVar(Global, Notify::ScreenCorner, NotificationsCorner);
DefineVar(Global, bool, NotificationsDemoIsShown); DefineVar(Global, bool, NotificationsDemoIsShown);
DefineVar(Global, DBIConnectionType, ConnectionType);
DefineVar(Global, bool, TryIPv6); DefineVar(Global, bool, TryIPv6);
DefineVar(Global, ProxyData, ConnectionProxy); DefineVar(Global, std::vector<ProxyData>, ProxiesList);
DefineVar(Global, ProxyData, SelectedProxy);
DefineVar(Global, bool, UseProxy);
DefineRefVar(Global, base::Observable<void>, ConnectionTypeChanged); DefineRefVar(Global, base::Observable<void>, ConnectionTypeChanged);
DefineVar(Global, int, AutoLock); DefineVar(Global, int, AutoLock);

View File

@ -371,9 +371,10 @@ DeclareVar(int, NotificationsCount);
DeclareVar(Notify::ScreenCorner, NotificationsCorner); DeclareVar(Notify::ScreenCorner, NotificationsCorner);
DeclareVar(bool, NotificationsDemoIsShown); DeclareVar(bool, NotificationsDemoIsShown);
DeclareVar(DBIConnectionType, ConnectionType); DeclareVar(std::vector<ProxyData>, ProxiesList);
DeclareVar(ProxyData, SelectedProxy);
DeclareVar(bool, UseProxy);
DeclareVar(bool, TryIPv6); DeclareVar(bool, TryIPv6);
DeclareVar(ProxyData, ConnectionProxy);
DeclareRefVar(base::Observable<void>, ConnectionTypeChanged); DeclareRefVar(base::Observable<void>, ConnectionTypeChanged);
DeclareVar(int, AutoLock); DeclareVar(int, AutoLock);

View File

@ -99,8 +99,7 @@ void ConnectingWidget::paintEvent(QPaintEvent *e) {
} }
void ConnectingWidget::onReconnect() { void ConnectingWidget::onReconnect() {
auto throughProxy = (Global::ConnectionType() != dbictAuto); if (Global::UseProxy()) {
if (throughProxy) {
Ui::show(Box<ConnectionBox>()); Ui::show(Box<ConnectionBox>());
} else { } else {
MTP::restart(); MTP::restart();
@ -409,7 +408,7 @@ void MainWindow::mtpStateChanged(int32 dc, int32 state) {
void MainWindow::updateConnectingStatus() { void MainWindow::updateConnectingStatus() {
auto state = MTP::dcstate(); auto state = MTP::dcstate();
auto throughProxy = (Global::ConnectionType() != dbictAuto); const auto throughProxy = Global::UseProxy();
if (state == MTP::ConnectingState || state == MTP::DisconnectedState || (state < 0 && state > -600)) { if (state == MTP::ConnectingState || state == MTP::DisconnectedState || (state < 0 && state > -600)) {
if (_main || getms() > 5000 || _connecting) { if (_main || getms() > 5000 || _connecting) {
showConnecting(lang(throughProxy ? lng_connecting_to_proxy : lng_connecting), throughProxy ? lang(lng_connecting_settings) : QString()); showConnecting(lang(throughProxy ? lng_connecting_to_proxy : lng_connecting), throughProxy ? lang(lng_connecting_settings) : QString());

View File

@ -100,7 +100,7 @@ void ConfigLoader::enumerate() {
} }
void ConfigLoader::createSpecialLoader() { void ConfigLoader::createSpecialLoader() {
if (Global::ConnectionProxy().type != ProxyData::Type::None) { if (Global::UseProxy()) {
_specialLoader.reset(); _specialLoader.reset();
return; return;
} }
@ -128,7 +128,7 @@ void ConfigLoader::addSpecialEndpoint(DcId dcId, const std::string &ip, int port
void ConfigLoader::sendSpecialRequest() { void ConfigLoader::sendSpecialRequest() {
terminateSpecialRequest(); terminateSpecialRequest();
if (Global::ConnectionType() != dbictAuto) { if (Global::UseProxy()) {
_specialLoader.reset(); _specialLoader.reset();
return; return;
} }

View File

@ -168,21 +168,18 @@ void Session::restart() {
} }
void Session::refreshDataFields() { void Session::refreshDataFields() {
const auto connectionType = Global::ConnectionType(); const auto &proxy = Global::SelectedProxy();
const auto proxyType = Global::ConnectionProxy().type; const auto proxyType = Global::UseProxy()
const auto useTcp = (proxyType != ProxyData::Type::Http) && ? proxy.type
(connectionType == dbictAuto : ProxyData::Type::None;
|| connectionType == dbictTcpProxy const auto useTcp = (proxyType != ProxyData::Type::Http);
|| proxyType == ProxyData::Type::Mtproto); const auto useHttp = (proxyType != ProxyData::Type::Mtproto);
const auto useHttp = (proxyType != ProxyData::Type::Mtproto) &&
(connectionType == dbictAuto
|| connectionType == dbictHttpProxy);
const auto useIPv4 = true; const auto useIPv4 = true;
const auto useIPv6 = Global::TryIPv6(); const auto useIPv6 = Global::TryIPv6();
data.setConnectionOptions(ConnectionOptions( data.setConnectionOptions(ConnectionOptions(
_instance->systemLangCode(), _instance->systemLangCode(),
_instance->cloudLangCode(), _instance->cloudLangCode(),
Global::ConnectionProxy(), Global::UseProxy() ? proxy : ProxyData(),
useIPv4, useIPv4,
useIPv6, useIPv6,
useHttp, useHttp,

View File

@ -94,21 +94,19 @@ void AdvancedWidget::onManageLocalStorage() {
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY #ifndef TDESKTOP_DISABLE_NETWORK_PROXY
void AdvancedWidget::connectionTypeUpdated() { void AdvancedWidget::connectionTypeUpdated() {
auto connection = [] { const auto connection = [] {
switch (Global::ConnectionType()) { const auto transport = MTP::dctransport();
case dbictHttpProxy: if (!Global::UseProxy()) {
case dbictTcpProxy: { return transport.isEmpty()
auto transport = MTP::dctransport(); ? lang(lng_connection_auto_connecting)
return transport.isEmpty() ? lang(lng_connection_proxy_connecting) : lng_connection_proxy(lt_transport, transport); : lng_connection_auto(lt_transport, transport);
} break; } else {
case dbictAuto: return transport.isEmpty()
default: { ? lang(lng_connection_proxy_connecting)
auto transport = MTP::dctransport(); : lng_connection_proxy(lt_transport, transport);
return transport.isEmpty() ? lang(lng_connection_auto_connecting) : lng_connection_auto(lt_transport, transport);
} break;
} }
}; }();
_connectionType->link()->setText(connection()); _connectionType->link()->setText(connection);
resizeToWidth(width()); resizeToWidth(width());
} }

View File

@ -584,6 +584,13 @@ enum {
dbiVersion = 666, dbiVersion = 666,
}; };
enum {
dbictAuto = 0,
dbictHttpAuto = 1, // not used
dbictHttpProxy = 2,
dbictTcpProxy = 3,
dbictProxiesList = 4,
};
typedef QMap<PeerId, FileKey> DraftsMap; typedef QMap<PeerId, FileKey> DraftsMap;
DraftsMap _draftsMap, _draftCursorsMap; DraftsMap _draftsMap, _draftCursorsMap;
@ -1171,44 +1178,77 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
proxy.type = (v == dbictTcpProxy) proxy.type = (v == dbictTcpProxy)
? ProxyData::Type::Socks5 ? ProxyData::Type::Socks5
: ProxyData::Type::Http; : ProxyData::Type::Http;
Global::SetConnectionType(DBIConnectionType(v));
} break; } break;
case dbictHttpAuto:
default: Global::SetConnectionType(dbictAuto); break;
}; };
Global::SetConnectionProxy(proxy); Global::SetSelectedProxy(proxy ? proxy : ProxyData());
Global::SetUseProxy(proxy ? true : false);
if (proxy) {
Global::SetProxiesList({ 1, proxy });
}
Sandbox::refreshGlobalProxy(); Sandbox::refreshGlobalProxy();
} break; } break;
case dbiConnectionType: { case dbiConnectionType: {
ProxyData proxy; qint32 connectionType;
qint32 connectionType, proxyType, port; stream >> connectionType;
stream >> connectionType >> proxyType >> proxy.host >> port >> proxy.user >> proxy.password;
if (!_checkStreamStatus(stream)) { if (!_checkStreamStatus(stream)) {
return false; return false;
} }
proxy.port = port; const auto readProxy = [&] {
proxy.type = (proxyType == dbictTcpProxy) qint32 proxyType, port;
? ProxyData::Type::Socks5 ProxyData proxy;
: (proxyType == dbictHttpProxy) stream >> proxyType >> proxy.host >> port >> proxy.user >> proxy.password;
? ProxyData::Type::Http proxy.port = port;
: (proxyType == kProxyTypeShift + int(ProxyData::Type::Socks5)) proxy.type = (proxyType == dbictTcpProxy)
? ProxyData::Type::Socks5 ? ProxyData::Type::Socks5
: (proxyType == kProxyTypeShift + int(ProxyData::Type::Http)) : (proxyType == dbictHttpProxy)
? ProxyData::Type::Http ? ProxyData::Type::Http
: (proxyType == kProxyTypeShift + int(ProxyData::Type::Mtproto)) : (proxyType == kProxyTypeShift + int(ProxyData::Type::Socks5))
? ProxyData::Type::Mtproto ? ProxyData::Type::Socks5
: ProxyData::Type::None; : (proxyType == kProxyTypeShift + int(ProxyData::Type::Http))
switch (connectionType) { ? ProxyData::Type::Http
case dbictHttpProxy: : (proxyType == kProxyTypeShift + int(ProxyData::Type::Mtproto))
case dbictTcpProxy: { ? ProxyData::Type::Mtproto
Global::SetConnectionType(DBIConnectionType(connectionType)); : ProxyData::Type::None;
} break; return proxy;
case dbictHttpAuto:
default: Global::SetConnectionType(dbictAuto); break;
}; };
Global::SetConnectionProxy(proxy); if (connectionType == dbictProxiesList) {
qint32 count = 0, index = 0;
stream >> count >> index;
auto list = std::vector<ProxyData>();
for (auto i = 0; i < count; ++i) {
const auto proxy = readProxy();
if (proxy) {
list.push_back(proxy);
}
}
if (!_checkStreamStatus(stream)) {
return false;
}
Global::SetProxiesList(list);
Global::SetUseProxy(index >= 0 && index < count);
index = std::abs(index);
if (index >= 0 && index < count) {
Global::SetSelectedProxy(list[index]);
} else {
Global::SetSelectedProxy(ProxyData());
}
} else {
const auto proxy = readProxy();
if (!_checkStreamStatus(stream)) {
return false;
}
Global::SetProxiesList({ 1, proxy });
if (connectionType == dbictTcpProxy
|| connectionType == dbictHttpProxy) {
Global::SetSelectedProxy(proxy);
Global::SetUseProxy(true);
} else {
Global::SetSelectedProxy(ProxyData());
Global::SetUseProxy(false);
}
}
Sandbox::refreshGlobalProxy(); Sandbox::refreshGlobalProxy();
} break; } break;
@ -2393,9 +2433,18 @@ void writeSettings() {
quint32 size = 12 * (sizeof(quint32) + sizeof(qint32)); quint32 size = 12 * (sizeof(quint32) + sizeof(qint32));
size += sizeof(quint32) + Serialize::bytearraySize(dcOptionsSerialized); size += sizeof(quint32) + Serialize::bytearraySize(dcOptionsSerialized);
auto &proxy = Global::ConnectionProxy(); auto &proxies = Global::RefProxiesList();
size += sizeof(quint32) + sizeof(qint32) + sizeof(qint32); const auto &proxy = Global::SelectedProxy();
size += Serialize::stringSize(proxy.host) + sizeof(qint32) + Serialize::stringSize(proxy.user) + Serialize::stringSize(proxy.password); auto proxyIt = ranges::find(proxies, proxy);
if (proxy.type != ProxyData::Type::None
&& proxyIt == end(proxies)) {
proxies.insert(begin(proxies), proxy);
proxyIt = begin(proxies);
}
size += sizeof(quint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32);
for (const auto &proxy : proxies) {
size += sizeof(qint32) + Serialize::stringSize(proxy.host) + sizeof(qint32) + Serialize::stringSize(proxy.user) + Serialize::stringSize(proxy.password);
}
if (_themeKey) { if (_themeKey) {
size += sizeof(quint32) + sizeof(quint64); size += sizeof(quint32) + sizeof(quint64);
@ -2421,8 +2470,14 @@ void writeSettings() {
data.stream << quint32(dbiScale) << qint32(cConfigScale()); data.stream << quint32(dbiScale) << qint32(cConfigScale());
data.stream << quint32(dbiDcOptions) << dcOptionsSerialized; data.stream << quint32(dbiDcOptions) << dcOptionsSerialized;
data.stream << quint32(dbiConnectionType) << qint32(Global::ConnectionType()) << qint32(kProxyTypeShift + int(proxy.type)); data.stream << quint32(dbiConnectionType) << qint32(dbictProxiesList);
data.stream << proxy.host << qint32(proxy.port) << proxy.user << proxy.password; data.stream << qint32(proxies.size());
const auto index = qint32(proxyIt - begin(proxies));
data.stream << (Global::UseProxy() ? index : -index);
for (const auto &proxy : proxies) {
data.stream << qint32(kProxyTypeShift + int(proxy.type));
data.stream << proxy.host << qint32(proxy.port) << proxy.user << proxy.password;
}
data.stream << quint32(dbiTryIPv6) << qint32(Global::TryIPv6()); data.stream << quint32(dbiTryIPv6) << qint32(Global::TryIPv6());
if (_themeKey) { if (_themeKey) {