Compare commits

..

12 Commits

Author SHA1 Message Date
lunardunno
464aa4ceae Merge branch 'check_sudo_permissions' into checking_sudo_permissions 2025-01-16 01:18:42 +04:00
lunardunno
db83555a03 Checking server user permissions to use sudo
Checking server user permissions to use sudo using a package manager.
2025-01-16 01:14:42 +04:00
lunardunno
7b2a4ea922 improved script readability 2024-12-10 20:14:29 +04:00
lunardunno
795ccaa080 added timestamp removal for sudo 2024-12-10 06:13:08 +04:00
lunardunno
ce4cb28e74 improved script readability 2024-12-10 05:44:55 +04:00
lunardunno
c9423dd9af improved script readability 2024-12-09 15:31:58 +04:00
lunardunno
055c8f7b66 splitting the sudo check script
The sudo command check script is split to check permissions correctly
2024-12-09 08:51:55 +04:00
lunardunno
2b85dafa15 сhanged extended description
Changed extended description for: not allowed in sudoers.
2024-12-09 08:31:19 +04:00
lunardunno
45fb4b0982 exception for root
Exception for root if sudo package is not installed
2024-12-08 14:31:23 +04:00
lunardunno
62497024f9 script simplification
Simplifying the script for later adding an exception for root to the server controller
2024-12-08 14:22:10 +04:00
lunardunno
076b076cd9 Verifying the server user to work with sudo (#1254)
* checking that the username is root

Changing the mechanism for checking that the username is root

* wheel group check (#1198)

Checking if the user is included in the wheel group

* Checking requirements in script (#1210)

* Checking requirements in script

Checking requirements for sudo users in script

* Adding error handling

Adding error handling in the server controller for:
Sudo package is not pre-installed for sudo users.
Server user or associated group is not listed in the sudoers file.
Server user password required

* adding error codes

* added extended error descriptions

* checking sudo permission for root

Сhecking sudo permission for root.
Сhecking and redefining the system language.

* Username if whoami returns an error

Сommand to use home directory name if whoami returns error or is missing.

* Correcting text error

Correction of the text of the extended description of the package manager error

* Updating translations

* Optimization check_user_in_sudo.sh

* exceptions for missing uname

* output only for groups sudo or wheel
2024-12-01 13:51:03 +04:00
lunardunno
85fa1ad8b1 added check for the root user and the wheel group 2024-12-01 12:22:14 +04:00
46 changed files with 416 additions and 421 deletions

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN)
project(${PROJECT} VERSION 4.8.3.2
project(${PROJECT} VERSION 4.8.3.1
DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/"
)
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(APP_ANDROID_VERSION_CODE 2075)
set(APP_ANDROID_VERSION_CODE 2074)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux")

View File

@@ -757,10 +757,6 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential
ErrorCode ServerController::isUserInSudo(const ServerCredentials &credentials, DockerContainer container)
{
if (credentials.userName == "root") {
return ErrorCode::NoError;
}
QString stdOut;
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
stdOut += data + "\n";
@@ -774,8 +770,14 @@ ErrorCode ServerController::isUserInSudo(const ServerCredentials &credentials, D
const QString scriptData = amnezia::scriptData(SharedScriptType::check_user_in_sudo);
ErrorCode error = runScript(credentials, replaceVars(scriptData, genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr);
if (!stdOut.contains("sudo"))
if (credentials.userName != "root" && !stdOut.contains("sudo") && !stdOut.contains("wheel"))
return ErrorCode::ServerUserNotInSudo;
if (credentials.userName != "root" && stdOut.contains("sudo:") && !stdOut.contains("uname:") && stdOut.contains("not found"))
return ErrorCode::SudoPackageIsNotPreinstalled;
if (stdOut.contains("sudoers"))
return ErrorCode::ServerUserNotAllowedInSudoers;
if (stdOut.contains("password is required"))
return ErrorCode::ServerUserPasswordRequired;
return error;
}

View File

@@ -56,6 +56,9 @@ namespace amnezia
ServerCancelInstallation = 204,
ServerUserNotInSudo = 205,
ServerPacketManagerError = 206,
SudoPackageIsNotPreinstalled = 207,
ServerUserNotAllowedInSudoers = 208,
ServerUserPasswordRequired = 209,
// Ssh connection errors
SshRequestDeniedError = 300,

View File

@@ -19,8 +19,11 @@ QString errorString(ErrorCode code) {
case(ErrorCode::ServerContainerMissingError): errorMessage = QObject::tr("Server error: Docker container missing"); break;
case(ErrorCode::ServerDockerFailedError): errorMessage = QObject::tr("Server error: Docker failed"); break;
case(ErrorCode::ServerCancelInstallation): errorMessage = QObject::tr("Installation canceled by user"); break;
case(ErrorCode::ServerUserNotInSudo): errorMessage = QObject::tr("The user does not have permission to use sudo"); break;
case(ErrorCode::ServerPacketManagerError): errorMessage = QObject::tr("Server error: Packet manager error"); break;
case(ErrorCode::ServerUserNotInSudo): errorMessage = QObject::tr("The user is not a member of the sudo group"); break;
case(ErrorCode::ServerPacketManagerError): errorMessage = QObject::tr("Server error: Package manager error"); break;
case(ErrorCode::SudoPackageIsNotPreinstalled): errorMessage = QObject::tr("The sudo package is not pre-installed"); break;
case(ErrorCode::ServerUserNotAllowedInSudoers): errorMessage = QObject::tr("Action not allowed in sudoers"); break;
case(ErrorCode::ServerUserPasswordRequired): errorMessage = QObject::tr("The user's password is required"); break;
// Libssh errors
case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("SSH request was denied"); break;

View File

@@ -1,14 +1,16 @@
#include "xrayprotocol.h"
#include "utilities.h"
#include "core/networkUtilities.h"
#include <QCryptographicHash>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkInterface>
#include "core/networkUtilities.h"
#include "utilities.h"
XrayProtocol::XrayProtocol(const QJsonObject &configuration, QObject *parent) : VpnProtocol(configuration, parent)
XrayProtocol::XrayProtocol(const QJsonObject &configuration, QObject *parent):
VpnProtocol(configuration, parent)
{
readXrayConfiguration(configuration);
m_routeGateway = NetworkUtilities::getGatewayAndIface();
@@ -43,7 +45,10 @@ ErrorCode XrayProtocol::start()
QStringList args = QStringList() << "-c" << m_xrayCfgFile.fileName() << "-format=json";
qDebug().noquote() << "XrayProtocol::start()" << xrayExecPath() << args.join(" ");
qDebug().noquote() << "XrayProtocol::start()"
<< xrayExecPath() << args.join(" ");
m_xrayProcess.setProcessChannelMode(QProcess::MergedChannels);
m_xrayProcess.setProgram(xrayExecPath());
@@ -61,15 +66,14 @@ ErrorCode XrayProtocol::start()
#endif
});
connect(&m_xrayProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this,
[this](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug().noquote() << "XrayProtocol finished, exitCode, exitStatus" << exitCode << exitStatus;
setConnectionState(Vpn::ConnectionState::Disconnected);
if ((exitStatus != QProcess::NormalExit) || (exitCode != 0)) {
emit protocolError(amnezia::ErrorCode::XrayExecutableCrashed);
emit setConnectionState(Vpn::ConnectionState::Error);
}
});
connect(&m_xrayProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug().noquote() << "XrayProtocol finished, exitCode, exitStatus" << exitCode << exitStatus;
setConnectionState(Vpn::ConnectionState::Disconnected);
if ((exitStatus != QProcess::NormalExit) || (exitCode != 0)) {
emit protocolError(amnezia::ErrorCode::XrayExecutableCrashed);
emit setConnectionState(Vpn::ConnectionState::Error);
}
});
m_xrayProcess.start();
m_xrayProcess.waitForStarted();
@@ -78,10 +82,11 @@ ErrorCode XrayProtocol::start()
setConnectionState(Vpn::ConnectionState::Connecting);
QThread::msleep(1000);
return startTun2Sock();
} else
return ErrorCode::XrayExecutableMissing;
}
else return ErrorCode::XrayExecutableMissing;
}
ErrorCode XrayProtocol::startTun2Sock()
{
m_t2sProcess->start();
@@ -93,68 +98,71 @@ ErrorCode XrayProtocol::startTun2Sock()
connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::stateChanged, this,
[&](QProcess::ProcessState newState) { qDebug() << "PrivilegedProcess stateChanged" << newState; });
connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::setConnectionState, this, [&](int vpnState) {
qDebug() << "PrivilegedProcess setConnectionState " << vpnState;
if (vpnState == Vpn::ConnectionState::Connected) {
setConnectionState(Vpn::ConnectionState::Connecting);
QList<QHostAddress> dnsAddr;
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns1).toString()));
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns2).toString()));
connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::setConnectionState, this,
[&](int vpnState) {
qDebug() << "PrivilegedProcess setConnectionState " << vpnState;
if (vpnState == Vpn::ConnectionState::Connected)
{
setConnectionState(Vpn::ConnectionState::Connecting);
QList<QHostAddress> dnsAddr;
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns1).toString()));
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns2).toString()));
#ifdef Q_OS_WIN
QThread::msleep(8000);
QThread::msleep(8000);
#endif
#ifdef Q_OS_MACOS
QThread::msleep(5000);
IpcClient::Interface()->createTun("utun22", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("utun22", dnsAddr);
QThread::msleep(5000);
IpcClient::Interface()->createTun("utun22", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("utun22", dnsAddr);
#endif
#ifdef Q_OS_LINUX
QThread::msleep(1000);
IpcClient::Interface()->createTun("tun2", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
QThread::msleep(1000);
IpcClient::Interface()->createTun("tun2", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
#endif
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
// killSwitch toggle
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
m_configData.insert("vpnServer", m_remoteAddress);
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
}
#endif
if (m_routeMode == Settings::RouteMode::VpnAllSites) {
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "0.0.0.0/1");
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "128.0.0.0/1");
IpcClient::Interface()->routeAddList(m_routeGateway, QStringList() << m_remoteAddress);
}
IpcClient::Interface()->StopRoutingIpv6();
#ifdef Q_OS_WIN
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
QList<QNetworkInterface> netInterfaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < netInterfaces.size(); i++) {
for (int j = 0; j < netInterfaces.at(i).addressEntries().size(); j++) {
// killSwitch toggle
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
}
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
m_configData.insert("vpnGateway", m_vpnGateway);
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
m_configData.insert("vpnServer", m_remoteAddress);
IpcClient::Interface()->enablePeerTraffic(m_configData);
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
}
#endif
if (m_routeMode == 0) {
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "0.0.0.0/1");
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "128.0.0.0/1");
IpcClient::Interface()->routeAddList(m_routeGateway, QStringList() << m_remoteAddress);
}
IpcClient::Interface()->StopRoutingIpv6();
#ifdef Q_OS_WIN
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
QList<QNetworkInterface> netInterfaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < netInterfaces.size(); i++) {
for (int j = 0; j < netInterfaces.at(i).addressEntries().size(); j++)
{
// killSwitch toggle
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
}
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
m_configData.insert("vpnGateway", m_vpnGateway);
m_configData.insert("vpnServer", m_remoteAddress);
IpcClient::Interface()->enablePeerTraffic(m_configData);
}
}
}
#endif
setConnectionState(Vpn::ConnectionState::Connected);
}
}
#endif
setConnectionState(Vpn::ConnectionState::Connected);
}
#if !defined(Q_OS_MACOS)
if (vpnState == Vpn::ConnectionState::Disconnected) {
setConnectionState(Vpn::ConnectionState::Disconnected);
IpcClient::Interface()->deleteTun("tun2");
IpcClient::Interface()->StartRoutingIpv6();
IpcClient::Interface()->clearSavedRoutes();
}
if (vpnState == Vpn::ConnectionState::Disconnected) {
setConnectionState(Vpn::ConnectionState::Disconnected);
IpcClient::Interface()->deleteTun("tun2");
IpcClient::Interface()->StartRoutingIpv6();
IpcClient::Interface()->clearSavedRoutes();
}
#endif
});
});
return ErrorCode::NoError;
}
@@ -196,7 +204,7 @@ void XrayProtocol::readXrayConfiguration(const QJsonObject &configuration)
m_localPort = QString(amnezia::protocols::xray::defaultLocalProxyPort).toInt();
m_remoteHost = configuration.value(amnezia::config_key::hostName).toString();
m_remoteAddress = NetworkUtilities::getIPAddress(m_remoteHost);
m_routeMode = static_cast<Settings::RouteMode>(configuration.value(amnezia::config_key::splitTunnelType).toInt());
m_routeMode = configuration.value(amnezia::config_key::splitTunnelType).toInt();
m_primaryDNS = configuration.value(amnezia::config_key::dns1).toString();
m_secondaryDNS = configuration.value(amnezia::config_key::dns2).toString();
}

View File

@@ -1,16 +1,14 @@
#ifndef XRAYPROTOCOL_H
#define XRAYPROTOCOL_H
#include "QProcess"
#include "containers/containers_defs.h"
#include "openvpnprotocol.h"
#include "settings.h"
#include "QProcess"
#include "containers/containers_defs.h"
class XrayProtocol : public VpnProtocol
{
public:
XrayProtocol(const QJsonObject &configuration, QObject *parent = nullptr);
XrayProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
virtual ~XrayProtocol() override;
ErrorCode start() override;
@@ -26,12 +24,11 @@ protected:
private:
static QString xrayExecPath();
static QString tun2SocksExecPath();
private:
int m_localPort;
QString m_remoteHost;
QString m_remoteAddress;
Settings::RouteMode m_routeMode;
int m_routeMode;
QJsonObject m_configData;
QString m_primaryDNS;
QString m_secondaryDNS;
@@ -40,6 +37,7 @@ private:
QSharedPointer<IpcProcessTun2SocksReplica> m_t2sProcess;
#endif
QTemporaryFile m_xrayCfgFile;
};
#endif // XRAYPROTOCOL_H

View File

@@ -15,12 +15,6 @@
using namespace QKeychain;
namespace {
constexpr const char *settingsKeyTag = "settingsKeyTag";
constexpr const char *settingsIvTag = "settingsIvTag";
constexpr const char *keyChainName = "AmneziaVPN-Keychain";
}
SecureQSettings::SecureQSettings(const QString &organization, const QString &application, QObject *parent)
: QObject { parent }, m_settings(organization, application, parent), encryptedKeys({ "Servers/serversList" })
{
@@ -55,7 +49,7 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue
// check if value is not encrypted, v. < 2.0.x
retVal = m_settings.value(key);
if (retVal.isValid()) {
if (retVal.userType() == QMetaType::QByteArray && retVal.toByteArray().mid(0, magicString.size()) == magicString) {
if (retVal.userType() == QVariant::ByteArray && retVal.toByteArray().mid(0, magicString.size()) == magicString) {
if (getEncKey().isEmpty() || getEncIv().isEmpty()) {
qCritical() << "SecureQSettings::setValue Decryption requested, but key is empty";

View File

@@ -8,6 +8,10 @@
#include "keychain.h"
constexpr const char *settingsKeyTag = "settingsKeyTag";
constexpr const char *settingsIvTag = "settingsIvTag";
constexpr const char *keyChainName = "AmneziaVPN-Keychain";
class SecureQSettings : public QObject
{
Q_OBJECT
@@ -40,7 +44,7 @@ public:
private:
QSettings m_settings;
mutable QHash<QString, QVariant> m_cache;
mutable QMap<QString, QVariant> m_cache;
QStringList encryptedKeys; // encode only key listed here
// only this fields need for backup

View File

@@ -1,2 +1,11 @@
CUR_USER=$(whoami);\
groups $CUR_USER
if which apt-get > /dev/null 2>&1; then pm=$(which apt-get); opt="--version";\
elif which dnf > /dev/null 2>&1; then pm=$(which dnf); opt="--version";\
elif which yum > /dev/null 2>&1; then pm=$(which yum); opt="--version";\
elif which pacman > /dev/null 2>&1; then pm=$(which pacman); opt="--version";\
else pm="uname"; opt="-a";\
fi;\
CUR_USER=$(whoami 2> /dev/null || echo ~ | sed 's/.*\///');\
echo $LANG | grep -qE '^(en_US.UTF-8|C.UTF-8|C)$' || export LC_ALL=C;\
if [ "$CUR_USER" = "root" ] || ( groups "$CUR_USER" | grep -E '\<(sudo|wheel)\>' ); then \
sudo -K && sudo -nu $CUR_USER $pm $opt > /dev/null && sudo -n $pm $opt > /dev/null;\
fi

View File

@@ -1,7 +1,7 @@
if which apt-get > /dev/null 2>&1; then pm=$(which apt-get); silent_inst="-yq install"; check_pkgs="-yq update"; docker_pkg="docker.io"; dist="debian";\
elif which dnf > /dev/null 2>&1; then pm=$(which dnf); silent_inst="-yq install"; check_pkgs="-yq check-update"; docker_pkg="docker"; dist="fedora";\
elif which yum > /dev/null 2>&1; then pm=$(which yum); silent_inst="-y -q install"; check_pkgs="-y -q check-update"; docker_pkg="docker"; dist="centos";\
elif which pacman > /dev/null 2>&1; then pm=$(which pacman); silent_inst="-S --noconfirm --noprogressbar --quiet"; check_pkgs="-Sup"; docker_pkg="docker"; dist="archlinux";\
elif which pacman > /dev/null 2>&1; then pm=$(which pacman); silent_inst="-S --noconfirm --noprogressbar --quiet"; check_pkgs="> /dev/null 2>&1"; docker_pkg="docker"; dist="archlinux";\
else echo "Packet manager not found"; exit 1; fi;\
echo "Dist: $dist, Packet manager: $pm, Install command: $silent_inst, Check pkgs command: $check_pkgs, Docker pkg: $docker_pkg";\
if [ "$dist" = "debian" ]; then export DEBIAN_FRONTEND=noninteractive; fi;\
@@ -12,9 +12,6 @@ if ! command -v docker > /dev/null 2>&1; then \
sudo $pm $check_pkgs; sudo $pm $silent_inst $docker_pkg;\
sleep 5; sudo systemctl enable --now docker; sleep 5;\
fi;\
if [ "$(cat /sys/module/apparmor/parameters/enabled 2>/dev/null)" = "Y" ]; then \
if ! command -v apparmor_parser > /dev/null 2>&1; then sudo $pm $check_pkgs; sudo $pm $silent_inst apparmor; fi;\
fi;\
if [ "$(systemctl is-active docker)" != "active" ]; then \
sudo $pm $check_pkgs; sudo $pm $silent_inst $docker_pkg;\
sleep 5; sudo systemctl start docker; sleep 5;\

View File

@@ -1,4 +1,4 @@
CUR_USER=$(whoami);\
CUR_USER=$(whoami 2> /dev/null || echo ~ | sed 's/.*\///');\
sudo mkdir -p $DOCKERFILE_FOLDER;\
sudo chown $CUR_USER $DOCKERFILE_FOLDER;\
if ! sudo docker network ls | grep -q amnezia-dns-net; then sudo docker network create \

View File

@@ -3334,8 +3334,8 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../core/errorstrings.cpp" line="22"/>
<source>The user does not have permission to use sudo</source>
<translation>ليس لدي المستخدم الصلحيات لأستخدام sudo</translation>
<source>The user is not a member of the sudo group</source>
<translation>المستخدم ليس عضوًا في مجموعة sudo</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="26"/>
@@ -3399,7 +3399,7 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../core/errorstrings.cpp" line="23"/>
<source>Server error: Packet manager error</source>
<source>Server error: Package manager error</source>
<translation>خطأ في الخادم: خطأ في مدير الحزم</translation>
</message>
<message>

View File

@@ -3468,8 +3468,8 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="22"/>
<source>The user does not have permission to use sudo</source>
<translation>The user does not have permission to use sudo</translation>
<source>The user is not a member of the sudo group</source>
<translation>کاربر عضو گروه sudo نیست</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="26"/>
@@ -3590,8 +3590,8 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="23"/>
<source>Server error: Packet manager error</source>
<translation>Server error: Packet manager error</translation>
<source>Server error: Package manager error</source>
<translation>خطای سرور: خطای مدیر بسته</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="34"/>

View File

@@ -3434,13 +3434,13 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../core/errorstrings.cpp" line="22"/>
<source>The user does not have permission to use sudo</source>
<translation> sudo ि </translation>
<source>The user is not a member of the sudo group</source>
<translation> sudo </translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="23"/>
<source>Server error: Packet manager error</source>
<translation> ि: ि</translation>
<source>Server error: Package manager error</source>
<translation> ि: ि</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="26"/>

View File

@@ -3330,8 +3330,8 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../core/errorstrings.cpp" line="22"/>
<source>The user does not have permission to use sudo</source>
<translation> sudo ကက</translation>
<source>The user is not a member of the sudo group</source>
<translation> sudo </translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="26"/>
@@ -3395,8 +3395,8 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../core/errorstrings.cpp" line="23"/>
<source>Server error: Packet manager error</source>
<translation> မှု: Packet Manager </translation>
<source>Server error: Package manager error</source>
<translation> - Package manager </translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="34"/>

View File

@@ -3604,12 +3604,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="22"/>
<source>The user does not have permission to use sudo</source>
<translation>У пользователя нет прав на использование sudo</translation>
<source>The user is not a member of the sudo group</source>
<translation>Пользователь не входит в группу sudo</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="23"/>
<source>Server error: Packet manager error</source>
<source>Server error: Package manager error</source>
<translation>Ошибка сервера: ошибка менеджера пакетов</translation>
</message>
<message>

View File

@@ -3700,13 +3700,13 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="22"/>
<source>The user does not have permission to use sudo</source>
<translation>The user does not have permission to use sudo</translation>
<source>The user is not a member of the sudo group</source>
<translation>Користувач не входить до групи sudo</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="23"/>
<source>Server error: Packet manager error</source>
<translation type="unfinished"></translation>
<source>Server error: Package manager error</source>
<translation>Помилка сервера: помилка менеджера пакетів</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="26"/>

View File

@@ -3433,8 +3433,8 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../core/errorstrings.cpp" line="22"/>
<source>The user does not have permission to use sudo</source>
<translation>صارف کو sudo استعمال کرنے کی اجازت نہیں ہے</translation>
<source>The user is not a member of the sudo group</source>
<translation>صارف sudo گروپ کا رکن نہیں ہے</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="26"/>
@@ -3498,7 +3498,7 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../core/errorstrings.cpp" line="23"/>
<source>Server error: Packet manager error</source>
<source>Server error: Package manager error</source>
<translation>سرور خطا: پیکیج منیجر خطا</translation>
</message>
<message>

View File

@@ -3675,13 +3675,13 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="22"/>
<source>The user does not have permission to use sudo</source>
<translation>root权限</translation>
<source>The user is not a member of the sudo group</source>
<translation> sudo </translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="23"/>
<source>Server error: Packet manager error</source>
<translation type="unfinished"></translation>
<source>Server error: Package manager error</source>
<translation></translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="26"/>

View File

@@ -255,7 +255,7 @@ ApiServicesModel::ApiServicesData ApiServicesModel::getApiServicesData(const QJs
serviceData.type = serviceType;
serviceData.protocol = serviceProtocol;
serviceData.storeEndpoint = data.value(configKey::storeEndpoint).toString();
serviceData.storeEndpoint = serviceInfo.value(configKey::storeEndpoint).toString();
if (data.value(configKey::isAvailable).isBool()) {
serviceData.isServiceAvailable = data.value(configKey::isAvailable).toBool();

View File

@@ -135,7 +135,7 @@ DrawerType2 {
backgroundColor: AmneziaStyle.color.slateGray
textField.placeholderText: qsTr("application name")
textFieldPlaceholderText: qsTr("application name")
}
BasicButtonType {

View File

@@ -22,9 +22,11 @@ Item {
property var clickedFunc
property alias textField: textField
property alias textFieldText: textField.text
property string textFieldTextColor: AmneziaStyle.color.paleGray
property string textFieldTextDisabledColor: AmneziaStyle.color.mutedGray
property string textFieldPlaceholderText
property bool textFieldEditable: true
property string borderColor: AmneziaStyle.color.slateGray
@@ -99,6 +101,7 @@ Item {
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhSensitiveData | Qt.ImhNoPredictiveText
placeholderText: root.textFieldPlaceholderText
placeholderTextColor: AmneziaStyle.color.charcoalGray
selectionColor: AmneziaStyle.color.richBrown
@@ -126,8 +129,8 @@ Item {
}
onActiveFocusChanged: {
if (root.checkEmptyText && text === "") {
root.errorText = qsTr("The field can't be empty")
if (checkEmptyText && textFieldText === "") {
errorText = qsTr("The field can't be empty")
}
}

View File

@@ -66,18 +66,18 @@ PageType {
Layout.leftMargin: 16
headerText: qsTr("Gateway endpoint")
textField.text: SettingsController.gatewayEndpoint
textFieldText: SettingsController.gatewayEndpoint
buttonImageSource: textField.text !== "" ? "qrc:/images/controls/refresh-cw.svg" : ""
buttonImageSource: textFieldText !== "" ? "qrc:/images/controls/refresh-cw.svg" : ""
clickedFunc: function() {
SettingsController.resetGatewayEndpoint()
}
textField.onEditingFinished: {
textField.text = textField.text.replace(/^\s+|\s+$/g, '')
if (textField.text !== SettingsController.gatewayEndpoint) {
SettingsController.gatewayEndpoint = textField.text
textFieldText = textField.text.replace(/^\s+|\s+$/g, '')
if (textFieldText !== SettingsController.gatewayEndpoint) {
SettingsController.gatewayEndpoint = textFieldText
}
}
}

View File

@@ -103,12 +103,12 @@ PageType {
Layout.topMargin: 40
headerText: qsTr("MTU")
textField.text: clientMtu
textFieldText: clientMtu
textField.validator: IntValidator { bottom: 576; top: 65535 }
textField.onEditingFinished: {
if (textField.text !== clientMtu) {
clientMtu = textField.text
if (textFieldText !== clientMtu) {
clientMtu = textFieldText
}
}
checkEmptyText: true
@@ -121,12 +121,12 @@ PageType {
Layout.topMargin: 16
headerText: "Jc - Junk packet count"
textField.text: clientJunkPacketCount
textFieldText: clientJunkPacketCount
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== clientJunkPacketCount) {
clientJunkPacketCount = textField.text
if (textFieldText !== clientJunkPacketCount) {
clientJunkPacketCount = textFieldText
}
}
@@ -141,12 +141,12 @@ PageType {
Layout.topMargin: 16
headerText: "Jmin - Junk packet minimum size"
textField.text: clientJunkPacketMinSize
textFieldText: clientJunkPacketMinSize
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== clientJunkPacketMinSize) {
clientJunkPacketMinSize = textField.text
if (textFieldText !== clientJunkPacketMinSize) {
clientJunkPacketMinSize = textFieldText
}
}
@@ -161,12 +161,12 @@ PageType {
Layout.topMargin: 16
headerText: "Jmax - Junk packet maximum size"
textField.text: clientJunkPacketMaxSize
textFieldText: clientJunkPacketMaxSize
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== clientJunkPacketMaxSize) {
clientJunkPacketMaxSize = textField.text
if (textFieldText !== clientJunkPacketMaxSize) {
clientJunkPacketMaxSize = textFieldText
}
}
@@ -189,7 +189,7 @@ PageType {
enabled: false
headerText: qsTr("Port")
textField.text: port
textFieldText: port
}
TextFieldWithHeaderType {
@@ -200,7 +200,7 @@ PageType {
enabled: false
headerText: "S1 - Init packet junk size"
textField.text: serverInitPacketJunkSize
textFieldText: serverInitPacketJunkSize
}
TextFieldWithHeaderType {
@@ -211,7 +211,7 @@ PageType {
enabled: false
headerText: "S2 - Response packet junk size"
textField.text: serverResponsePacketJunkSize
textFieldText: serverResponsePacketJunkSize
}
TextFieldWithHeaderType {
@@ -222,7 +222,7 @@ PageType {
enabled: false
headerText: "H1 - Init packet magic header"
textField.text: serverInitPacketMagicHeader
textFieldText: serverInitPacketMagicHeader
}
TextFieldWithHeaderType {
@@ -233,7 +233,7 @@ PageType {
enabled: false
headerText: "H2 - Response packet magic header"
textField.text: serverResponsePacketMagicHeader
textFieldText: serverResponsePacketMagicHeader
}
TextFieldWithHeaderType {
@@ -244,7 +244,7 @@ PageType {
enabled: false
headerText: "H3 - Underload packet magic header"
textField.text: serverUnderloadPacketMagicHeader
textFieldText: serverUnderloadPacketMagicHeader
}
TextFieldWithHeaderType {
@@ -255,7 +255,7 @@ PageType {
enabled: false
headerText: "H4 - Transport packet magic header"
textField.text: serverTransportPacketMagicHeader
textFieldText: serverTransportPacketMagicHeader
}
}
}

View File

@@ -106,11 +106,11 @@ PageType {
enabled: delegateItem.isEnabled
headerText: qsTr("VPN address subnet")
textField.text: subnetAddress
textFieldText: subnetAddress
textField.onEditingFinished: {
if (textField.text !== subnetAddress) {
subnetAddress = textField.text
if (textFieldText !== subnetAddress) {
subnetAddress = textFieldText
}
}
@@ -125,13 +125,13 @@ PageType {
enabled: delegateItem.isEnabled
headerText: qsTr("Port")
textField.text: port
textFieldText: port
textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 }
textField.onEditingFinished: {
if (textField.text !== port) {
port = textField.text
if (textFieldText !== port) {
port = textFieldText
}
}
@@ -144,16 +144,16 @@ PageType {
Layout.topMargin: 16
headerText: qsTr("Jc - Junk packet count")
textField.text: serverJunkPacketCount
textFieldText: serverJunkPacketCount
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text === "") {
textField.text = "0"
if (textFieldText === "") {
textFieldText = "0"
}
if (textField.text !== serverJunkPacketCount) {
serverJunkPacketCount = textField.text
if (textFieldText !== serverJunkPacketCount) {
serverJunkPacketCount = textFieldText
}
}
@@ -166,12 +166,12 @@ PageType {
Layout.topMargin: 16
headerText: qsTr("Jmin - Junk packet minimum size")
textField.text: serverJunkPacketMinSize
textFieldText: serverJunkPacketMinSize
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== serverJunkPacketMinSize) {
serverJunkPacketMinSize = textField.text
if (textFieldText !== serverJunkPacketMinSize) {
serverJunkPacketMinSize = textFieldText
}
}
@@ -184,12 +184,12 @@ PageType {
Layout.topMargin: 16
headerText: qsTr("Jmax - Junk packet maximum size")
textField.text: serverJunkPacketMaxSize
textFieldText: serverJunkPacketMaxSize
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== serverJunkPacketMaxSize) {
serverJunkPacketMaxSize = textField.text
if (textFieldText !== serverJunkPacketMaxSize) {
serverJunkPacketMaxSize = textFieldText
}
}
@@ -202,12 +202,12 @@ PageType {
Layout.topMargin: 16
headerText: qsTr("S1 - Init packet junk size")
textField.text: serverInitPacketJunkSize
textFieldText: serverInitPacketJunkSize
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== serverInitPacketJunkSize) {
serverInitPacketJunkSize = textField.text
if (textFieldText !== serverInitPacketJunkSize) {
serverInitPacketJunkSize = textFieldText
}
}
@@ -226,12 +226,12 @@ PageType {
Layout.topMargin: 16
headerText: qsTr("S2 - Response packet junk size")
textField.text: serverResponsePacketJunkSize
textFieldText: serverResponsePacketJunkSize
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== serverResponsePacketJunkSize) {
serverResponsePacketJunkSize = textField.text
if (textFieldText !== serverResponsePacketJunkSize) {
serverResponsePacketJunkSize = textFieldText
}
}
@@ -250,12 +250,12 @@ PageType {
Layout.topMargin: 16
headerText: qsTr("H1 - Init packet magic header")
textField.text: serverInitPacketMagicHeader
textFieldText: serverInitPacketMagicHeader
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== serverInitPacketMagicHeader) {
serverInitPacketMagicHeader = textField.text
if (textFieldText !== serverInitPacketMagicHeader) {
serverInitPacketMagicHeader = textFieldText
}
}
@@ -268,12 +268,12 @@ PageType {
Layout.topMargin: 16
headerText: qsTr("H2 - Response packet magic header")
textField.text: serverResponsePacketMagicHeader
textFieldText: serverResponsePacketMagicHeader
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== serverResponsePacketMagicHeader) {
serverResponsePacketMagicHeader = textField.text
if (textFieldText !== serverResponsePacketMagicHeader) {
serverResponsePacketMagicHeader = textFieldText
}
}
@@ -286,12 +286,12 @@ PageType {
Layout.topMargin: 16
headerText: qsTr("H4 - Transport packet magic header")
textField.text: serverTransportPacketMagicHeader
textFieldText: serverTransportPacketMagicHeader
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== serverTransportPacketMagicHeader) {
serverTransportPacketMagicHeader = textField.text
if (textFieldText !== serverTransportPacketMagicHeader) {
serverTransportPacketMagicHeader = textFieldText
}
}
@@ -304,12 +304,12 @@ PageType {
Layout.topMargin: 16
headerText: qsTr("H3 - Underload packet magic header")
textField.text: serverUnderloadPacketMagicHeader
textFieldText: serverUnderloadPacketMagicHeader
textField.validator: IntValidator { bottom: 0 }
textField.onEditingFinished: {
if (textField.text !== serverUnderloadPacketMagicHeader) {
serverUnderloadPacketMagicHeader = textField.text
if (textFieldText !== serverUnderloadPacketMagicHeader) {
serverUnderloadPacketMagicHeader = textFieldText
}
}

View File

@@ -89,18 +89,18 @@ PageType {
Layout.topMargin: 32
headerText: qsTr("Disguised as traffic from")
textField.text: site
textFieldText: site
textField.onEditingFinished: {
if (textField.text !== site) {
var tmpText = textField.text
if (textFieldText !== site) {
var tmpText = textFieldText
tmpText = tmpText.toLocaleLowerCase()
var indexHttps = tmpText.indexOf("https://")
if (indexHttps === 0) {
tmpText = textField.text.substring(8)
tmpText = textFieldText.substring(8)
} else {
site = textField.text
site = textFieldText
}
}
}
@@ -113,13 +113,13 @@ PageType {
Layout.topMargin: 16
headerText: qsTr("Port")
textField.text: port
textFieldText: port
textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 }
textField.onEditingFinished: {
if (textField.text !== port) {
port = textField.text
if (textFieldText !== port) {
port = textFieldText
}
}
}

View File

@@ -88,13 +88,13 @@ PageType {
Layout.topMargin: 32
headerText: qsTr("VPN address subnet")
textField.text: subnetAddress
textFieldText: subnetAddress
parentFlickable: fl
textField.onEditingFinished: {
if (textField.text !== subnetAddress) {
subnetAddress = textField.text
if (textFieldText !== subnetAddress) {
subnetAddress = textFieldText
}
}
}
@@ -137,13 +137,13 @@ PageType {
enabled: isPortEditable
headerText: qsTr("Port")
textField.text: port
textFieldText: port
textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 }
textField.onEditingFinished: {
if (textField.text !== port) {
port = textField.text
if (textFieldText !== port) {
port = textFieldText
}
}
}

View File

@@ -93,13 +93,13 @@ PageType {
enabled: isPortEditable
headerText: qsTr("Port")
textField.text: port
textFieldText: port
textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 }
textField.onEditingFinished: {
if (textField.text !== port) {
port = textField.text
if (textFieldText !== port) {
port = textFieldText
}
}
}

View File

@@ -97,12 +97,12 @@ PageType {
Layout.topMargin: 40
headerText: qsTr("MTU")
textField.text: clientMtu
textFieldText: clientMtu
textField.validator: IntValidator { bottom: 576; top: 65535 }
textField.onEditingFinished: {
if (textField.text !== clientMtu) {
clientMtu = textField.text
if (textFieldText !== clientMtu) {
clientMtu = textFieldText
}
}
checkEmptyText: true
@@ -124,7 +124,7 @@ PageType {
enabled: false
headerText: qsTr("Port")
textField.text: port
textFieldText: port
}
}
}

View File

@@ -90,11 +90,11 @@ PageType {
enabled: delegateItem.isEnabled
headerText: qsTr("VPN address subnet")
textField.text: subnetAddress
textFieldText: subnetAddress
textField.onEditingFinished: {
if (textField.text !== subnetAddress) {
subnetAddress = textField.text
if (textFieldText !== subnetAddress) {
subnetAddress = textFieldText
}
}
@@ -109,13 +109,13 @@ PageType {
enabled: delegateItem.isEnabled
headerText: qsTr("Port")
textField.text: port
textFieldText: port
textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 }
textField.onEditingFinished: {
if (textField.text !== port) {
port = textField.text
if (textFieldText !== port) {
port = textFieldText
}
}

View File

@@ -86,18 +86,18 @@ PageType {
Layout.topMargin: 32
headerText: qsTr("Disguised as traffic from")
textField.text: site
textFieldText: site
textField.onEditingFinished: {
if (textField.text !== site) {
var tmpText = textField.text
if (textFieldText !== site) {
var tmpText = textFieldText
tmpText = tmpText.toLocaleLowerCase()
var indexHttps = tmpText.indexOf("https://")
if (indexHttps === 0) {
tmpText = textField.text.substring(8)
tmpText = textFieldText.substring(8)
} else {
site = textField.text
site = textFieldText
}
}
}

View File

@@ -211,9 +211,9 @@ PageType {
port = tempPort
username = tempUsername
password = tempPassword
portTextField.textField.text = port
usernameTextField.textField.text = username
passwordTextField.textField.text = password
portTextField.textFieldText = port
usernameTextField.textFieldText = username
passwordTextField.textFieldText = password
}
}
@@ -231,14 +231,14 @@ PageType {
parentFlickable: fl
headerText: qsTr("Port")
textField.text: port
textFieldText: port
textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 }
textField.onEditingFinished: {
textField.text = textField.text.replace(/^\s+|\s+$/g, '')
if (textField.text !== port) {
port = textField.text
textFieldText = textField.text.replace(/^\s+|\s+$/g, '')
if (textFieldText !== port) {
port = textFieldText
}
}
}
@@ -251,14 +251,14 @@ PageType {
parentFlickable: fl
headerText: qsTr("Username")
textField.placeholderText: "username"
textField.text: username
textFieldPlaceholderText: "username"
textFieldText: username
textField.maximumLength: 32
textField.onEditingFinished: {
textField.text = textField.text.replace(/^\s+|\s+$/g, '')
if (textField.text !== username) {
username = textField.text
textFieldText = textField.text.replace(/^\s+|\s+$/g, '')
if (textFieldText !== username) {
username = textFieldText
}
}
}
@@ -273,12 +273,12 @@ PageType {
parentFlickable: fl
headerText: qsTr("Password")
textField.placeholderText: "password"
textField.text: password
textFieldPlaceholderText: "password"
textFieldText: password
textField.maximumLength: 32
textField.echoMode: hidePassword ? TextInput.Password : TextInput.Normal
buttonImageSource: textField.text !== "" ? (hidePassword ? "qrc:/images/controls/eye.svg" : "qrc:/images/controls/eye-off.svg")
buttonImageSource: textFieldText !== "" ? (hidePassword ? "qrc:/images/controls/eye.svg" : "qrc:/images/controls/eye-off.svg")
: ""
clickedFunc: function() {
@@ -286,9 +286,9 @@ PageType {
}
textField.onFocusChanged: {
textField.text = textField.text.replace(/^\s+|\s+$/g, '')
if (textField.text !== password) {
password = textField.text
textFieldText = textField.text.replace(/^\s+|\s+$/g, '')
if (textFieldText !== password) {
password = textFieldText
}
}
}
@@ -309,19 +309,19 @@ PageType {
portTextField.errorText = qsTr("The port must be in the range of 1 to 65535")
return
}
if (usernameTextField.textField.text && passwordTextField.textField.text === "") {
if (usernameTextField.textFieldText && passwordTextField.textFieldText === "") {
passwordTextField.errorText = qsTr("Password cannot be empty")
return
} else if (usernameTextField.textField.text === "" && passwordTextField.textField.text) {
} else if (usernameTextField.textFieldText === "" && passwordTextField.textFieldText) {
usernameTextField.errorText = qsTr("Username cannot be empty")
return
}
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
InstallController.updateContainer(Socks5ProxyConfigModel.getConfig())
tempPort = portTextField.textField.text
tempUsername = usernameTextField.textField.text
tempPassword = passwordTextField.textField.text
tempPort = portTextField.textFieldText
tempUsername = usernameTextField.textFieldText
tempPassword = passwordTextField.textFieldText
changeSettingsDrawer.closeTriggered()
}
}

View File

@@ -87,6 +87,7 @@ PageType {
LabelWithButtonType {
id: backup
visible: !SettingsController.isOnTv()
Layout.fillWidth: true
text: qsTr("Backup")
@@ -98,7 +99,9 @@ PageType {
}
}
DividerType {}
DividerType {
visible: !SettingsController.isOnTv()
}
LabelWithButtonType {
id: about

View File

@@ -15,100 +15,61 @@ import "../Components"
PageType {
id: root
property list<QtObject> labelsModel: [
regionObject,
priceObject,
endDateObject,
speedObject
]
FlickableType {
id: fl
anchors.top: parent.top
anchors.bottom: parent.bottom
contentHeight: content.height
QtObject {
id: regionObject
ColumnLayout {
id: content
readonly property string title: qsTr("For the region")
readonly property string contentKey: "region"
readonly property string objectImageSource: "qrc:/images/controls/map-pin.svg"
}
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
QtObject {
id: priceObject
readonly property string title: qsTr("Price")
readonly property string contentKey: "price"
readonly property string objectImageSource: "qrc:/images/controls/tag.svg"
}
QtObject {
id: endDateObject
readonly property string title: qsTr("Valid until")
readonly property string contentKey: "endDate"
readonly property string objectImageSource: "qrc:/images/controls/history.svg"
}
QtObject {
id: speedObject
readonly property string title: qsTr("Speed")
readonly property string contentKey: "speed"
readonly property string objectImageSource: "qrc:/images/controls/gauge.svg"
}
ListView {
id: listView
anchors.fill: parent
property bool isFocusable: true
Keys.onTabPressed: {
FocusController.nextKeyTabItem()
}
Keys.onBacktabPressed: {
FocusController.previousKeyTabItem()
}
Keys.onUpPressed: {
FocusController.nextKeyUpItem()
}
Keys.onDownPressed: {
FocusController.nextKeyDownItem()
}
Keys.onLeftPressed: {
FocusController.nextKeyLeftItem()
}
Keys.onRightPressed: {
FocusController.nextKeyRightItem()
}
ScrollBar.vertical: ScrollBarType {}
model: labelsModel
clip: true
reuseItems: true
delegate: ColumnLayout {
width: listView.width
spacing: 0
LabelWithImageType {
Layout.fillWidth: true
Layout.margins: 16
imageSource: objectImageSource
leftText: title
rightText: ApiServicesModel.getSelectedServiceData(contentKey)
imageSource: "qrc:/images/controls/map-pin.svg"
leftText: qsTr("For the region")
rightText: ApiServicesModel.getSelectedServiceData("region")
}
LabelWithImageType {
Layout.fillWidth: true
Layout.margins: 16
imageSource: "qrc:/images/controls/tag.svg"
leftText: qsTr("Price")
rightText: ApiServicesModel.getSelectedServiceData("price")
}
LabelWithImageType {
property bool showSubscriptionEndDate: ServersModel.getProcessedServerData("isCountrySelectionAvailable")
Layout.fillWidth: true
Layout.margins: 16
imageSource: "qrc:/images/controls/history.svg"
leftText: showSubscriptionEndDate ? qsTr("Valid until") : qsTr("Work period")
rightText: showSubscriptionEndDate ? ApiServicesModel.getSelectedServiceData("endDate")
: ApiServicesModel.getSelectedServiceData("workPeriod")
visible: rightText !== ""
}
}
footer: ColumnLayout {
width: listView.width
spacing: 0
LabelWithImageType {
Layout.fillWidth: true
Layout.margins: 16
imageSource: "qrc:/images/controls/gauge.svg"
leftText: qsTr("Speed")
rightText: ApiServicesModel.getSelectedServiceData("speed")
}
ParagraphTextType {
Layout.fillWidth: true
@@ -127,8 +88,6 @@ PageType {
return text.replace("%1", LanguageModel.getCurrentSiteUrl())
}
visible: text !== ""
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton

View File

@@ -252,7 +252,7 @@ PageType {
Layout.fillWidth: true
textField.placeholderText: qsTr("application name")
textFieldPlaceholderText: qsTr("application name")
buttonImageSource: "qrc:/images/controls/plus.svg"
rightButtonClickedOnEnter: true

View File

@@ -67,7 +67,7 @@ PageType {
Layout.fillWidth: true
headerText: qsTr("Primary DNS")
textField.text: SettingsController.primaryDns
textFieldText: SettingsController.primaryDns
textField.validator: RegularExpressionValidator {
regularExpression: InstallController.ipAddressRegExp()
}
@@ -79,7 +79,7 @@ PageType {
Layout.fillWidth: true
headerText: qsTr("Secondary DNS")
textField.text: SettingsController.secondaryDns
textFieldText: SettingsController.secondaryDns
textField.validator: RegularExpressionValidator {
regularExpression: InstallController.ipAddressRegExp()
}
@@ -105,9 +105,9 @@ PageType {
var yesButtonFunction = function() {
SettingsController.primaryDns = "1.1.1.1"
primaryDns.textField.text = SettingsController.primaryDns
primaryDns.textFieldText = SettingsController.primaryDns
SettingsController.secondaryDns = "1.0.0.1"
secondaryDns.textField.text = SettingsController.secondaryDns
secondaryDns.textFieldText = SettingsController.secondaryDns
PageController.showNotificationMessage(qsTr("Settings have been reset"))
}
var noButtonFunction = function() {
@@ -125,11 +125,11 @@ PageType {
text: qsTr("Save")
clickedFunc: function() {
if (primaryDns.textField.text !== SettingsController.primaryDns) {
SettingsController.primaryDns = primaryDns.textField.text
if (primaryDns.textFieldText !== SettingsController.primaryDns) {
SettingsController.primaryDns = primaryDns.textFieldText
}
if (secondaryDns.textField.text !== SettingsController.secondaryDns) {
SettingsController.secondaryDns = secondaryDns.textField.text
if (secondaryDns.textFieldText !== SettingsController.secondaryDns) {
SettingsController.secondaryDns = secondaryDns.textFieldText
}
PageController.showNotificationMessage(qsTr("Settings saved"))
}

View File

@@ -137,8 +137,6 @@ PageType {
Layout.topMargin: -8
Layout.bottomMargin: -8
visible: !GC.isMobile()
text: qsTr("Open logs folder")
leftImageSource: "qrc:/images/controls/folder-open.svg"
isSmallLeftImage: true

View File

@@ -142,7 +142,7 @@ PageType {
Layout.fillWidth: true
headerText: qsTr("Server name")
textField.text: root.processedServer.name
textFieldText: root.processedServer.name
textField.maximumLength: 30
checkEmptyText: true
}
@@ -155,12 +155,12 @@ PageType {
text: qsTr("Save")
clickedFunc: function() {
if (serverName.textField.text === "") {
if (serverName.textFieldText === "") {
return
}
if (serverName.textField.text !== root.processedServer.name) {
ServersModel.setProcessedServerData("name", serverName.textField.text);
if (serverName.textFieldText !== root.processedServer.name) {
ServersModel.setProcessedServerData("name", serverName.textFieldText);
}
serverNameEditDrawer.closeTriggered()
}

View File

@@ -274,13 +274,13 @@ PageType {
Layout.fillWidth: true
rightButtonClickedOnEnter: true
textField.placeholderText: qsTr("website or IP")
textFieldPlaceholderText: qsTr("website or IP")
buttonImageSource: "qrc:/images/controls/plus.svg"
clickedFunc: function() {
PageController.showBusyIndicator(true)
SitesController.addSite(textField.text)
textField.text = ""
SitesController.addSite(textFieldText)
textFieldText = ""
PageController.showBusyIndicator(false)
}
}
@@ -338,6 +338,7 @@ PageType {
LabelWithButtonType {
id: exportSitesButton
enabled: !SettingsController.isOnTv()
Layout.fillWidth: true
text: qsTr("Save site list")
@@ -361,7 +362,9 @@ PageType {
}
}
DividerType {}
DividerType {
enabled: !SettingsController.isOnTv()
}
}
}

View File

@@ -163,12 +163,12 @@ PageType {
Layout.rightMargin: 16
Layout.leftMargin: 16
visible: textKey.textField.text !== ""
visible: textKey.textFieldText !== ""
text: qsTr("Continue")
clickedFunc: function() {
if (ImportController.extractConfigFromData(textKey.textField.text)) {
if (ImportController.extractConfigFromData(textKey.textFieldText)) {
PageController.goToPage(PageEnum.PageSetupWizardViewConfig)
}
}
@@ -217,8 +217,6 @@ PageType {
Layout.alignment: Qt.AlignHCenter
implicitHeight: 32
visible: Qt.platform.os !== "ios"
defaultColor: AmneziaStyle.color.transparent
hoveredColor: AmneziaStyle.color.translucentWhite
pressedColor: AmneziaStyle.color.sheerWhite
@@ -332,7 +330,7 @@ PageType {
property string title: qsTr("I have nothing")
property string description: qsTr("")
property string imageSource: "qrc:/images/controls/help-circle.svg"
property bool isVisible: PageController.isStartPageVisible() && Qt.platform.os !== "ios"
property bool isVisible: PageController.isStartPageVisible()
property var handler: function() {
Qt.openUrlExternally(LanguageModel.getCurrentSiteUrl())
}

View File

@@ -82,19 +82,24 @@ PageType {
reuseItems: true
delegate: ColumnLayout {
property alias textField: _textField.textField
width: listView.width
TextFieldWithHeaderType {
id: delegate
id: _textField
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
property bool hidePassword: hideText
headerText: title
textField.echoMode: hideContent ? TextInput.Password : TextInput.Normal
textField.placeholderText: placeholderContent
textField.text: textField.text
textField.echoMode: hideText ? TextInput.Password : TextInput.Normal
buttonImageSource: imageSource
textFieldPlaceholderText: placeholderText
textField.text: textFieldText
rightButtonClickedOnEnter: true
@@ -103,12 +108,17 @@ PageType {
}
textField.onFocusChanged: {
textField.text = textField.text.replace(/^\s+|\s+$/g, '')
var _currentIndex = listView.currentIndex
var _currentItem = listView.itemAtIndex(_currentIndex).children[0]
listView.model[_currentIndex].textFieldText = _currentItem.textFieldText.replace(/^\s+|\s+$/g, '')
}
textField.onTextChanged: {
if (hideContent) {
buttonImageSource = textField.text !== "" ? (hideContent ? "qrc:/images/controls/eye.svg" : "qrc:/images/controls/eye-off.svg") : ""
var _currentIndex = listView.currentIndex
textFieldText = textField.text
if (_currentIndex === vars.secretDataIndex) {
buttonImageSource = textFieldText !== "" ? (hideText ? "qrc:/images/controls/eye.svg" : "qrc:/images/controls/eye-off.svg") : ""
}
}
}
@@ -133,9 +143,9 @@ PageType {
}
InstallController.setShouldCreateServer(true)
var _hostname = listView.itemAtIndex(vars.hostnameIndex).children[0].textField.text
var _username = listView.itemAtIndex(vars.usernameIndex).children[0].textField.text
var _secretData = listView.itemAtIndex(vars.secretDataIndex).children[0].textField.text
var _hostname = listView.itemAtIndex(vars.hostnameIndex).children[0].textFieldText
var _username = listView.itemAtIndex(vars.usernameIndex).children[0].textFieldText
var _secretData = listView.itemAtIndex(vars.secretDataIndex).children[0].textFieldText
InstallController.setProcessedServerCredentials(_hostname, _username, _secretData)
@@ -184,23 +194,23 @@ PageType {
function isCredentialsFilled() {
var hasEmptyField = false
var hostnameItem = listView.itemAtIndex(vars.hostnameIndex).children[0]
if (hostnameItem.textField.text === "") {
hostnameItem.errorText = qsTr("Ip address cannot be empty")
var _hostname = listView.itemAtIndex(vars.hostnameIndex).children[0]
if (_hostname.textFieldText === "") {
_hostname.errorText = qsTr("Ip address cannot be empty")
hasEmptyField = true
} else if (!hostnameItem.textField.acceptableInput) {
hostnameItem.errorText = qsTr("Enter the address in the format 255.255.255.255:88")
} else if (!_hostname.textField.acceptableInput) {
_hostname.errorText = qsTr("Enter the address in the format 255.255.255.255:88")
}
var usernameItem = listView.itemAtIndex(vars.usernameIndex).children[0]
if (usernameItem.textField.text === "") {
usernameItem.errorText = qsTr("Login cannot be empty")
var _username = listView.itemAtIndex(vars.usernameIndex).children[0]
if (_username.textFieldText === "") {
_username.errorText = qsTr("Login cannot be empty")
hasEmptyField = true
}
var secretDataItem = listView.itemAtIndex(vars.secretDataIndex).children[0]
if (secretDataItem.textField.text === "") {
secretDataItem.errorText = qsTr("Password/private key cannot be empty")
var _secretData = listView.itemAtIndex(vars.secretDataIndex).children[0]
if (_secretData.textFieldText === "") {
_secretData.errorText = qsTr("Password/private key cannot be empty")
hasEmptyField = true
}
@@ -208,37 +218,46 @@ PageType {
}
property list<QtObject> inputFields: [
hostnameObject,
usernameObject,
secretDataObject
hostname,
username,
secretData
]
QtObject {
id: hostnameObject
id: hostname
property string title: qsTr("Server IP address [:port]")
readonly property string placeholderContent: qsTr("255.255.255.255:22")
property bool hideContent: false
readonly property var clickedHandler: undefined
readonly property string placeholderText: qsTr("255.255.255.255:22")
property string textFieldText: ""
property bool hideText: false
property string imageSource: ""
readonly property var clickedHandler: function() {
console.debug(">>> Server IP address text field was clicked!!!")
clicked()
}
}
QtObject {
id: usernameObject
id: username
property string title: qsTr("SSH Username")
readonly property string placeholderContent: "root"
property bool hideContent: false
readonly property string placeholderText: "root"
property string textFieldText: ""
property bool hideText: false
property string imageSource: ""
readonly property var clickedHandler: undefined
}
QtObject {
id: secretDataObject
id: secretData
property string title: qsTr("Password or SSH private key")
readonly property string placeholderContent: ""
property bool hideContent: true
readonly property string placeholderText: ""
property string textFieldText: ""
property bool hideText: true
property string imageSource: textFieldText !== "" ? (hideText ? "qrc:/images/controls/eye.svg" : "qrc:/images/controls/eye-off.svg") : ""
readonly property var clickedHandler: function() {
hideContent = !hideContent
hideText = !hideText
}
}

View File

@@ -257,7 +257,7 @@ PageType {
}
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
InstallController.install(dockerContainer, port.textField.text, transportProtoSelector.currentIndex)
InstallController.install(dockerContainer, port.textFieldText, transportProtoSelector.currentIndex)
}
}
@@ -267,7 +267,7 @@ PageType {
if (ProtocolProps.defaultPort(defaultContainerProto) < 0) {
port.visible = false
} else {
port.textField.text = ProtocolProps.getPortForInstall(defaultContainerProto)
port.textFieldText = ProtocolProps.getPortForInstall(defaultContainerProto)
}
transportProtoSelector.currentIndex = ProtocolProps.defaultTransportProto(defaultContainerProto)

View File

@@ -51,7 +51,7 @@ PageType {
Layout.leftMargin: 16
headerText: qsTr("Key")
textField.placeholderText: "vpn://"
textFieldPlaceholderText: "vpn://"
buttonText: qsTr("Insert")
clickedFunc: function() {
@@ -75,7 +75,7 @@ PageType {
text: qsTr("Continue")
clickedFunc: function() {
if (ImportController.extractConfigFromData(textKey.textField.text)) {
if (ImportController.extractConfigFromData(textKey.textFieldText)) {
PageController.goToPage(PageEnum.PageSetupWizardViewConfig)
}
}

View File

@@ -51,25 +51,25 @@ PageType {
switch (type) {
case PageShare.ConfigType.AmneziaConnection: {
ExportController.generateConnectionConfig(clientNameTextField.textField.text);
ExportController.generateConnectionConfig(clientNameTextField.textFieldText);
break;
}
case PageShare.ConfigType.OpenVpn: {
ExportController.generateOpenVpnConfig(clientNameTextField.textField.text)
ExportController.generateOpenVpnConfig(clientNameTextField.textFieldText)
shareConnectionDrawer.configCaption = qsTr("Save OpenVPN config")
shareConnectionDrawer.configExtension = ".ovpn"
shareConnectionDrawer.configFileName = "amnezia_for_openvpn"
break
}
case PageShare.ConfigType.WireGuard: {
ExportController.generateWireGuardConfig(clientNameTextField.textField.text)
ExportController.generateWireGuardConfig(clientNameTextField.textFieldText)
shareConnectionDrawer.configCaption = qsTr("Save WireGuard config")
shareConnectionDrawer.configExtension = ".conf"
shareConnectionDrawer.configFileName = "amnezia_for_wireguard"
break
}
case PageShare.ConfigType.Awg: {
ExportController.generateAwgConfig(clientNameTextField.textField.text)
ExportController.generateAwgConfig(clientNameTextField.textFieldText)
shareConnectionDrawer.configCaption = qsTr("Save AmneziaWG config")
shareConnectionDrawer.configExtension = ".conf"
shareConnectionDrawer.configFileName = "amnezia_for_awg"
@@ -90,7 +90,7 @@ PageType {
break
}
case PageShare.ConfigType.Xray: {
ExportController.generateXrayConfig(clientNameTextField.textField.text)
ExportController.generateXrayConfig(clientNameTextField.textFieldText)
shareConnectionDrawer.configCaption = qsTr("Save XRay config")
shareConnectionDrawer.configExtension = ".json"
shareConnectionDrawer.configFileName = "amnezia_for_xray"
@@ -296,7 +296,7 @@ PageType {
visible: accessTypeSelector.currentIndex === 0
headerText: qsTr("User name")
textField.text: "New client"
textFieldText: "New client"
textField.maximumLength: 20
checkEmptyText: true
@@ -525,7 +525,7 @@ PageType {
parentFlickable: a
clickedFunc: function(){
if (clientNameTextField.textField.text !== "") {
if (clientNameTextField.textFieldText !== "") {
ExportController.generateConfig(root.connectionTypesModel[exportTypeSelector.currentIndex].type)
}
}
@@ -555,14 +555,14 @@ PageType {
id: searchTextField
Layout.fillWidth: true
textField.placeholderText: qsTr("Search")
textFieldPlaceholderText: qsTr("Search")
Keys.onEscapePressed: {
root.isSearchBarVisible = false
}
function navigateTo() {
if (searchTextField.textField.text === "") {
if (searchTextField.textFieldText === "") {
root.isSearchBarVisible = false
}
}
@@ -601,7 +601,7 @@ PageType {
sourceModel: ClientManagementModel
filters: RegExpFilter {
roleName: "clientName"
pattern: ".*" + searchTextField.textField.text + ".*"
pattern: ".*" + searchTextField.textFieldText + ".*"
caseSensitivity: Qt.CaseInsensitive
}
}
@@ -765,7 +765,7 @@ PageType {
id: clientNameEditor
Layout.fillWidth: true
headerText: qsTr("Client name")
textField.text: clientName
textFieldText: clientName
textField.maximumLength: 20
checkEmptyText: true
}
@@ -778,14 +778,14 @@ PageType {
text: qsTr("Save")
clickedFunc: function() {
if (clientNameEditor.textField.text === "") {
if (clientNameEditor.textFieldText === "") {
return
}
if (clientNameEditor.textField.text !== clientName) {
if (clientNameEditor.textFieldText !== clientName) {
PageController.showBusyIndicator(true)
ExportController.renameClient(index,
clientNameEditor.textField.text,
clientNameEditor.textFieldText,
ContainersModel.getProcessedContainerIndex(),
ServersModel.getProcessedServerCredentials())
PageController.showBusyIndicator(false)

View File

@@ -176,12 +176,12 @@ Window {
Connections {
target: privateKeyPassphraseDrawer
function onOpened() {
passphrase.textField.text = ""
passphrase.textFieldText = ""
passphrase.textField.forceActiveFocus()
}
function onAboutToHide() {
if (passphrase.textField.text !== "") {
if (passphrase.textFieldText !== "") {
PageController.showBusyIndicator(true)
}
}
@@ -222,7 +222,7 @@ Window {
clickedFunc: function() {
privateKeyPassphraseDrawer.closeTriggered()
PageController.passphraseRequestDrawerClosed(passphrase.textField.text)
PageController.passphraseRequestDrawerClosed(passphrase.textFieldText)
}
}
}

View File

@@ -215,9 +215,10 @@ ErrorCode VpnConnection::lastError() const
void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &vpnConfiguration)
{
qDebug() << QString("Trying to connect to VPN, server index is %1, container is %2")
qDebug() << QString("ConnectToVpn, Server index is %1, container is %2, route mode is")
.arg(serverIndex)
.arg(ContainerProps::containerToString(container));
.arg(ContainerProps::containerToString(container))
<< m_settings->routeMode();
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
if (!m_IpcClient) {
m_IpcClient = new IpcClient(this);
@@ -340,26 +341,26 @@ void VpnConnection::appendSplitTunnelingConfig()
}
}
Settings::RouteMode sitesRouteMode = Settings::RouteMode::VpnAllSites;
Settings::RouteMode routeMode = Settings::RouteMode::VpnAllSites;
QJsonArray sitesJsonArray;
if (m_settings->isSitesSplitTunnelingEnabled()) {
sitesRouteMode = m_settings->routeMode();
routeMode = m_settings->routeMode();
if (allowSiteBasedSplitTunneling) {
auto sites = m_settings->getVpnIps(sitesRouteMode);
auto sites = m_settings->getVpnIps(routeMode);
for (const auto &site : sites) {
sitesJsonArray.append(site);
}
// Allow traffic to Amnezia DNS
if (sitesRouteMode == Settings::VpnOnlyForwardSites) {
if (routeMode == Settings::VpnOnlyForwardSites) {
sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns1).toString());
sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns2).toString());
}
}
}
m_vpnConfiguration.insert(config_key::splitTunnelType, sitesRouteMode);
m_vpnConfiguration.insert(config_key::splitTunnelType, routeMode);
m_vpnConfiguration.insert(config_key::splitTunnelSites, sitesJsonArray);
Settings::AppsRouteMode appsRouteMode = Settings::AppsRouteMode::VpnAllApps;
@@ -375,13 +376,6 @@ void VpnConnection::appendSplitTunnelingConfig()
m_vpnConfiguration.insert(config_key::appSplitTunnelType, appsRouteMode);
m_vpnConfiguration.insert(config_key::splitTunnelApps, appsJsonArray);
qDebug() << QString("Site split tunneling is %1, route mode is %2")
.arg(m_settings->isSitesSplitTunnelingEnabled() ? "enabled" : "disabled")
.arg(sitesRouteMode);
qDebug() << QString("App split tunneling is %1, route mode is %2")
.arg(m_settings->isAppsSplitTunnelingEnabled() ? "enabled" : "disabled")
.arg(appsRouteMode);
}
#ifdef Q_OS_ANDROID