Compare commits

..

5 Commits

Author SHA1 Message Date
vladimir.kuznetsov 2445058801 chore: fixed external premium visability 2025-04-08 15:31:23 +08:00
vladimir.kuznetsov fb63d75f4a Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD 2025-04-08 15:09:22 +08:00
vladimir.kuznetsov 00d48bb97d Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD 2025-04-07 12:58:40 +08:00
vladimir.kuznetsov 66eb35bd31 feature: added "external-premium" service-type 2025-04-07 12:58:12 +08:00
vladimir.kuznetsov 0da108e809 feature: retrieving support info from gateway 2025-03-20 22:31:47 +07:00
25 changed files with 2839 additions and 6818 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ env:
jobs: jobs:
Build-Linux-Ubuntu: Build-Linux-Ubuntu:
runs-on: ubuntu-22.04 runs-on: ubuntu-20.04
env: env:
QT_VERSION: 6.6.2 QT_VERSION: 6.6.2
+42 -19
View File
@@ -1,41 +1,64 @@
name: 'Upload a new version' name: 'Upload a new version'
on: on:
workflow_dispatch: push:
inputs: tags:
RELEASE_VERSION: - '[0-9]+.[0-9]+.[0-9]+.[0-9]+'
description: 'Release version (e.g. 1.2.3.4)'
required: true
type: string
jobs: jobs:
Upload-S3: upload:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: upload
steps: steps:
- name: Checkout - name: Checkout CMakeLists.txt
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
ref: ${{ inputs.RELEASE_VERSION }} ref: ${{ github.ref_name }}
sparse-checkout: | sparse-checkout: |
CMakeLists.txt CMakeLists.txt
deploy/deploy_s3.sh
sparse-checkout-cone-mode: false sparse-checkout-cone-mode: false
- name: Verify git tag - name: Verify git tag
run: | run: |
TAG_NAME=${{ inputs.RELEASE_VERSION }} GIT_TAG=${{ github.ref_name }}
CMAKE_TAG=$(grep 'project.*VERSION' CMakeLists.txt | sed -E 's/.* ([0-9]+.[0-9]+.[0-9]+.[0-9]+)$/\1/') CMAKE_TAG=$(grep 'project.*VERSION' CMakeLists.txt | sed -E 's/.* ([0-9]+.[0-9]+.[0-9]+.[0-9]+)$/\1/')
if [[ "$TAG_NAME" == "$CMAKE_TAG" ]]; then
echo "Git tag ($TAG_NAME) matches CMakeLists.txt version ($CMAKE_TAG)." if [[ "$GIT_TAG" == "$CMAKE_TAG" ]]; then
echo "Git tag ($GIT_TAG) and version in CMakeLists.txt ($CMAKE_TAG) are the same. Continuing..."
else else
echo "::error::Mismatch: Git tag ($TAG_NAME) != CMakeLists.txt version ($CMAKE_TAG). Exiting with error..." echo "Git tag ($GIT_TAG) and version in CMakeLists.txt ($CMAKE_TAG) are not the same! Cancelling..."
exit 1 exit 1
fi fi
- name: Setup Rclone - name: Download artifacts from the "${{ github.ref_name }}" tag
uses: AnimMouse/setup-rclone@v1 uses: robinraju/release-downloader@v1.8
with: with:
rclone_config: ${{ secrets.RCLONE_CONFIG }} tag: ${{ github.ref_name }}
fileName: "AmneziaVPN_(Linux_|)${{ github.ref_name }}*"
out-file-path: ${{ github.ref_name }}
- name: Send dist to S3 - name: Upload beta version
run: bash deploy/deploy_s3.sh ${{ inputs.RELEASE_VERSION }} uses: jakejarvis/s3-sync-action@master
if: contains(github.event.base_ref, 'dev')
with:
args: --include "AmneziaVPN*" --delete
env:
AWS_S3_BUCKET: updates
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_SECRET_ACCESS_KEY }}
AWS_S3_ENDPOINT: https://${{ vars.CF_ACCOUNT_ID }}.r2.cloudflarestorage.com
SOURCE_DIR: ${{ github.ref_name }}
DEST_DIR: beta/${{ github.ref_name }}
- name: Upload stable version
uses: jakejarvis/s3-sync-action@master
if: contains(github.event.base_ref, 'master')
with:
args: --include "AmneziaVPN*" --delete
env:
AWS_S3_BUCKET: updates
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_SECRET_ACCESS_KEY }}
AWS_S3_ENDPOINT: https://${{ vars.CF_ACCOUNT_ID }}.r2.cloudflarestorage.com
SOURCE_DIR: ${{ github.ref_name }}
DEST_DIR: stable/${{ github.ref_name }}
+2 -2
View File
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN) set(PROJECT AmneziaVPN)
project(${PROJECT} VERSION 4.8.6.0 project(${PROJECT} VERSION 4.8.5.0
DESCRIPTION "AmneziaVPN" DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/" HOMEPAGE_URL "https://amnezia.org/"
) )
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}") set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}) set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(APP_ANDROID_VERSION_CODE 2083) set(APP_ANDROID_VERSION_CODE 2082)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux") set(MZ_PLATFORM_NAME "linux")
-1
View File
@@ -68,7 +68,6 @@ amnezia::ErrorCode apiUtils::checkNetworkReplyErrors(const QList<QSslError> &ssl
return amnezia::ErrorCode::NoError; return amnezia::ErrorCode::NoError;
} else if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError } else if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError
|| reply->error() == QNetworkReply::NetworkError::TimeoutError) { || reply->error() == QNetworkReply::NetworkError::TimeoutError) {
qDebug() << reply->error();
return amnezia::ErrorCode::ApiConfigTimeoutError; return amnezia::ErrorCode::ApiConfigTimeoutError;
} else { } else {
QString err = reply->errorString(); QString err = reply->errorString();
+4 -10
View File
@@ -251,9 +251,6 @@ QStringList GatewayController::getProxyUrls()
} }
return endpoints; return endpoints;
} else { } else {
apiUtils::checkNetworkReplyErrors(sslErrors, reply);
qDebug() << "go to the next storage endpoint";
reply->deleteLater(); reply->deleteLater();
} }
} }
@@ -264,29 +261,26 @@ bool GatewayController::shouldBypassProxy(QNetworkReply *reply, const QByteArray
const QByteArray &iv, const QByteArray &salt) const QByteArray &iv, const QByteArray &salt)
{ {
if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError || reply->error() == QNetworkReply::NetworkError::TimeoutError) { if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError || reply->error() == QNetworkReply::NetworkError::TimeoutError) {
qDebug() << "timeout occurred"; qDebug() << "Timeout occurred";
qDebug() << reply->error();
return true; return true;
} else if (responseBody.contains("html")) { } else if (responseBody.contains("html")) {
qDebug() << "the response contains an html tag"; qDebug() << "The response contains an html tag";
return true; return true;
} else if (reply->error() == QNetworkReply::NetworkError::ContentNotFoundError) { } else if (reply->error() == QNetworkReply::NetworkError::ContentNotFoundError) {
if (responseBody.contains(errorResponsePattern1) || responseBody.contains(errorResponsePattern2) if (responseBody.contains(errorResponsePattern1) || responseBody.contains(errorResponsePattern2)
|| responseBody.contains(errorResponsePattern3)) { || responseBody.contains(errorResponsePattern3)) {
return false; return false;
} else { } else {
qDebug() << reply->error();
return true; return true;
} }
} else if (reply->error() != QNetworkReply::NetworkError::NoError) { } else if (reply->error() != QNetworkReply::NetworkError::NoError) {
qDebug() << reply->error();
return true; return true;
} else if (checkEncryption) { } else if (checkEncryption) {
try { try {
QSimpleCrypto::QBlockCipher blockCipher; QSimpleCrypto::QBlockCipher blockCipher;
static_cast<void>(blockCipher.decryptAesBlockCipher(responseBody, key, iv, "", salt)); static_cast<void>(blockCipher.decryptAesBlockCipher(responseBody, key, iv, "", salt));
} catch (...) { } catch (...) {
qDebug() << "failed to decrypt the data"; qDebug() << "Failed to decrypt the data";
return true; return true;
} }
} }
@@ -307,7 +301,7 @@ void GatewayController::bypassProxy(const QString &endpoint, QNetworkReply *repl
QByteArray responseBody; QByteArray responseBody;
for (const QString &proxyUrl : proxyUrls) { for (const QString &proxyUrl : proxyUrls) {
qDebug() << "go to the next proxy endpoint"; qDebug() << "Go to the next endpoint";
reply->deleteLater(); // delete the previous reply reply->deleteLater(); // delete the previous reply
reply = requestFunction(endpoint.arg(proxyUrl)); reply = requestFunction(endpoint.arg(proxyUrl));
+9 -23
View File
@@ -138,7 +138,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
if (overwriteMode == libssh::ScpOverwriteMode::ScpOverwriteExisting) { if (overwriteMode == libssh::ScpOverwriteMode::ScpOverwriteExisting) {
e = runScript(credentials, e = runScript(credentials,
replaceVars(QStringLiteral("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName, path), replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(path),
genVarsForScript(credentials, container)), genVarsForScript(credentials, container)),
cbReadStd, cbReadStd); cbReadStd, cbReadStd);
@@ -146,7 +146,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
return e; return e;
} else if (overwriteMode == libssh::ScpOverwriteMode::ScpAppendToExisting) { } else if (overwriteMode == libssh::ScpOverwriteMode::ScpAppendToExisting) {
e = runScript(credentials, e = runScript(credentials,
replaceVars(QStringLiteral("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName, tmpFileName), replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(tmpFileName),
genVarsForScript(credentials, container)), genVarsForScript(credentials, container)),
cbReadStd, cbReadStd); cbReadStd, cbReadStd);
@@ -154,7 +154,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
return e; return e;
e = runScript(credentials, e = runScript(credentials,
replaceVars(QStringLiteral("sudo docker exec -i $CONTAINER_NAME sh -c \"cat %1 >> %2\"").arg(tmpFileName, path), replaceVars(QString("sudo docker exec -i $CONTAINER_NAME sh -c \"cat %1 >> %2\"").arg(tmpFileName).arg(path),
genVarsForScript(credentials, container)), genVarsForScript(credentials, container)),
cbReadStd, cbReadStd); cbReadStd, cbReadStd);
@@ -177,7 +177,7 @@ QByteArray ServerController::getTextFileFromContainer(DockerContainer container,
errorCode = ErrorCode::NoError; errorCode = ErrorCode::NoError;
QString script = QStringLiteral("sudo docker exec -i %1 sh -c \"xxd -p '%2'\"").arg(ContainerProps::containerToString(container), path); QString script = QString("sudo docker exec -i %1 sh -c \"xxd -p \'%2\'\"").arg(ContainerProps::containerToString(container)).arg(path);
QString stdOut; QString stdOut;
auto cbReadStdOut = [&](const QString &data, libssh::Client &) { auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
@@ -383,13 +383,6 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
return true; return true;
} }
if (container == DockerContainer::Xray) {
if (oldProtoConfig.value(config_key::port).toString(protocols::xray::defaultPort)
!= newProtoConfig.value(config_key::port).toString(protocols::xray::defaultPort)) {
return true;
}
}
return false; return false;
} }
@@ -446,22 +439,15 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
stdOut += data + "\n"; stdOut += data + "\n";
return ErrorCode::NoError; return ErrorCode::NoError;
}; };
auto cbReadStdErr = [&](const QString &data, libssh::Client &) {
stdOut += data + "\n";
return ErrorCode::NoError;
};
ErrorCode error = errorCode =
runScript(credentials, runScript(credentials,
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)), replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
cbReadStdOut, cbReadStdErr); cbReadStdOut);
if (errorCode)
if (stdOut.contains("doesn't work on cgroups v2")) return errorCode;
return ErrorCode::ServerDockerOnCgroupsV2;
if (stdOut.contains("cgroup mountpoint does not exist"))
return ErrorCode::ServerCgroupMountpoint;
return error; return errorCode;
} }
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config) ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
-2
View File
@@ -58,8 +58,6 @@ namespace amnezia
ServerUserDirectoryNotAccessible = 208, ServerUserDirectoryNotAccessible = 208,
ServerUserNotAllowedInSudoers = 209, ServerUserNotAllowedInSudoers = 209,
ServerUserPasswordRequired = 210, ServerUserPasswordRequired = 210,
ServerDockerOnCgroupsV2 = 211,
ServerCgroupMountpoint = 212,
// Ssh connection errors // Ssh connection errors
SshRequestDeniedError = 300, SshRequestDeniedError = 300,
-2
View File
@@ -26,8 +26,6 @@ QString errorString(ErrorCode code) {
case(ErrorCode::ServerUserDirectoryNotAccessible): errorMessage = QObject::tr("The server user's home directory is not accessible"); break; case(ErrorCode::ServerUserDirectoryNotAccessible): errorMessage = QObject::tr("The server user's home directory is not accessible"); break;
case(ErrorCode::ServerUserNotAllowedInSudoers): errorMessage = QObject::tr("Action not allowed in sudoers"); 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; case(ErrorCode::ServerUserPasswordRequired): errorMessage = QObject::tr("The user's password is required"); break;
case(ErrorCode::ServerDockerOnCgroupsV2): errorMessage = QObject::tr("Docker error: runc doesn't work on cgroups v2"); break;
case(ErrorCode::ServerCgroupMountpoint): errorMessage = QObject::tr("Server error: cgroup mountpoint does not exist"); break;
// Libssh errors // Libssh errors
case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("SSH request was denied"); break; case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("SSH request was denied"); break;
-1
View File
@@ -6,7 +6,6 @@
#define INTERFACECONFIG_H #define INTERFACECONFIG_H
#include <QList> #include <QList>
#include <QMap>
#include <QString> #include <QString>
#include "ipaddress.h" #include "ipaddress.h"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+95 -180
View File
@@ -3,14 +3,10 @@
<TS version="2.1" language="ru_RU"> <TS version="2.1" language="ru_RU">
<context> <context>
<name>AdLabel</name> <name>AdLabel</name>
<message>
<source>Amnezia Premium - for access to any website</source>
<translation type="vanished">Amnezia Premium - для доступа к любым сайтам</translation>
</message>
<message> <message>
<location filename="../ui/qml/Components/AdLabel.qml" line="57"/> <location filename="../ui/qml/Components/AdLabel.qml" line="57"/>
<source>Amnezia Premium - for access to all websites and online resources</source> <source>Amnezia Premium - for access to any website</source>
<translation>Amnezia Premium - доступ ко всем сайтам и онлайн ресурсам</translation> <translation>Amnezia Premium - для доступа к любым сайтам</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -60,12 +56,12 @@
<translation>%1 успешно установлен.</translation> <translation>%1 успешно установлен.</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/api/apiConfigsController.cpp" line="257"/> <location filename="../ui/controllers/api/apiConfigsController.cpp" line="258"/>
<source>API config reloaded</source> <source>API config reloaded</source>
<translation>Конфигурация API перезагружена</translation> <translation>Конфигурация API перезагружена</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/api/apiConfigsController.cpp" line="261"/> <location filename="../ui/controllers/api/apiConfigsController.cpp" line="262"/>
<source>Successfully changed the country of connection to %1</source> <source>Successfully changed the country of connection to %1</source>
<translation>Страна подключения изменена на %1</translation> <translation>Страна подключения изменена на %1</translation>
</message> </message>
@@ -94,8 +90,9 @@
<translation type="vanished">Amnezia Free - это бесплатный VPN для обхода блокировок в странах с высоким уровнем интернет-цензуры</translation> <translation type="vanished">Amnezia Free - это бесплатный VPN для обхода блокировок в странах с высоким уровнем интернет-цензуры</translation>
</message> </message>
<message> <message>
<location filename="../ui/models/api/apiServicesModel.cpp" line="68"/>
<source>Amnezia Premium is VPN for comfortable work, downloading large files and watching videos in 8K resolution. Works for any sites with no restrictions. Speed up to %1 MBit/s. Unlimited traffic.</source> <source>Amnezia Premium is VPN for comfortable work, downloading large files and watching videos in 8K resolution. Works for any sites with no restrictions. Speed up to %1 MBit/s. Unlimited traffic.</source>
<translation type="vanished">Amnezia Premium VPN для комфортной работы, скачивания больших файлов и просмотра видео в высоком разрешении. Скорость до %1 Мбит/с. Безлимитный трафик.</translation> <translation>Amnezia Premium VPN для комфортной работы, скачивания больших файлов и просмотра видео в высоком разрешении. Скорость до %1 Мбит/с. Безлимитный трафик.</translation>
</message> </message>
<message> <message>
<location filename="../ui/models/api/apiServicesModel.cpp" line="72"/> <location filename="../ui/models/api/apiServicesModel.cpp" line="72"/>
@@ -103,19 +100,10 @@
<source>AmneziaFree provides free unlimited access to a basic set of web sites, such as Facebook, Instagram, Twitter (X), Discord, Telegram, and others. YouTube is not included in the free plan.</source> <source>AmneziaFree provides free unlimited access to a basic set of web sites, such as Facebook, Instagram, Twitter (X), Discord, Telegram, and others. YouTube is not included in the free plan.</source>
<translation>AmneziaFree предоставляет бесплатный неограниченный доступ к базовому набору сайтов и приложений, таким как Facebook, Instagram, Twitter (X), Discord, Telegram и другим. YouTube не включен в бесплатный тариф.</translation> <translation>AmneziaFree предоставляет бесплатный неограниченный доступ к базовому набору сайтов и приложений, таким как Facebook, Instagram, Twitter (X), Discord, Telegram и другим. YouTube не включен в бесплатный тариф.</translation>
</message> </message>
<message>
<source>Amnezia Premium is VPN for comfortable work, downloading large files and watching videos in 8K resolution. Works for any sites with no restrictions.</source>
<translation type="vanished">Amnezia Premium VPN для комфортной работы, скачивания больших файлов и просмотра видео в высоком разрешении. Работает для любых сайтов без ограничений.</translation>
</message>
<message>
<location filename="../ui/models/api/apiServicesModel.cpp" line="68"/>
<source>Amnezia Premium is classic VPN for seamless work, downloading large files, and watching videos. Access all websites and online resources. Speeds up to %1 Mbps.</source>
<translation>Amnezia Premium - это классический VPN для комфортной работы, загрузки больших файлов и просмотра видео. Доступ ко всем сайтам и онлайн ресурсам. Скорость - до %1 Мбит/с.</translation>
</message>
<message> <message>
<location filename="../ui/models/api/apiServicesModel.cpp" line="82"/> <location filename="../ui/models/api/apiServicesModel.cpp" line="82"/>
<source>Amnezia Premium is classic VPN for for seamless work, downloading large files, and watching videos. Access all websites and online resources.</source> <source>Amnezia Premium is VPN for comfortable work, downloading large files and watching videos in 8K resolution. Works for any sites with no restrictions.</source>
<translation>Amnezia Premium - это классический VPN для комфортной работы, загрузки больших файлов и просмотра видео. Доступ ко всем сайтам и онлайн ресурсам.</translation> <translation>Amnezia Premium VPN для комфортной работы, скачивания больших файлов и просмотра видео в высоком разрешении. Работает для любых сайтов без ограничений.</translation>
</message> </message>
<message> <message>
<location filename="../ui/models/api/apiServicesModel.cpp" line="97"/> <location filename="../ui/models/api/apiServicesModel.cpp" line="97"/>
@@ -352,23 +340,14 @@ Can&apos;t be disabled for current server</source>
<translation type="vanished">Неверный файл конфигурации</translation> <translation type="vanished">Неверный файл конфигурации</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/importController.cpp" line="650"/> <location filename="../ui/controllers/importController.cpp" line="651"/>
<source>Scanned %1 of %2.</source> <source>Scanned %1 of %2.</source>
<translation>Отсканировано %1 из %2.</translation> <translation>Отсканировано %1 из %2.</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/importController.cpp" line="685"/> <location filename="../ui/controllers/importController.cpp" line="686"/>
<source>This configuration contains an OpenVPN setup. OpenVPN configurations can include malicious scripts, so only add it if you fully trust the provider of this config. </source>
<translation>Эта конфигурация содержит настройки OpenVPN. Конфигурации OpenVPN могут содержать вредоносные скрипты, поэтому добавляйте их только в том случае, если полностью доверяете источнику этого файла. </translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="689"/>
<source>&lt;br&gt;In the imported configuration, potentially dangerous lines were found:</source>
<translation>&lt;br&gt;В импортированной конфигурации обнаружены потенциально опасные строки:</translation>
</message>
<message>
<source>In the imported configuration, potentially dangerous lines were found:</source> <source>In the imported configuration, potentially dangerous lines were found:</source>
<translation type="vanished">В импортированной конфигурации были обнаружены потенциально опасные строки:</translation> <translation>В импортированной конфигурации были обнаружены потенциально опасные строки:</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -538,12 +517,12 @@ Already installed containers were found on the server. All installed containers
<message> <message>
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="68"/> <location filename="../ui/qml/Pages2/PageDevMenu.qml" line="68"/>
<source>Gateway endpoint</source> <source>Gateway endpoint</source>
<translation>Gateway endpoint</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="97"/> <location filename="../ui/qml/Pages2/PageDevMenu.qml" line="97"/>
<source>Dev gateway environment</source> <source>Dev gateway environment</source>
<translation>Dev gateway environment</translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context> <context>
@@ -673,47 +652,47 @@ Already installed containers were found on the server. All installed containers
<message> <message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="146"/> <location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="146"/>
<source>Jc - Junk packet count</source> <source>Jc - Junk packet count</source>
<translation>Jc - Junk packet count</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="168"/> <location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="168"/>
<source>Jmin - Junk packet minimum size</source> <source>Jmin - Junk packet minimum size</source>
<translation>Jmin - Junk packet minimum size</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="186"/> <location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="186"/>
<source>Jmax - Junk packet maximum size</source> <source>Jmax - Junk packet maximum size</source>
<translation>Jmax - Junk packet maximum size</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="204"/> <location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="204"/>
<source>S1 - Init packet junk size</source> <source>S1 - Init packet junk size</source>
<translation>S1 - Init packet junk size</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="228"/> <location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="228"/>
<source>S2 - Response packet junk size</source> <source>S2 - Response packet junk size</source>
<translation>S2 - Response packet junk size</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="252"/> <location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="252"/>
<source>H1 - Init packet magic header</source> <source>H1 - Init packet magic header</source>
<translation>H1 - Init packet magic header</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="270"/> <location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="270"/>
<source>H2 - Response packet magic header</source> <source>H2 - Response packet magic header</source>
<translation>H2 - Response packet magic header</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="288"/> <location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="288"/>
<source>H4 - Transport packet magic header</source> <source>H4 - Transport packet magic header</source>
<translation>H4 - Transport packet magic header</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="306"/> <location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="306"/>
<source>H3 - Underload packet magic header</source> <source>H3 - Underload packet magic header</source>
<translation>H3 - Underload packet magic header</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="354"/> <location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="354"/>
@@ -1482,7 +1461,7 @@ Already installed containers were found on the server. All installed containers
<message> <message>
<location filename="../ui/qml/Pages2/PageSettings.qml" line="123"/> <location filename="../ui/qml/Pages2/PageSettings.qml" line="123"/>
<source>Dev console</source> <source>Dev console</source>
<translation>Dev console</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettings.qml" line="142"/> <location filename="../ui/qml/Pages2/PageSettings.qml" line="142"/>
@@ -1609,13 +1588,9 @@ Already installed containers were found on the server. All installed containers
</context> </context>
<context> <context>
<name>PageSettingsApiDevices</name> <name>PageSettingsApiDevices</name>
<message>
<source>Active devices</source>
<translation type="vanished">Активные устройства</translation>
</message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiDevices.qml" line="45"/> <location filename="../ui/qml/Pages2/PageSettingsApiDevices.qml" line="45"/>
<source>Active Devices</source> <source>Active devices</source>
<translation>Активные устройства</translation> <translation>Активные устройства</translation>
</message> </message>
<message> <message>
@@ -1766,14 +1741,10 @@ Already installed containers were found on the server. All installed containers
<source>Save AmneziaVPN config</source> <source>Save AmneziaVPN config</source>
<translation>Сохранить конфигурацию AmneziaVPN</translation> <translation>Сохранить конфигурацию AmneziaVPN</translation>
</message> </message>
<message>
<source>Configuration files</source>
<translation type="vanished">Файл конфигурации</translation>
</message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiNativeConfigs.qml" line="48"/> <location filename="../ui/qml/Pages2/PageSettingsApiNativeConfigs.qml" line="48"/>
<source>Configuration Files</source> <source>Configuration files</source>
<translation>Файлы конфигурации</translation> <translation>Файл конфигурации</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiNativeConfigs.qml" line="49"/> <location filename="../ui/qml/Pages2/PageSettingsApiNativeConfigs.qml" line="49"/>
@@ -1861,8 +1832,9 @@ Already installed containers were found on the server. All installed containers
<translation type="vanished">Период работы</translation> <translation type="vanished">Период работы</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="37"/>
<source>Valid until</source> <source>Valid until</source>
<translation type="vanished">Действует до</translation> <translation>Действует до</translation>
</message> </message>
<message> <message>
<source>Speed</source> <source>Speed</source>
@@ -1873,12 +1845,14 @@ Already installed containers were found on the server. All installed containers
<translation type="vanished">Скопировано</translation> <translation type="vanished">Скопировано</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="29"/>
<source>Subscription status</source> <source>Subscription status</source>
<translation type="vanished">Статус подписки</translation> <translation>Статус подписки</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="45"/>
<source>Active connections</source> <source>Active connections</source>
<translation type="vanished">Активные соединения</translation> <translation>Активные соединения</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="171"/> <location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="171"/>
@@ -1886,8 +1860,9 @@ Already installed containers were found on the server. All installed containers
<translation>Сетевые адреса одного или нескольких серверов были обновлены. Пожалуйста, удалите старые конфигурацию и загрузите новые файлы</translation> <translation>Сетевые адреса одного или нескольких серверов были обновлены. Пожалуйста, удалите старые конфигурацию и загрузите новые файлы</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
<source>Subscription key</source> <source>Subscription key</source>
<translation type="vanished">Ключ для подключения</translation> <translation>Ключ для подключения</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/> <location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
@@ -1895,8 +1870,9 @@ Already installed containers were found on the server. All installed containers
<translation>Ключ подписки Amnezia Premium</translation> <translation>Ключ подписки Amnezia Premium</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="194"/>
<source>Save VPN key to file</source> <source>Save VPN key to file</source>
<translation type="vanished">Сохранить VPN-ключ в файле</translation> <translation>Сохранить VPN-ключ в файле</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="195"/> <location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="195"/>
@@ -1904,51 +1880,18 @@ Already installed containers were found on the server. All installed containers
<translation>Скопировать VPN ключ</translation> <translation>Скопировать VPN ключ</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="216"/>
<source>Configuration files</source> <source>Configuration files</source>
<translation type="vanished">Файл конфигурации</translation> <translation>Файл конфигурации</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="218"/> <location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="218"/>
<source>Manage configuration files</source> <source>Manage configuration files</source>
<translation>Управление файлами конфигурации</translation> <translation>Управление файлами конфигурации</translation>
</message> </message>
<message>
<source>Active devices</source>
<translation type="vanished">Активные устройства</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="29"/>
<source>Subscription Status</source>
<translation>Статус подписки</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="37"/>
<source>Valid Until</source>
<translation>Действительна до</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="45"/>
<source>Active Connections</source>
<translation>Активные соединения</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
<source>Subscription Key</source>
<translation>Ключ для подключения</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="194"/>
<source>Save VPN key as a file</source>
<translation>Сохранить VPN-ключ в файл</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="216"/>
<source>Configuration Files</source>
<translation>Файлы конфигурации</translation>
</message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="236"/> <location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="236"/>
<source>Active Devices</source> <source>Active devices</source>
<translation>Активные устройства</translation> <translation>Активные устройства</translation>
</message> </message>
<message> <message>
@@ -2038,13 +1981,9 @@ Already installed containers were found on the server. All installed containers
<source>Telegram</source> <source>Telegram</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Email Support</source>
<translation type="vanished">Email</translation>
</message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsApiSupport.qml" line="30"/> <location filename="../ui/qml/Pages2/PageSettingsApiSupport.qml" line="30"/>
<source>Email</source> <source>Email Support</source>
<translation>Email</translation> <translation>Email</translation>
</message> </message>
<message> <message>
@@ -2393,12 +2332,8 @@ Already installed containers were found on the server. All installed containers
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="143"/> <location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="143"/>
<source>Cannot change KillSwitch settings during active connection</source>
<translation>Невозможно изменить настройки KillSwitch во время активного подключения</translation>
</message>
<message>
<source>Cannot change killSwitch settings during active connection</source> <source>Cannot change killSwitch settings during active connection</source>
<translation type="vanished">Невозможно изменить настройки аварийного выключателя во время активного соединения</translation> <translation>Невозможно изменить настройки аварийного выключателя во время активного соединения</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="86"/> <location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="86"/>
@@ -2561,12 +2496,12 @@ Already installed containers were found on the server. All installed containers
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="175"/> <location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="175"/>
<source>Client logs</source> <source>Client logs</source>
<translation>Логи приложения</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="176"/> <location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="176"/>
<source>AmneziaVPN logs</source> <source>AmneziaVPN logs</source>
<translation>AmneziaVPN logs</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="142"/> <location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="142"/>
@@ -2581,12 +2516,12 @@ Already installed containers were found on the server. All installed containers
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="204"/> <location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="204"/>
<source>Service logs</source> <source>Service logs</source>
<translation>Логи службы</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="205"/> <location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="205"/>
<source>AmneziaVPN-service logs</source> <source>AmneziaVPN-service logs</source>
<translation>AmneziaVPN-service logs</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="78"/> <location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="78"/>
@@ -3071,7 +3006,7 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<message> <message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="109"/> <location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="109"/>
<source>Support tag</source> <source>Support tag</source>
<translation>Support tag</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="120"/> <location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="120"/>
@@ -3659,7 +3594,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="726"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="726"/>
<source>Allowed IPs: %1</source> <source>Allowed IPs: %1</source>
<translation>Разрешенные подсети: %1</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<source>Creation date: </source> <source>Creation date: </source>
@@ -4111,58 +4046,38 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<source>Server error: Package manager error</source> <source>Server error: Package manager error</source>
<translation>Ошибка сервера: Ошибка менеджера пакетов</translation> <translation>Ошибка сервера: Ошибка менеджера пакетов</translation>
</message> </message>
<message>
<location filename="../core/errorstrings.cpp" line="25"/>
<source>The sudo package is not pre-installed on the server</source>
<translation>Пакет sudo не установлен на сервере по умолчанию</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="26"/>
<source>The server user&apos;s home directory is not accessible</source>
<translation>Домашний каталог пользователя сервера недоступен</translation>
</message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="27"/> <location filename="../core/errorstrings.cpp" line="27"/>
<source>Action not allowed in sudoers</source>
<translation>Действие не разрешено в sudoers</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="28"/>
<source>The user&apos;s password is required</source>
<translation>Требуется пароль пользователя</translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="31"/>
<source>SSH request was denied</source> <source>SSH request was denied</source>
<translation>SSH-запрос был отклонён</translation> <translation>SSH-запрос был отклонён</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="32"/> <location filename="../core/errorstrings.cpp" line="28"/>
<source>SSH request was interrupted</source> <source>SSH request was interrupted</source>
<translation>SSH-запрос был прерван</translation> <translation>SSH-запрос был прерван</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="33"/> <location filename="../core/errorstrings.cpp" line="29"/>
<source>SSH internal error</source> <source>SSH internal error</source>
<translation>Внутренняя ошибка SSH</translation> <translation>Внутренняя ошибка SSH</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="34"/> <location filename="../core/errorstrings.cpp" line="30"/>
<source>Invalid private key or invalid passphrase entered</source> <source>Invalid private key or invalid passphrase entered</source>
<translation>Введен неверный закрытый ключ или неверная парольная фраза</translation> <translation>Введен неверный закрытый ключ или неверная парольная фраза</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="35"/> <location filename="../core/errorstrings.cpp" line="31"/>
<source>The selected private key format is not supported, use openssh ED25519 key types or PEM key types</source> <source>The selected private key format is not supported, use openssh ED25519 key types or PEM key types</source>
<translation>Выбранный формат закрытого ключа не поддерживается, используйте типы ключей openssh ED25519 или PEM</translation> <translation>Выбранный формат закрытого ключа не поддерживается, используйте типы ключей openssh ED25519 или PEM</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="36"/> <location filename="../core/errorstrings.cpp" line="32"/>
<source>Timeout connecting to server</source> <source>Timeout connecting to server</source>
<translation>Тайм-аут подключения к серверу</translation> <translation>Тайм-аут подключения к серверу</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="39"/> <location filename="../core/errorstrings.cpp" line="35"/>
<source>SCP error: Generic failure</source> <source>SCP error: Generic failure</source>
<translation>Ошибка SCP: общий сбой</translation> <translation>Ошибка SCP: общий сбой</translation>
</message> </message>
@@ -4219,23 +4134,23 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation type="vanished">Sftp error: No media was in remote drive</translation> <translation type="vanished">Sftp error: No media was in remote drive</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="57"/> <location filename="../core/errorstrings.cpp" line="53"/>
<source>The config does not contain any containers and credentials for connecting to the server</source> <source>The config does not contain any containers and credentials for connecting to the server</source>
<translation>Конфигурация не содержит каких-либо контейнеров и учетных данных для подключения к серверу</translation> <translation>Конфигурация не содержит каких-либо контейнеров и учетных данных для подключения к серверу</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="65"/> <location filename="../core/errorstrings.cpp" line="61"/>
<location filename="../core/errorstrings.cpp" line="74"/> <location filename="../core/errorstrings.cpp" line="70"/>
<source>Error when retrieving configuration from API</source> <source>Error when retrieving configuration from API</source>
<translation>Ошибка при получении конфигурации из API</translation> <translation>Ошибка при получении конфигурации из API</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="66"/> <location filename="../core/errorstrings.cpp" line="62"/>
<source>This config has already been added to the application</source> <source>This config has already been added to the application</source>
<translation>Данная конфигурация уже была добавлена в приложение</translation> <translation>Данная конфигурация уже была добавлена в приложение</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="89"/> <location filename="../core/errorstrings.cpp" line="85"/>
<source>ErrorCode: %1. </source> <source>ErrorCode: %1. </source>
<translation>Код ошибки: %1. </translation> <translation>Код ошибки: %1. </translation>
</message> </message>
@@ -4244,139 +4159,139 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation type="vanished">Failed to save config to disk</translation> <translation type="vanished">Failed to save config to disk</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="42"/> <location filename="../core/errorstrings.cpp" line="38"/>
<source>OpenVPN config missing</source> <source>OpenVPN config missing</source>
<translation>Отсутствует конфигурация OpenVPN</translation> <translation>Отсутствует конфигурация OpenVPN</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="43"/> <location filename="../core/errorstrings.cpp" line="39"/>
<source>OpenVPN management server error</source> <source>OpenVPN management server error</source>
<translation>Серверная ошибка управлением OpenVPN</translation> <translation>Серверная ошибка управлением OpenVPN</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="46"/> <location filename="../core/errorstrings.cpp" line="42"/>
<source>OpenVPN executable missing</source> <source>OpenVPN executable missing</source>
<translation>Отсутствует исполняемый файл OpenVPN</translation> <translation>Отсутствует исполняемый файл OpenVPN</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="47"/> <location filename="../core/errorstrings.cpp" line="43"/>
<source>Shadowsocks (ss-local) executable missing</source> <source>Shadowsocks (ss-local) executable missing</source>
<translation>Отсутствует исполняемый файл Shadowsocks (ss-local)</translation> <translation>Отсутствует исполняемый файл Shadowsocks (ss-local)</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="48"/> <location filename="../core/errorstrings.cpp" line="44"/>
<source>Cloak (ck-client) executable missing</source> <source>Cloak (ck-client) executable missing</source>
<translation>Отсутствует исполняемый файл Cloak (ck-client)</translation> <translation>Отсутствует исполняемый файл Cloak (ck-client)</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="49"/> <location filename="../core/errorstrings.cpp" line="45"/>
<source>Amnezia helper service error</source> <source>Amnezia helper service error</source>
<translation>Ошибка вспомогательной службы Amnezia</translation> <translation>Ошибка вспомогательной службы Amnezia</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="50"/> <location filename="../core/errorstrings.cpp" line="46"/>
<source>OpenSSL failed</source> <source>OpenSSL failed</source>
<translation>Ошибка OpenSSL</translation> <translation>Ошибка OpenSSL</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="53"/> <location filename="../core/errorstrings.cpp" line="49"/>
<source>Can&apos;t connect: another VPN connection is active</source> <source>Can&apos;t connect: another VPN connection is active</source>
<translation>Невозможно подключиться: активно другое VPN-соединение</translation> <translation>Невозможно подключиться: активно другое VPN-соединение</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="54"/> <location filename="../core/errorstrings.cpp" line="50"/>
<source>Can&apos;t setup OpenVPN TAP network adapter</source> <source>Can&apos;t setup OpenVPN TAP network adapter</source>
<translation>Невозможно настроить сетевой адаптер OpenVPN TAP</translation> <translation>Невозможно настроить сетевой адаптер OpenVPN TAP</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="55"/> <location filename="../core/errorstrings.cpp" line="51"/>
<source>VPN pool error: no available addresses</source> <source>VPN pool error: no available addresses</source>
<translation>Ошибка пула VPN: нет доступных адресов</translation> <translation>Ошибка пула VPN: нет доступных адресов</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="58"/> <location filename="../core/errorstrings.cpp" line="54"/>
<source>Unable to open config file</source> <source>Unable to open config file</source>
<translation>Не удалось открыть файл конфигурации</translation> <translation>Не удалось открыть файл конфигурации</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="59"/> <location filename="../core/errorstrings.cpp" line="55"/>
<source>VPN Protocols is not installed. <source>VPN Protocols is not installed.
Please install VPN container at first</source> Please install VPN container at first</source>
<translation>VPN-протоколы не установлены. <translation>VPN-протоколы не установлены.
Пожалуйста, установите протокол</translation> Пожалуйста, установите протокол</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="62"/> <location filename="../core/errorstrings.cpp" line="58"/>
<source>VPN connection error</source> <source>VPN connection error</source>
<translation>Ошибка VPN-соединения</translation> <translation>Ошибка VPN-соединения</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="67"/> <location filename="../core/errorstrings.cpp" line="63"/>
<source>In the response from the server, an empty config was received</source> <source>In the response from the server, an empty config was received</source>
<translation>В ответе от сервера была получена пустая конфигурация</translation> <translation>В ответе от сервера была получена пустая конфигурация</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="68"/> <location filename="../core/errorstrings.cpp" line="64"/>
<source>SSL error occurred</source> <source>SSL error occurred</source>
<translation>Произошла ошибка SSL</translation> <translation>Произошла ошибка SSL</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="69"/> <location filename="../core/errorstrings.cpp" line="65"/>
<source>Server response timeout on api request</source> <source>Server response timeout on api request</source>
<translation>Тайм-аут ответа сервера на запрос API</translation> <translation>Тайм-аут ответа сервера на запрос API</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="70"/> <location filename="../core/errorstrings.cpp" line="66"/>
<source>Missing AGW public key</source> <source>Missing AGW public key</source>
<translation>Отсутствует публичный ключ AGW</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="71"/> <location filename="../core/errorstrings.cpp" line="67"/>
<source>Failed to decrypt response payload</source> <source>Failed to decrypt response payload</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="72"/> <location filename="../core/errorstrings.cpp" line="68"/>
<source>Missing list of available services</source> <source>Missing list of available services</source>
<translation>Отсутствует список доступных сервисов</translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="73"/> <location filename="../core/errorstrings.cpp" line="69"/>
<source>The limit of allowed configurations per subscription has been exceeded</source> <source>The limit of allowed configurations per subscription has been exceeded</source>
<translation>Превышен лимит разрешенных конфигураций для одной подписки</translation> <translation>Превышен лимит разрешенных конфигураций для одной подписки</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="77"/> <location filename="../core/errorstrings.cpp" line="73"/>
<source>QFile error: The file could not be opened</source> <source>QFile error: The file could not be opened</source>
<translation>Ошибка QFile: не удалось открыть файл</translation> <translation>Ошибка QFile: не удалось открыть файл</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="78"/> <location filename="../core/errorstrings.cpp" line="74"/>
<source>QFile error: An error occurred when reading from the file</source> <source>QFile error: An error occurred when reading from the file</source>
<translation>Ошибка QFile: произошла ошибка при чтении из файла</translation> <translation>Ошибка QFile: произошла ошибка при чтении из файла</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="79"/> <location filename="../core/errorstrings.cpp" line="75"/>
<source>QFile error: The file could not be accessed</source> <source>QFile error: The file could not be accessed</source>
<translation>Ошибка QFile: не удалось получить доступ к файлу</translation> <translation>Ошибка QFile: не удалось получить доступ к файлу</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="80"/> <location filename="../core/errorstrings.cpp" line="76"/>
<source>QFile error: An unspecified error occurred</source> <source>QFile error: An unspecified error occurred</source>
<translation>Ошибка QFile: произошла неизвестная ошибка</translation> <translation>Ошибка QFile: произошла неизвестная ошибка</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="81"/> <location filename="../core/errorstrings.cpp" line="77"/>
<source>QFile error: A fatal error occurred</source> <source>QFile error: A fatal error occurred</source>
<translation>Ошибка QFile: произошла фатальная ошибка</translation> <translation>Ошибка QFile: произошла фатальная ошибка</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="82"/> <location filename="../core/errorstrings.cpp" line="78"/>
<source>QFile error: The operation was aborted</source> <source>QFile error: The operation was aborted</source>
<translation>Ошибка QFile: операция была прервана</translation> <translation>Ошибка QFile: операция была прервана</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="86"/> <location filename="../core/errorstrings.cpp" line="82"/>
<source>Internal error</source> <source>Internal error</source>
<translation>Внутренняя ошибка</translation> <translation>Внутренняя ошибка</translation>
</message> </message>
@@ -5138,37 +5053,37 @@ This means that AmneziaWG keeps the fast performance of the original while addin
<translation>Имя хоста не похоже на IP-адрес или доменное имя</translation> <translation>Имя хоста не похоже на IP-адрес или доменное имя</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/sitesController.cpp" line="66"/> <location filename="../ui/controllers/sitesController.cpp" line="67"/>
<source>New site added: %1</source> <source>New site added: %1</source>
<translation>Добавлен новый сайт: %1</translation> <translation>Добавлен новый сайт: %1</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/sitesController.cpp" line="78"/> <location filename="../ui/controllers/sitesController.cpp" line="80"/>
<source>Site removed: %1</source> <source>Site removed: %1</source>
<translation>Сайт удален: %1</translation> <translation>Сайт удален: %1</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/sitesController.cpp" line="85"/> <location filename="../ui/controllers/sitesController.cpp" line="87"/>
<source>Can&apos;t open file: %1</source> <source>Can&apos;t open file: %1</source>
<translation>Невозможно открыть файл: %1</translation> <translation>Невозможно открыть файл: %1</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/sitesController.cpp" line="91"/> <location filename="../ui/controllers/sitesController.cpp" line="93"/>
<source>Failed to parse JSON data from file: %1</source> <source>Failed to parse JSON data from file: %1</source>
<translation>Не удалось разобрать JSON-данные из файла: %1</translation> <translation>Не удалось разобрать JSON-данные из файла: %1</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/sitesController.cpp" line="96"/> <location filename="../ui/controllers/sitesController.cpp" line="98"/>
<source>The JSON data is not an array in file: %1</source> <source>The JSON data is not an array in file: %1</source>
<translation>JSON-данные не являются массивом в файле: %1</translation> <translation>JSON-данные не являются массивом в файле: %1</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/sitesController.cpp" line="126"/> <location filename="../ui/controllers/sitesController.cpp" line="129"/>
<source>Import completed</source> <source>Import completed</source>
<translation>Импорт завершен</translation> <translation>Импорт завершен</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/sitesController.cpp" line="145"/> <location filename="../ui/controllers/sitesController.cpp" line="148"/>
<source>Export completed</source> <source>Export completed</source>
<translation>Экспорт завершен</translation> <translation>Экспорт завершен</translation>
</message> </message>
@@ -5217,7 +5132,7 @@ This means that AmneziaWG keeps the fast performance of the original while addin
<context> <context>
<name>VpnConnection</name> <name>VpnConnection</name>
<message> <message>
<location filename="../vpnconnection.cpp" line="421"/> <location filename="../vpnconnection.cpp" line="415"/>
<source>Mbps</source> <source>Mbps</source>
<translation>Мбит/с</translation> <translation>Мбит/с</translation>
</message> </message>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -145,7 +145,7 @@ void ExportController::generateOpenVpnConfig(const QString &clientName)
} }
QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n"); QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n");
for (const QString &line : std::as_const(lines)) { for (const QString &line : lines) {
m_config.append(line + "\n"); m_config.append(line + "\n");
} }
@@ -163,7 +163,7 @@ void ExportController::generateWireGuardConfig(const QString &clientName)
} }
QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n"); QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n");
for (const QString &line : std::as_const(lines)) { for (const QString &line : lines) {
m_config.append(line + "\n"); m_config.append(line + "\n");
} }
@@ -183,7 +183,7 @@ void ExportController::generateAwgConfig(const QString &clientName)
} }
QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n"); QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n");
for (const QString &line : std::as_const(lines)) { for (const QString &line : lines) {
m_config.append(line + "\n"); m_config.append(line + "\n");
} }
@@ -211,7 +211,7 @@ void ExportController::generateShadowSocksConfig()
} }
QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n"); QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n");
for (const QString &line : std::as_const(lines)) { for (const QString &line : lines) {
m_config.append(line + "\n"); m_config.append(line + "\n");
} }
@@ -240,7 +240,7 @@ void ExportController::generateCloakConfig()
nativeConfig.insert("ProxyMethod", "shadowsocks"); nativeConfig.insert("ProxyMethod", "shadowsocks");
QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n"); QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n");
for (const QString &line : std::as_const(lines)) { for (const QString &line : lines) {
m_config.append(line + "\n"); m_config.append(line + "\n");
} }
@@ -257,7 +257,7 @@ void ExportController::generateXrayConfig(const QString &clientName)
} }
QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n"); QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n");
for (const QString &line : std::as_const(lines)) { for (const QString &line : lines) {
m_config.append(line + "\n"); m_config.append(line + "\n");
} }
@@ -20,7 +20,6 @@ bool XrayConfigModel::setData(const QModelIndex &index, const QVariant &value, i
switch (role) { switch (role) {
case Roles::SiteRole: m_protocolConfig.insert(config_key::site, value.toString()); break; case Roles::SiteRole: m_protocolConfig.insert(config_key::site, value.toString()); break;
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
} }
emit dataChanged(index, index, QList { role }); emit dataChanged(index, index, QList { role });
@@ -35,7 +34,6 @@ QVariant XrayConfigModel::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case Roles::SiteRole: return m_protocolConfig.value(config_key::site).toString(protocols::xray::defaultSite); case Roles::SiteRole: return m_protocolConfig.value(config_key::site).toString(protocols::xray::defaultSite);
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::xray::defaultPort);
} }
return QVariant(); return QVariant();
@@ -69,7 +67,6 @@ QHash<int, QByteArray> XrayConfigModel::roleNames() const
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[SiteRole] = "site"; roles[SiteRole] = "site";
roles[PortRole] = "port";
return roles; return roles;
} }
+1 -2
View File
@@ -12,8 +12,7 @@ class XrayConfigModel : public QAbstractListModel
public: public:
enum Roles { enum Roles {
SiteRole, SiteRole
PortRole
}; };
explicit XrayConfigModel(QObject *parent = nullptr); explicit XrayConfigModel(QObject *parent = nullptr);
@@ -103,29 +103,8 @@ PageType {
} }
} }
TextFieldWithHeaderType {
id: portTextField
Layout.fillWidth: true
Layout.topMargin: 16
enabled: delegateItem.isEnabled
headerText: qsTr("Port")
textField.text: port
textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 }
textField.onEditingFinished: {
if (textField.text !== port) {
port = textField.text
}
}
checkEmptyText: true
}
BasicButtonType { BasicButtonType {
id: saveButton id: basicButton
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 24 Layout.topMargin: 24
Layout.bottomMargin: 24 Layout.bottomMargin: 24
@@ -3,8 +3,6 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Dialogs import QtQuick.Dialogs
import QtCore
import PageEnum 1.0 import PageEnum 1.0
import Style 1.0 import Style 1.0
@@ -103,34 +101,6 @@ PageType {
} }
} }
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Export client logs")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
visible: PageController.isStartPageVisible()
clickedFunction: function() {
var fileName = ""
if (GC.isMobile()) {
fileName = "AmneziaVPN.log"
} else {
fileName = SystemController.getFileName(qsTr("Save"),
qsTr("Logs files (*.log)"),
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN",
true,
".log")
}
if (fileName !== "") {
PageController.showBusyIndicator(true)
SettingsController.exportLogsFile(fileName)
PageController.showBusyIndicator(false)
PageController.showNotificationMessage(qsTr("Logs file saved"))
}
}
}
LabelWithButtonType { LabelWithButtonType {
id: supportUuid id: supportUuid
Layout.fillWidth: true Layout.fillWidth: true
+2 -8
View File
@@ -351,10 +351,8 @@ void VpnConnection::appendSplitTunnelingConfig()
sitesJsonArray.append(site); sitesJsonArray.append(site);
} }
if (sitesJsonArray.isEmpty()) { // Allow traffic to Amnezia DNS
sitesRouteMode = Settings::RouteMode::VpnAllSites; if (sitesRouteMode == Settings::VpnOnlyForwardSites) {
} else if (sitesRouteMode == Settings::VpnOnlyForwardSites) {
// Allow traffic to Amnezia DNS
sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns1).toString()); sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns1).toString());
sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns2).toString()); sitesJsonArray.append(m_vpnConfiguration.value(config_key::dns2).toString());
} }
@@ -373,10 +371,6 @@ void VpnConnection::appendSplitTunnelingConfig()
for (const auto &app : apps) { for (const auto &app : apps) {
appsJsonArray.append(app.appPath.isEmpty() ? app.packageName : app.appPath); appsJsonArray.append(app.appPath.isEmpty() ? app.packageName : app.appPath);
} }
if (appsJsonArray.isEmpty()) {
appsRouteMode = Settings::AppsRouteMode::VpnAllApps;
}
} }
m_vpnConfiguration.insert(config_key::appSplitTunnelType, appsRouteMode); m_vpnConfiguration.insert(config_key::appSplitTunnelType, appsRouteMode);
+7 -27
View File
@@ -2,33 +2,13 @@
APP_NAME=AmneziaVPN APP_NAME=AmneziaVPN
PLIST_NAME=$APP_NAME.plist PLIST_NAME=$APP_NAME.plist
LAUNCH_DAEMONS_PLIST_NAME="/Library/LaunchDaemons/$PLIST_NAME" LAUNCH_DAEMONS_PLIST_NAME=/Library/LaunchDaemons/$PLIST_NAME
APP_PATH="/Applications/$APP_NAME.app"
USER_APP_SUPPORT="$HOME/Library/Application Support/$APP_NAME"
SYSTEM_APP_SUPPORT="/Library/Application Support/$APP_NAME"
LOG_FOLDER="/var/log/$APP_NAME"
CACHES_FOLDER="$HOME/Library/Caches/$APP_NAME"
# Stop the running service if it exists if launchctl list "$APP_NAME-service" &> /dev/null; then
if pgrep -x "${APP_NAME}-service" > /dev/null; then launchctl unload $LAUNCH_DAEMONS_PLIST_NAME
sudo killall -9 "${APP_NAME}-service" rm -f $LAUNCH_DAEMONS_PLIST_NAME
fi fi
# Unload the service if loaded and remove its plist file regardless rm -rf "$HOME/Library/Application Support/$APP_NAME"
if launchctl list "${APP_NAME}-service" &> /dev/null; then rm -rf /var/log/$APP_NAME
sudo launchctl unload "$LAUNCH_DAEMONS_PLIST_NAME" rm -rf /Applications/$APP_NAME.app/Contents
fi
sudo rm -f "$LAUNCH_DAEMONS_PLIST_NAME"
# Remove the entire application bundle
sudo rm -rf "$APP_PATH"
# Remove Application Support folders (user and system, if they exist)
rm -rf "$USER_APP_SUPPORT"
sudo rm -rf "$SYSTEM_APP_SUPPORT"
# Remove the log folder
sudo rm -rf "$LOG_FOLDER"
# Remove any caches left behind
rm -rf "$CACHES_FOLDER"
-38
View File
@@ -1,38 +0,0 @@
#!/bin/sh
set -e
VERSION=$1
if [[ $VERSION = '' ]]; then
echo '::error::VERSION does not set. Exiting with error...'
exit 1
fi
mkdir -p dist
cd dist
echo $VERSION >> VERSION
curl -s https://api.github.com/repos/amnezia-vpn/amnezia-client/releases/tags/$VERSION | jq -r .body | tr -d '\r' > CHANGELOG
if [[ $(cat CHANGELOG) = null ]]; then
echo '::error::Release does not exists. Exiting with error...'
exit 1
fi
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android8+_arm64-v8a.apk
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android8+_armeabi-v7a.apk
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android8+_x86.apk
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android8+_x86_64.apk
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android_7_arm64-v8a.apk
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android_7_armeabi-v7a.apk
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android_7_x86.apk
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android_7_x86_64.apk
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_linux.tar.zip
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_macos.dmg
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_macos_old.dmg
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_x64.exe
cd ../
rclone sync ./dist/ r2:/updates/