Merge branch 'dev' into feature/killswitch

This commit is contained in:
pokamest 2024-01-19 14:58:28 +00:00
commit 3702d69b9d
47 changed files with 654 additions and 634 deletions

View file

@ -48,14 +48,18 @@ jobs:
export QIF_BIN_DIR=${{ runner.temp }}/Qt/Tools/QtInstallerFramework/${{ env.QIF_VERSION }}/bin export QIF_BIN_DIR=${{ runner.temp }}/Qt/Tools/QtInstallerFramework/${{ env.QIF_VERSION }}/bin
bash deploy/build_linux.sh bash deploy/build_linux.sh
- name: 'Pack installer'
run: cd deploy && tar -cf AmneziaVPN_Linux_Installer.tar AmneziaVPN_Linux_Installer.bin
- name: 'Upload installer artifact' - name: 'Upload installer artifact'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: AmneziaVPN_Linux_installer name: AmneziaVPN_Linux_installer.tar
path: deploy/AmneziaVPN_Linux_Installer path: deploy/AmneziaVPN_Linux_Installer.tar
retention-days: 7 retention-days: 7
- name: 'Upload unpacked artifact' - name: 'Upload unpacked artifact'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: AmneziaVPN_Linux_unpacked name: AmneziaVPN_Linux_unpacked
path: deploy/AppDir path: deploy/AppDir
@ -110,13 +114,14 @@ jobs:
call deploy\\build_windows.bat call deploy\\build_windows.bat
- name: 'Upload installer artifact' - name: 'Upload installer artifact'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: AmneziaVPN_Windows_installer name: AmneziaVPN_Windows_installer
path: AmneziaVPN_x${{ env.BUILD_ARCH }}.exe path: AmneziaVPN_x${{ env.BUILD_ARCH }}.exe
retention-days: 7 retention-days: 7
- name: 'Upload unpacked artifact' - name: 'Upload unpacked artifact'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: AmneziaVPN_Windows_unpacked name: AmneziaVPN_Windows_unpacked
path: deploy\\build_${{ env.BUILD_ARCH }}\\client\\Release path: deploy\\build_${{ env.BUILD_ARCH }}\\client\\Release
@ -200,7 +205,7 @@ jobs:
IOS_NE_PROVISIONING_PROFILE: ${{ secrets.IOS_NE_PROVISIONING_PROFILE }} IOS_NE_PROVISIONING_PROFILE: ${{ secrets.IOS_NE_PROVISIONING_PROFILE }}
# - name: 'Upload appstore .ipa and dSYMs to artifacts' # - name: 'Upload appstore .ipa and dSYMs to artifacts'
# uses: actions/upload-artifact@v3 # uses: actions/upload-artifact@v4
# with: # with:
# name: app-store ipa & dsyms # name: app-store ipa & dsyms
# path: | # path: |
@ -255,13 +260,14 @@ jobs:
bash deploy/build_macos.sh bash deploy/build_macos.sh
- name: 'Upload installer artifact' - name: 'Upload installer artifact'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: AmneziaVPN_MacOS_installer name: AmneziaVPN_MacOS_installer
path: AmneziaVPN.dmg path: AmneziaVPN.dmg
retention-days: 7 retention-days: 7
- name: 'Upload unpacked artifact' - name: 'Upload unpacked artifact'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: AmneziaVPN_MacOS_unpacked name: AmneziaVPN_MacOS_unpacked
path: deploy/build/client/AmneziaVPN.app path: deploy/build/client/AmneziaVPN.app
@ -277,6 +283,7 @@ jobs:
ANDROID_BUILD_PLATFORM: android-34 ANDROID_BUILD_PLATFORM: android-34
QT_VERSION: 6.6.1 QT_VERSION: 6.6.1
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools' QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
BUILD_AAB: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') }}
steps: steps:
- name: 'Install desktop Qt' - name: 'Install desktop Qt'
@ -375,32 +382,45 @@ jobs:
ANDROID_KEYSTORE_KEY_ALIAS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_ALIAS }} ANDROID_KEYSTORE_KEY_ALIAS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_ALIAS }}
ANDROID_KEYSTORE_KEY_PASS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_PASS }} ANDROID_KEYSTORE_KEY_PASS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_PASS }}
shell: bash shell: bash
run: ./deploy/build_android.sh --apk all --build-platform ${{ env.ANDROID_BUILD_PLATFORM }} run: ./deploy/build_android.sh ${{ env.BUILD_AAB == 'true' && '--aab' || '' }} --apk all --build-platform ${{ env.ANDROID_BUILD_PLATFORM }}
- name: 'Upload x86_64 apk' - name: 'Upload x86_64 apk'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: AmneziaVPN-android-x86_64 name: AmneziaVPN-android-x86_64
path: deploy/build/AmneziaVPN-x86_64-release.apk path: deploy/build/AmneziaVPN-x86_64-release.apk
compression-level: 0
retention-days: 7 retention-days: 7
- name: 'Upload x86 apk' - name: 'Upload x86 apk'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: AmneziaVPN-android-x86 name: AmneziaVPN-android-x86
path: deploy/build/AmneziaVPN-x86-release.apk path: deploy/build/AmneziaVPN-x86-release.apk
compression-level: 0
retention-days: 7 retention-days: 7
- name: 'Upload arm64-v8a apk' - name: 'Upload arm64-v8a apk'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: AmneziaVPN-android-arm64-v8a name: AmneziaVPN-android-arm64-v8a
path: deploy/build/AmneziaVPN-arm64-v8a-release.apk path: deploy/build/AmneziaVPN-arm64-v8a-release.apk
compression-level: 0
retention-days: 7 retention-days: 7
- name: 'Upload armeabi-v7a apk' - name: 'Upload armeabi-v7a apk'
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: AmneziaVPN-android-armeabi-v7a name: AmneziaVPN-android-armeabi-v7a
path: deploy/build/AmneziaVPN-armeabi-v7a-release.apk path: deploy/build/AmneziaVPN-armeabi-v7a-release.apk
compression-level: 0
retention-days: 7
- name: 'Upload aab'
if: ${{ env.BUILD_AAB == 'true' }}
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN-android
path: deploy/build/AmneziaVPN-release.aab
compression-level: 0
retention-days: 7 retention-days: 7

6
.gitmodules vendored
View file

@ -22,6 +22,6 @@
[submodule "client/3rd-prebuilt"] [submodule "client/3rd-prebuilt"]
path = client/3rd-prebuilt path = client/3rd-prebuilt
url = https://github.com/amnezia-vpn/3rd-prebuilt url = https://github.com/amnezia-vpn/3rd-prebuilt
[submodule "client/3rd/awg-apple"] [submodule "client/3rd/amneziawg-apple"]
path = client/3rd/awg-apple path = client/3rd/amneziawg-apple
url = https://github.com/amnezia-vpn/awg-apple url = https://github.com/amnezia-vpn/amneziawg-apple

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.1.0.1 project(${PROJECT} VERSION 4.2.0.1
DESCRIPTION "AmneziaVPN" DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/" HOMEPAGE_URL "https://amnezia.org/"
) )

View file

@ -36,7 +36,7 @@ AmneziaVPN uses a number of open source projects to work:
Make sure to pull all submodules after checking out the repo. Make sure to pull all submodules after checking out the repo.
```bash ```bash
git submodule update --init git submodule update --init --recursive
``` ```
## Development ## Development
@ -50,7 +50,15 @@ Look deploy folder for build scripts.
1. First, make sure you have [XCode](https://developer.apple.com/xcode/) installed, at least version 14 or higher. 1. First, make sure you have [XCode](https://developer.apple.com/xcode/) installed, at least version 14 or higher.
2. We use QT to generate the XCode project. we need QT version 6.4. Install QT for macos in [here](https://doc.qt.io/qt-6/macos.html) 2. We use QT to generate the XCode project. we need QT version 6.6.1. Install QT for macos in [here](https://doc.qt.io/qt-6/macos.html) or [QT Online Installer](https://www.qt.io/download-open-source). Required modules:
- macOS
- iOS
- Qt 5 Compatibility Module
- Qt Shader Tools
- Additional Libraries:
- Qt Image Formats
- Qt Multimedia
- Qt Remote Objects
3. Install cmake is require. We recommend cmake version 3.25. You can install cmake in [here](https://cmake.org/download/) 3. Install cmake is require. We recommend cmake version 3.25. You can install cmake in [here](https://cmake.org/download/)
@ -66,10 +74,11 @@ gomobile init
5. Build project 5. Build project
```bash ```bash
export QT_BIN_DIR="<PATH-TO-QT-FOLDER>/Qt/<QT-VERSION>/ios/bin" export QT_BIN_DIR="<PATH-TO-QT-FOLDER>/Qt/<QT-VERSION>/ios/bin"
export QT_MACOS_ROOT_DIR="<PATH-TO-QT-FOLDER>/Qt/<QT-VERSION>/macos"
export QT_IOS_BIN=$QT_BIN_DIR export QT_IOS_BIN=$QT_BIN_DIR
export PATH=$PATH:~/go/bin export PATH=$PATH:~/go/bin
mkdir build-ios mkdir build-ios
$QT_IOS_BIN/qt-cmake . -B build-ios -GXcode -DQT_HOST_PATH=$QT_BIN_DIR $QT_IOS_BIN/qt-cmake . -B build-ios -GXcode -DQT_HOST_PATH=$QT_MACOS_ROOT_DIR
``` ```
Replace PATH-TO-QT-FOLDER and QT-VERSION to your environment Replace PATH-TO-QT-FOLDER and QT-VERSION to your environment

@ -1 +1 @@
Subproject commit fcf3022a2724402f68cc11bcbed9b43ea9ffcc07 Subproject commit e568e7d0e8defe8fe009c0127323f2c55fd9be76

1
client/3rd/amneziawg-apple vendored Submodule

@ -0,0 +1 @@
Subproject commit f23eee4700ed4a2ef44a800d2c20466c9ab0222b

@ -1 +0,0 @@
Subproject commit 233eda6760962efddc860f177a0ce2bcdf533d85

@ -1 +1 @@
Subproject commit 8bbaa6d8302cf0747d9786ace4dd13c7fb746502 Subproject commit 74776e2a3e2d98d19943e0968901c5b5e04cc1bd

View file

@ -168,16 +168,19 @@ void AmneziaApplication::init()
} }
#endif #endif
// Android TextField clipboard workaround // Android TextArea clipboard workaround
// https://bugreports.qt.io/browse/QTBUG-113461 // Text from TextArea always has "text/html" mime-type:
// /qt/6.6.1/Src/qtdeclarative/src/quick/items/qquicktextcontrol.cpp:1865
// Next, html is created for this mime-type:
// /qt/6.6.1/Src/qtdeclarative/src/quick/items/qquicktextcontrol.cpp:1885
// And this html goes to the Androids clipboard, i.e. text from TextArea is always copied as richText:
// /qt/6.6.1/Src/qtbase/src/plugins/platforms/android/androidjniclipboard.cpp:46
// So we catch all the copies to the clipboard and clear them from "text/html"
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
QObject::connect(qApp, &QGuiApplication::applicationStateChanged, [](Qt::ApplicationState state) { connect(QGuiApplication::clipboard(), &QClipboard::dataChanged, []() {
if (state == Qt::ApplicationActive) { auto clipboard = QGuiApplication::clipboard();
if (qApp->clipboard()->mimeData()->formats().contains("text/html")) { if (clipboard->mimeData()->hasHtml()) {
QTextDocument doc; clipboard->setText(clipboard->text());
doc.setHtml(qApp->clipboard()->mimeData()->html());
qApp->clipboard()->setText(doc.toPlainText());
}
} }
}); });
#endif #endif

View file

@ -22,7 +22,6 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- Enable when VPN-per-app mode will be implemented --> <!-- Enable when VPN-per-app mode will be implemented -->
<!-- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> --> <!-- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> -->
@ -39,6 +38,7 @@
android:configChanges="uiMode|screenSize|smallestScreenSize|screenLayout|orientation|density android:configChanges="uiMode|screenSize|smallestScreenSize|screenLayout|orientation|density
|fontScale|layoutDirection|locale|keyboard|keyboardHidden|navigation|mcc|mnc" |fontScale|layoutDirection|locale|keyboard|keyboardHidden|navigation|mcc|mnc"
android:launchMode="singleInstance" android:launchMode="singleInstance"
android:windowSoftInputMode="adjustResize"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>

View file

@ -2,6 +2,7 @@ package org.amnezia.vpn
import android.content.ComponentName import android.content.ComponentName
import android.content.Intent import android.content.Intent
import android.content.Intent.EXTRA_MIME_TYPES
import android.content.Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY import android.content.Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
import android.content.ServiceConnection import android.content.ServiceConnection
import android.net.Uri import android.net.Uri
@ -12,11 +13,13 @@ import android.os.IBinder
import android.os.Looper import android.os.Looper
import android.os.Message import android.os.Message
import android.os.Messenger import android.os.Messenger
import android.webkit.MimeTypeMap
import android.widget.Toast import android.widget.Toast
import androidx.annotation.MainThread import androidx.annotation.MainThread
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import java.io.IOException import java.io.IOException
import kotlin.LazyThreadSafetyMode.NONE import kotlin.LazyThreadSafetyMode.NONE
import kotlin.text.RegexOption.IGNORE_CASE
import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -35,6 +38,7 @@ private const val TAG = "AmneziaActivity"
private const val CHECK_VPN_PERMISSION_ACTION_CODE = 1 private const val CHECK_VPN_PERMISSION_ACTION_CODE = 1
private const val CREATE_FILE_ACTION_CODE = 2 private const val CREATE_FILE_ACTION_CODE = 2
private const val OPEN_FILE_ACTION_CODE = 3
private const val BIND_SERVICE_TIMEOUT = 1000L private const val BIND_SERVICE_TIMEOUT = 1000L
class AmneziaActivity : QtActivity() { class AmneziaActivity : QtActivity() {
@ -201,6 +205,15 @@ class AmneziaActivity : QtActivity() {
} }
} }
OPEN_FILE_ACTION_CODE -> {
when (resultCode) {
RESULT_OK -> data?.data?.toString() ?: ""
else -> ""
}.let { uri ->
QtAndroidController.onFileOpened(uri)
}
}
CHECK_VPN_PERMISSION_ACTION_CODE -> { CHECK_VPN_PERMISSION_ACTION_CODE -> {
when (resultCode) { when (resultCode) {
RESULT_OK -> { RESULT_OK -> {
@ -370,6 +383,36 @@ class AmneziaActivity : QtActivity() {
} }
} }
@Suppress("unused")
fun openFile(filter: String?) {
Log.v(TAG, "Open file with filter: $filter")
val mimeTypes = if (!filter.isNullOrEmpty()) {
val extensionRegex = "\\*\\.[a-z .]+".toRegex(IGNORE_CASE)
val mime = MimeTypeMap.getSingleton()
extensionRegex.findAll(filter).map {
mime.getMimeTypeFromExtension(it.value.drop(2))
}.filterNotNull().toSet()
} else emptySet()
Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
Log.d(TAG, "File mimyType filter: $mimeTypes")
when (mimeTypes.size) {
1 -> type = mimeTypes.first()
in 2..Int.MAX_VALUE -> {
type = "*/*"
putExtra(EXTRA_MIME_TYPES, mimeTypes.toTypedArray())
}
else -> type = "*/*"
}
}.also {
startActivityForResult(it, OPEN_FILE_ACTION_CODE)
}
}
@Suppress("unused") @Suppress("unused")
fun setNotificationText(title: String, message: String, timerSec: Int) { fun setNotificationText(title: String, message: String, timerSec: Int) {
Log.v(TAG, "Set notification text") Log.v(TAG, "Set notification text")

View file

@ -15,6 +15,8 @@ object QtAndroidController {
external fun onVpnReconnecting() external fun onVpnReconnecting()
external fun onStatisticsUpdate(rxBytes: Long, txBytes: Long) external fun onStatisticsUpdate(rxBytes: Long, txBytes: Long)
external fun onFileOpened(uri: String)
external fun onConfigImported(data: String) external fun onConfigImported(data: String)
external fun decodeQrCode(data: String): Boolean external fun decodeQrCode(data: String): Boolean

View file

@ -90,7 +90,7 @@ include_directories(
${LIBSSH_ROOT_DIR}/include ${LIBSSH_ROOT_DIR}/include
${CLIENT_ROOT_DIR}/3rd/libssh/include ${CLIENT_ROOT_DIR}/3rd/libssh/include
${CLIENT_ROOT_DIR}/3rd/QSimpleCrypto/include ${CLIENT_ROOT_DIR}/3rd/QSimpleCrypto/include
${CLIENT_ROOT_DIR}/3rd/qtkeychain ${CLIENT_ROOT_DIR}/3rd/qtkeychain/qtkeychain
${CMAKE_CURRENT_BINARY_DIR}/3rd/qtkeychain ${CMAKE_CURRENT_BINARY_DIR}/3rd/qtkeychain
${CMAKE_CURRENT_BINARY_DIR}/3rd/libssh/include ${CMAKE_CURRENT_BINARY_DIR}/3rd/libssh/include
) )

View file

@ -27,7 +27,7 @@ link_directories(${CMAKE_CURRENT_SOURCE_DIR}/platforms/android)
set(HEADERS ${HEADERS} set(HEADERS ${HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_controller.h ${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_controller.h
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_notificationhandler.h ${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_notificationhandler.h
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/androidutils.h ${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_utils.h
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/authResultReceiver.h ${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/authResultReceiver.h
${CMAKE_CURRENT_SOURCE_DIR}/protocols/android_vpnprotocol.h ${CMAKE_CURRENT_SOURCE_DIR}/protocols/android_vpnprotocol.h
) )
@ -35,7 +35,7 @@ set(HEADERS ${HEADERS}
set(SOURCES ${SOURCES} set(SOURCES ${SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_controller.cpp ${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_controller.cpp
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_notificationhandler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_notificationhandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/androidutils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/authResultReceiver.cpp ${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/authResultReceiver.cpp
${CMAKE_CURRENT_SOURCE_DIR}/protocols/android_vpnprotocol.cpp ${CMAKE_CURRENT_SOURCE_DIR}/protocols/android_vpnprotocol.cpp
) )

View file

@ -97,7 +97,7 @@ target_compile_options(${PROJECT} PRIVATE
-DVPN_NE_BUNDLEID=\"${BUILD_IOS_APP_IDENTIFIER}.network-extension\" -DVPN_NE_BUNDLEID=\"${BUILD_IOS_APP_IDENTIFIER}.network-extension\"
) )
set(WG_APPLE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/awg-apple/Sources) set(WG_APPLE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/amneziawg-apple/Sources)
target_sources(${PROJECT} PRIVATE target_sources(${PROJECT} PRIVATE
# ${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/iosvpnprotocol.swift # ${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/iosvpnprotocol.swift

View file

@ -118,31 +118,33 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia
return QJsonDocument(jConfig).toJson(); return QJsonDocument(jConfig).toJson();
} }
QString OpenVpnConfigurator::processConfigWithLocalSettings(QString jsonConfig) QString OpenVpnConfigurator::processConfigWithLocalSettings(QString jsonConfig, const int serverIndex)
{ {
QJsonObject json = QJsonDocument::fromJson(jsonConfig.toUtf8()).object(); QJsonObject json = QJsonDocument::fromJson(jsonConfig.toUtf8()).object();
QString config = json[config_key::config].toString(); QString config = json[config_key::config].toString();
QRegularExpression regex("redirect-gateway.*"); if (!m_settings->server(serverIndex).value(config_key::configVersion).toInt()) {
config.replace(regex, ""); QRegularExpression regex("redirect-gateway.*");
config.replace(regex, "");
if (m_settings->routeMode() == Settings::VpnAllSites) { if (m_settings->routeMode() == Settings::VpnAllSites) {
config.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n"); config.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
// Prevent ipv6 leak // Prevent ipv6 leak
config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n"); config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n");
config.append("block-ipv6\n"); config.append("block-ipv6\n");
} }
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) { if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
// no redirect-gateway // no redirect-gateway
} }
if (m_settings->routeMode() == Settings::VpnAllExceptSites) { if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
#ifndef Q_OS_ANDROID #ifndef Q_OS_ANDROID
config.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n"); config.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n");
#endif #endif
// Prevent ipv6 leak // Prevent ipv6 leak
config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n"); config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n");
config.append("block-ipv6\n"); config.append("block-ipv6\n");
}
} }
#ifndef MZ_WINDOWS #ifndef MZ_WINDOWS

View file

@ -26,7 +26,7 @@ public:
QString genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, QString genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode = nullptr); const QJsonObject &containerConfig, QString &clientId, ErrorCode *errorCode = nullptr);
QString processConfigWithLocalSettings(QString jsonConfig); QString processConfigWithLocalSettings(QString jsonConfig, const int serverIndex);
QString processConfigWithExportSettings(QString jsonConfig); QString processConfigWithExportSettings(QString jsonConfig);
ErrorCode signCert(DockerContainer container, ErrorCode signCert(DockerContainer container,

View file

@ -92,7 +92,7 @@ QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, Docker
processConfigWithDnsSettings(serverIndex, container, proto, config); processConfigWithDnsSettings(serverIndex, container, proto, config);
if (proto == Proto::OpenVpn) { if (proto == Proto::OpenVpn) {
config = openVpnConfigurator->processConfigWithLocalSettings(config); config = openVpnConfigurator->processConfigWithLocalSettings(config, serverIndex);
} }
return config; return config;
} }

View file

@ -58,7 +58,7 @@ target_link_libraries(networkextension PRIVATE ${FW_UI_KIT})
target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\") target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1) target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1)
set(WG_APPLE_SOURCE_DIR ${CLIENT_ROOT_DIR}/3rd/awg-apple/Sources) set(WG_APPLE_SOURCE_DIR ${CLIENT_ROOT_DIR}/3rd/amneziawg-apple/Sources)
target_sources(networkextension PRIVATE target_sources(networkextension PRIVATE
${WG_APPLE_SOURCE_DIR}/WireGuardKit/WireGuardAdapter.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/WireGuardAdapter.swift

View file

@ -1,6 +1,6 @@
#include "wireguard-go-version.h" #include "wireguard-go-version.h"
#include "3rd/awg-apple/Sources/WireGuardKitGo/wireguard.h" #include "3rd/amneziawg-apple/Sources/WireGuardKitGo/wireguard.h"
#include "3rd/awg-apple/Sources/WireGuardKitC/WireGuardKitC.h" #include "3rd/amneziawg-apple/Sources/WireGuardKitC/WireGuardKitC.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>

View file

@ -1,8 +1,10 @@
#include <QCoreApplication>
#include <QJniEnvironment> #include <QJniEnvironment>
#include <QJsonDocument> #include <QJsonDocument>
#include <QQmlFile>
#include <QEventLoop>
#include "android_controller.h" #include "android_controller.h"
#include "android_utils.h"
#include "ui/controllers/importController.h" #include "ui/controllers/importController.h"
namespace namespace
@ -106,6 +108,7 @@ bool AndroidController::initialize()
{"onVpnDisconnected", "()V", reinterpret_cast<void *>(onVpnDisconnected)}, {"onVpnDisconnected", "()V", reinterpret_cast<void *>(onVpnDisconnected)},
{"onVpnReconnecting", "()V", reinterpret_cast<void *>(onVpnReconnecting)}, {"onVpnReconnecting", "()V", reinterpret_cast<void *>(onVpnReconnecting)},
{"onStatisticsUpdate", "(JJ)V", reinterpret_cast<void *>(onStatisticsUpdate)}, {"onStatisticsUpdate", "(JJ)V", reinterpret_cast<void *>(onStatisticsUpdate)},
{"onFileOpened", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onFileOpened)},
{"onConfigImported", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onConfigImported)}, {"onConfigImported", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onConfigImported)},
{"decodeQrCode", "(Ljava/lang/String;)Z", reinterpret_cast<bool *>(decodeQrCode)} {"decodeQrCode", "(Ljava/lang/String;)Z", reinterpret_cast<bool *>(decodeQrCode)}
}; };
@ -127,7 +130,7 @@ auto AndroidController::callActivityMethod(const char *methodName, const char *s
const std::function<Ret()> &defValue, Args &&...args) const std::function<Ret()> &defValue, Args &&...args)
{ {
qDebug() << "Call activity method:" << methodName; qDebug() << "Call activity method:" << methodName;
QJniObject activity = QNativeInterface::QAndroidApplication::context(); QJniObject activity = AndroidUtils::getActivity();
if (activity.isValid()) { if (activity.isValid()) {
return activity.callMethod<Ret>(methodName, signature, std::forward<Args>(args)...); return activity.callMethod<Ret>(methodName, signature, std::forward<Args>(args)...);
} else { } else {
@ -165,6 +168,24 @@ void AndroidController::saveFile(const QString &fileName, const QString &data)
QJniObject::fromString(data).object<jstring>()); QJniObject::fromString(data).object<jstring>());
} }
QString AndroidController::openFile(const QString &filter)
{
QEventLoop wait;
QString fileName;
connect(this, &AndroidController::fileOpened, this,
[&fileName, &wait](const QString &uri) {
qDebug() << "Android event: file opened; uri:" << uri;
fileName = QQmlFile::urlToLocalFileOrQrc(uri);
qDebug() << "Android opened filename:" << fileName;
wait.quit();
},
static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::SingleShotConnection));
callActivityMethod("openFile", "(Ljava/lang/String;)V",
QJniObject::fromString(filter).object<jstring>());
wait.exec();
return fileName;
}
void AndroidController::setNotificationText(const QString &title, const QString &message, int timerSec) void AndroidController::setNotificationText(const QString &title, const QString &message, int timerSec)
{ {
callActivityMethod("setNotificationText", "(Ljava/lang/String;Ljava/lang/String;I)V", callActivityMethod("setNotificationText", "(Ljava/lang/String;Ljava/lang/String;I)V",
@ -285,20 +306,19 @@ void AndroidController::onStatisticsUpdate(JNIEnv *env, jobject thiz, jlong rxBy
} }
// static // static
void AndroidController::onConfigImported(JNIEnv *env, jobject thiz, jstring data) void AndroidController::onFileOpened(JNIEnv *env, jobject thiz, jstring uri)
{ {
Q_UNUSED(env);
Q_UNUSED(thiz); Q_UNUSED(thiz);
const char *buffer = env->GetStringUTFChars(data, nullptr); emit AndroidController::instance()->fileOpened(AndroidUtils::convertJString(env, uri));
if (!buffer) { }
return;
}
QString config(buffer); // static
env->ReleaseStringUTFChars(data, buffer); void AndroidController::onConfigImported(JNIEnv *env, jobject thiz, jstring data)
{
Q_UNUSED(thiz);
emit AndroidController::instance()->configImported(config); emit AndroidController::instance()->configImported(AndroidUtils::convertJString(env, data));
} }
// static // static
@ -306,12 +326,5 @@ bool AndroidController::decodeQrCode(JNIEnv *env, jobject thiz, jstring data)
{ {
Q_UNUSED(thiz); Q_UNUSED(thiz);
const char *buffer = env->GetStringUTFChars(data, nullptr); return ImportController::decodeQrCode(AndroidUtils::convertJString(env, data));
if (!buffer) {
return false;
}
QString code(buffer);
env->ReleaseStringUTFChars(data, buffer);
return ImportController::decodeQrCode(code);
} }

View file

@ -18,7 +18,8 @@ public:
bool initialize(); bool initialize();
// keep synchronized with org.amnezia.vpn.protocol.ProtocolState // keep synchronized with org.amnezia.vpn.protocol.ProtocolState
enum class ConnectionState { enum class ConnectionState
{
CONNECTED, CONNECTED,
CONNECTING, CONNECTING,
DISCONNECTED, DISCONNECTED,
@ -30,7 +31,8 @@ public:
ErrorCode start(const QJsonObject &vpnConfig); ErrorCode start(const QJsonObject &vpnConfig);
void stop(); void stop();
void setNotificationText(const QString &title, const QString &message, int timerSec); void setNotificationText(const QString &title, const QString &message, int timerSec);
void saveFile(const QString& fileName, const QString &data); void saveFile(const QString &fileName, const QString &data);
QString openFile(const QString &filter);
void startQrReaderActivity(); void startQrReaderActivity();
signals: signals:
@ -43,6 +45,7 @@ signals:
void vpnDisconnected(); void vpnDisconnected();
void vpnReconnecting(); void vpnReconnecting();
void statisticsUpdated(quint64 rxBytes, quint64 txBytes); void statisticsUpdated(quint64 rxBytes, quint64 txBytes);
void fileOpened(QString uri);
void configImported(QString config); void configImported(QString config);
void importConfigFromOutside(QString config); void importConfigFromOutside(QString config);
void initConnectionState(Vpn::ConnectionState state); void initConnectionState(Vpn::ConnectionState state);
@ -65,6 +68,7 @@ private:
static void onVpnReconnecting(JNIEnv *env, jobject thiz); static void onVpnReconnecting(JNIEnv *env, jobject thiz);
static void onStatisticsUpdate(JNIEnv *env, jobject thiz, jlong rxBytes, jlong txBytes); static void onStatisticsUpdate(JNIEnv *env, jobject thiz, jlong rxBytes, jlong txBytes);
static void onConfigImported(JNIEnv *env, jobject thiz, jstring data); static void onConfigImported(JNIEnv *env, jobject thiz, jstring data);
static void onFileOpened(JNIEnv *env, jobject thiz, jstring uri);
static bool decodeQrCode(JNIEnv *env, jobject thiz, jstring data); static bool decodeQrCode(JNIEnv *env, jobject thiz, jstring data);
template <typename Ret, typename ...Args> template <typename Ret, typename ...Args>

View file

@ -0,0 +1,30 @@
#include <QCoreApplication>
#include "android_utils.h"
namespace AndroidUtils
{
QJniObject getActivity()
{
return QNativeInterface::QAndroidApplication::context();
}
QString convertJString(JNIEnv *env, jstring data)
{
int len = env->GetStringLength(data);
QString res(len, Qt::Uninitialized);
env->GetStringRegion(data, 0, len, reinterpret_cast<jchar *>(res.data()));
return res;
}
void runOnAndroidThreadSync(const std::function<void()> &runnable)
{
QNativeInterface::QAndroidApplication::runOnAndroidMainThread(runnable).waitForFinished();
}
void runOnAndroidThreadAsync(const std::function<void()> &runnable)
{
QNativeInterface::QAndroidApplication::runOnAndroidMainThread(runnable);
}
}

View file

@ -0,0 +1,16 @@
#ifndef ANDROID_UTILS_H
#define ANDROID_UTILS_H
#include <QJniObject>
namespace AndroidUtils
{
QJniObject getActivity();
QString convertJString(JNIEnv *env, jstring data);
void runOnAndroidThreadSync(const std::function<void()> &runnable);
void runOnAndroidThreadAsync(const std::function<void()> &runnable);
};
#endif // ANDROID_UTILS_H

View file

@ -1,183 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "androidutils.h"
#include <QGuiApplication>
#include <QJniEnvironment>
#include <QJniObject>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkCookieJar>
#include <QTimer>
#include <QUrlQuery>
#include "jni.h"
namespace
{
AndroidUtils *s_instance = nullptr;
} // namespace
// static
QString AndroidUtils::GetDeviceName()
{
QJniEnvironment env;
jclass BUILD = env->FindClass("android/os/Build");
jfieldID model = env->GetStaticFieldID(BUILD, "MODEL", "Ljava/lang/String;");
jstring value = (jstring)env->GetStaticObjectField(BUILD, model);
if (!value) {
return QString("Android Device");
}
const char *buffer = env->GetStringUTFChars(value, nullptr);
if (!buffer) {
return QString("Android Device");
}
QString res(buffer);
env->ReleaseStringUTFChars(value, buffer);
return res;
};
// static
AndroidUtils *AndroidUtils::instance()
{
if (!s_instance) {
Q_ASSERT(qApp);
s_instance = new AndroidUtils(qApp);
}
return s_instance;
}
AndroidUtils::AndroidUtils(QObject *parent) : QObject(parent)
{
Q_ASSERT(!s_instance);
s_instance = this;
}
AndroidUtils::~AndroidUtils()
{
Q_ASSERT(s_instance == this);
s_instance = nullptr;
}
// static
void AndroidUtils::dispatchToMainThread(std::function<void()> callback)
{
QTimer *timer = new QTimer();
timer->moveToThread(qApp->thread());
timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout, [=]() {
callback();
timer->deleteLater();
});
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection);
}
// static
QByteArray AndroidUtils::getQByteArrayFromJString(JNIEnv *env, jstring data)
{
const char *buffer = env->GetStringUTFChars(data, nullptr);
if (!buffer) {
qDebug() << "getQByteArrayFromJString - failed to parse data.";
return QByteArray();
}
QByteArray out(buffer);
env->ReleaseStringUTFChars(data, buffer);
return out;
}
// static
QString AndroidUtils::getQStringFromJString(JNIEnv *env, jstring data)
{
const char *buffer = env->GetStringUTFChars(data, nullptr);
if (!buffer) {
qDebug() << "getQStringFromJString - failed to parse data.";
return QString();
}
QString out(buffer);
env->ReleaseStringUTFChars(data, buffer);
return out;
}
// static
QJsonObject AndroidUtils::getQJsonObjectFromJString(JNIEnv *env, jstring data)
{
QByteArray raw(getQByteArrayFromJString(env, data));
QJsonParseError jsonError;
QJsonDocument json = QJsonDocument::fromJson(raw, &jsonError);
if (QJsonParseError::NoError != jsonError.error) {
qDebug() << "getQJsonObjectFromJstring - error parsing json. Code: " << jsonError.error
<< "Offset: " << jsonError.offset << "Message: " << jsonError.errorString() << "Data: " << raw;
return QJsonObject();
}
if (!json.isObject()) {
qDebug() << "getQJsonObjectFromJString - object expected.";
return QJsonObject();
}
return json.object();
}
QJniObject AndroidUtils::getActivity()
{
return QNativeInterface::QAndroidApplication::context();
}
int AndroidUtils::GetSDKVersion()
{
QJniEnvironment env;
jclass versionClass = env->FindClass("android/os/Build$VERSION");
jfieldID sdkIntFieldID = env->GetStaticFieldID(versionClass, "SDK_INT", "I");
int sdk = env->GetStaticIntField(versionClass, sdkIntFieldID);
return sdk;
}
QString AndroidUtils::GetManufacturer()
{
QJniEnvironment env;
jclass buildClass = env->FindClass("android/os/Build");
jfieldID manuFacturerField = env->GetStaticFieldID(buildClass, "MANUFACTURER", "Ljava/lang/String;");
jstring value = (jstring)env->GetStaticObjectField(buildClass, manuFacturerField);
const char *buffer = env->GetStringUTFChars(value, nullptr);
if (!buffer) {
qDebug() << "Failed to fetch MANUFACTURER";
return QByteArray();
}
QString res(buffer);
qDebug() << "MANUFACTURER: " << res;
env->ReleaseStringUTFChars(value, buffer);
return res;
}
void AndroidUtils::runOnAndroidThreadSync(const std::function<void()> runnable)
{
QNativeInterface::QAndroidApplication::runOnAndroidMainThread(runnable).waitForFinished();
}
void AndroidUtils::runOnAndroidThreadAsync(const std::function<void()> runnable)
{
QNativeInterface::QAndroidApplication::runOnAndroidMainThread(runnable);
}
// Static
// Creates a copy of the passed QByteArray in the JVM and passes back a ref
jbyteArray AndroidUtils::tojByteArray(const QByteArray &data)
{
QJniEnvironment env;
jbyteArray out = env->NewByteArray(data.size());
env->SetByteArrayRegion(out, 0, data.size(), reinterpret_cast<const jbyte *>(data.constData()));
return out;
}

View file

@ -1,49 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef ANDROIDUTILS_H
#define ANDROIDUTILS_H
#include <jni.h>
#include <QJniEnvironment>
#include <QJniObject>
#include <QObject>
#include <QString>
#include <QUrl>
class AndroidUtils final : public QObject
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(AndroidUtils)
public:
static QString GetDeviceName();
static int GetSDKVersion();
static QString GetManufacturer();
static AndroidUtils* instance();
static void dispatchToMainThread(std::function<void()> callback);
static QByteArray getQByteArrayFromJString(JNIEnv* env, jstring data);
static jbyteArray tojByteArray(const QByteArray& data);
static QString getQStringFromJString(JNIEnv* env, jstring data);
static QJsonObject getQJsonObjectFromJString(JNIEnv* env, jstring data);
static QJniObject getActivity();
static void runOnAndroidThreadSync(const std::function<void()> runnable);
static void runOnAndroidThreadAsync(const std::function<void()> runnable);
private:
AndroidUtils(QObject* parent);
~AndroidUtils();
};
#endif // ANDROIDUTILS_H

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "3rd/awg-apple/Sources/WireGuardKitC/WireGuardKitC.h" #include "3rd/amneziawg-apple/Sources/WireGuardKitC/WireGuardKitC.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>

View file

@ -946,6 +946,11 @@ Already installed containers were found on the server. All installed containers
<source>Show other methods on Github</source> <source>Show other methods on Github</source>
<translation>نمایش متدهای دیگر در گیت هاب</translation> <translation>نمایش متدهای دیگر در گیت هاب</translation>
</message> </message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="104"/>
<source>https://github.com/amnezia-vpn/amnezia-client#donate</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="113"/> <location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="113"/>
<source>Contacts</source> <source>Contacts</source>
@ -1854,6 +1859,11 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<source>I have nothing</source> <source>I have nothing</source>
<translation>من هیچی ندارم</translation> <translation>من هیچی ندارم</translation>
</message> </message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardStart.qml" line="138"/>
<source>https://amnezia.org/instructions/0_starter-guide</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>PageSetupWizardTextKey</name> <name>PageSetupWizardTextKey</name>
@ -2178,38 +2188,38 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::DeletePasswordJobPrivate</name> <name>QKeychain::DeletePasswordJobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="104"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="104"/>
<source>Password entry not found</source> <source>Password entry not found</source>
<translation>Password entry not found</translation> <translation>Password entry not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="108"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="108"/>
<source>Could not decrypt data</source> <source>Could not decrypt data</source>
<translation>Could not decrypt data</translation> <translation>Could not decrypt data</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="552"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="585"/>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="560"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="593"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation>Unknown error</translation> <translation>Unknown error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="578"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="614"/>
<source>Could not open wallet: %1; %2</source> <source>Could not open wallet: %1; %2</source>
<translation>Could not open wallet: %1; %2</translation> <translation>Could not open wallet: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="177"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="177"/>
<source>Password not found</source> <source>Password not found</source>
<translation>Password not found</translation> <translation>Password not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="173"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
<source>Could not open keystore</source> <source>Could not open keystore</source>
<translation>Could not open keystore</translation> <translation>Could not open keystore</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="179"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
<source>Could not remove private key from keystore</source> <source>Could not remove private key from keystore</source>
<translation>Could not remove private key from keystore</translation> <translation>Could not remove private key from keystore</translation>
</message> </message>
@ -2217,12 +2227,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::JobPrivate</name> <name>QKeychain::JobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="265"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="295"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation>Unknown error</translation> <translation>Unknown error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="509"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="542"/>
<source>Access to keychain denied</source> <source>Access to keychain denied</source>
<translation>Access to keychain denied</translation> <translation>Access to keychain denied</translation>
</message> </message>
@ -2230,27 +2240,27 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::PlainTextStore</name> <name>QKeychain::PlainTextStore</name>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="65"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="65"/>
<source>Could not store data in settings: access error</source> <source>Could not store data in settings: access error</source>
<translation>Could not store data in settings: access error</translation> <translation>Could not store data in settings: access error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="67"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="67"/>
<source>Could not store data in settings: format error</source> <source>Could not store data in settings: format error</source>
<translation>Could not store data in settings: format error</translation> <translation>Could not store data in settings: format error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="85"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="85"/>
<source>Could not delete data from settings: access error</source> <source>Could not delete data from settings: access error</source>
<translation>Could not delete data from settings: access error</translation> <translation>Could not delete data from settings: access error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="87"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="87"/>
<source>Could not delete data from settings: format error</source> <source>Could not delete data from settings: format error</source>
<translation>Could not delete data from settings: format error</translation> <translation>Could not delete data from settings: format error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="104"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="104"/>
<source>Entry not found</source> <source>Entry not found</source>
<translation>Entry not found</translation> <translation>Entry not found</translation>
</message> </message>
@ -2258,80 +2268,80 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::ReadPasswordJobPrivate</name> <name>QKeychain::ReadPasswordJobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="32"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="32"/>
<source>Password entry not found</source> <source>Password entry not found</source>
<translation>Password entry not found</translation> <translation>Password entry not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="36"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="36"/>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="139"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="139"/>
<source>Could not decrypt data</source> <source>Could not decrypt data</source>
<translation>Could not decrypt data</translation> <translation>Could not decrypt data</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="178"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="205"/>
<source>D-Bus is not running</source> <source>D-Bus is not running</source>
<translation>D-Bus is not running</translation> <translation>D-Bus is not running</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="187"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="214"/>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="197"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="224"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation>Unknown error</translation> <translation>Unknown error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="286"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="316"/>
<source>No keychain service available</source> <source>No keychain service available</source>
<translation>No keychain service available</translation> <translation>No keychain service available</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="288"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="318"/>
<source>Could not open wallet: %1; %2</source> <source>Could not open wallet: %1; %2</source>
<translation>Could not open wallet: %1; %2</translation> <translation>Could not open wallet: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="333"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="363"/>
<source>Access to keychain denied</source> <source>Access to keychain denied</source>
<translation>Access to keychain denied</translation> <translation>Access to keychain denied</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="354"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="384"/>
<source>Could not determine data type: %1; %2</source> <source>Could not determine data type: %1; %2</source>
<translation>Could not determine data type: %1; %2</translation> <translation>Could not determine data type: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="363"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="393"/>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="52"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="52"/>
<source>Entry not found</source> <source>Entry not found</source>
<translation>Entry not found</translation> <translation>Entry not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="372"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="402"/>
<source>Unsupported entry type &apos;Map&apos;</source> <source>Unsupported entry type &apos;Map&apos;</source>
<translation>Unsupported entry type &apos;Map&apos;</translation> <translation>Unsupported entry type &apos;Map&apos;</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="375"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="405"/>
<source>Unknown kwallet entry type &apos;%1&apos;</source> <source>Unknown kwallet entry type &apos;%1&apos;</source>
<translation>Unknown kwallet entry type &apos;%1&apos;</translation> <translation>Unknown kwallet entry type &apos;%1&apos;</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="96"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="96"/>
<source>Password not found</source> <source>Password not found</source>
<translation>Password not found</translation> <translation>Password not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="60"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="60"/>
<source>Could not open keystore</source> <source>Could not open keystore</source>
<translation>Could not open keystore</translation> <translation>Could not open keystore</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="68"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="68"/>
<source>Could not retrieve private key from keystore</source> <source>Could not retrieve private key from keystore</source>
<translation>Could not retrieve private key from keystore</translation> <translation>Could not retrieve private key from keystore</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="75"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="75"/>
<source>Could not create decryption cipher</source> <source>Could not create decryption cipher</source>
<translation>Could not create decryption cipher</translation> <translation>Could not create decryption cipher</translation>
</message> </message>
@ -2339,73 +2349,73 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::WritePasswordJobPrivate</name> <name>QKeychain::WritePasswordJobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="78"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="78"/>
<source>Credential size exceeds maximum size of %1</source> <source>Credential size exceeds maximum size of %1</source>
<translation>Credential size exceeds maximum size of %1</translation> <translation>Credential size exceeds maximum size of %1</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="87"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="87"/>
<source>Credential key exceeds maximum size of %1</source> <source>Credential key exceeds maximum size of %1</source>
<translation>Credential key exceeds maximum size of %1</translation> <translation>Credential key exceeds maximum size of %1</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="92"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="92"/>
<source>Writing credentials failed: Win32 error code %1</source> <source>Writing credentials failed: Win32 error code %1</source>
<translation>Writing credentials failed: Win32 error code %1</translation> <translation>Writing credentials failed: Win32 error code %1</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="162"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="162"/>
<source>Encryption failed</source> <source>Encryption failed</source>
<translation>Encryption failed</translation> <translation>Encryption failed</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="415"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="445"/>
<source>D-Bus is not running</source> <source>D-Bus is not running</source>
<translation>D-Bus is not running</translation> <translation>D-Bus is not running</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="425"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="455"/>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="452"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="482"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation>Unknown error</translation> <translation>Unknown error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="468"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="501"/>
<source>Could not open wallet: %1; %2</source> <source>Could not open wallet: %1; %2</source>
<translation>Could not open wallet: %1; %2</translation> <translation>Could not open wallet: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="144"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="144"/>
<source>Password not found</source> <source>Password not found</source>
<translation>Password not found</translation> <translation>Password not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="95"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="95"/>
<source>Could not open keystore</source> <source>Could not open keystore</source>
<translation>Could not open keystore</translation> <translation>Could not open keystore</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="124"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
<source>Could not create private key generator</source> <source>Could not create private key generator</source>
<translation>Could not create private key generator</translation> <translation>Could not create private key generator</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="131"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="131"/>
<source>Could not generate new private key</source> <source>Could not generate new private key</source>
<translation>Could not generate new private key</translation> <translation>Could not generate new private key</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="139"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="139"/>
<source>Could not retrieve private key from keystore</source> <source>Could not retrieve private key from keystore</source>
<translation>Could not retrieve private key from keystore</translation> <translation>Could not retrieve private key from keystore</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="147"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="147"/>
<source>Could not create encryption cipher</source> <source>Could not create encryption cipher</source>
<translation>Could not create encryption cipher</translation> <translation>Could not create encryption cipher</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="155"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="155"/>
<source>Could not encrypt data</source> <source>Could not encrypt data</source>
<translation>Could not encrypt data</translation> <translation>Could not encrypt data</translation>
</message> </message>
@ -2855,74 +2865,72 @@ This means that AmneziaWG keeps the fast performance of the original while addin
<translation>سرویس Sftp</translation> <translation>سرویس Sftp</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/libsecret.cpp" line="119"/> <location filename="../3rd/qtkeychain/qtkeychain/libsecret.cpp" line="119"/>
<source>Entry not found</source> <source>Entry not found</source>
<translation>Entry not found</translation> <translation>Entry not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="225"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="255"/>
<source>Access to keychain denied</source> <source>Access to keychain denied</source>
<translation>Access to keychain denied</translation> <translation>Access to keychain denied</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="227"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="257"/>
<source>No keyring daemon</source> <source>No keyring daemon</source>
<translation>No keyring daemon</translation> <translation>No keyring daemon</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="229"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="259"/>
<source>Already unlocked</source> <source>Already unlocked</source>
<translation>Already unlocked</translation> <translation>Already unlocked</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="231"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="261"/>
<source>No such keyring</source> <source>No such keyring</source>
<translation>No such keyring</translation> <translation>No such keyring</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="233"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="263"/>
<source>Bad arguments</source> <source>Bad arguments</source>
<translation>Bad arguments</translation> <translation>Bad arguments</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="235"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="265"/>
<source>I/O error</source> <source>I/O error</source>
<translation>I/O error</translation> <translation>I/O error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="237"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="267"/>
<source>Cancelled</source> <source>Cancelled</source>
<translation>Cancelled</translation> <translation>Cancelled</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="239"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="269"/>
<source>Keyring already exists</source> <source>Keyring already exists</source>
<translation>Keyring already exists</translation> <translation>Keyring already exists</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="241"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="271"/>
<source>No match</source> <source>No match</source>
<translation>No match</translation> <translation>No match</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="246"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="276"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation>Unknown error</translation> <translation>Unknown error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="72"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="72"/>
<source>error 0x%1: %2</source> <source>error 0x%1: %2</source>
<translation>error 0x%1: %2</translation> <translation>error 0x%1: %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/wireguard-tools/contrib/highlighter/gui/highlight.cpp" line="39"/>
<source>WireGuard Configuration Highlighter</source> <source>WireGuard Configuration Highlighter</source>
<translation>هایلایتر پیکربندی WireGuard</translation> <translation type="vanished">هایلایتر پیکربندی WireGuard</translation>
</message> </message>
<message> <message>
<location filename="../3rd/wireguard-tools/contrib/highlighter/gui/highlight.cpp" line="82"/>
<source>&amp;Randomize colors</source> <source>&amp;Randomize colors</source>
<translation>رنگهای تصادفی</translation> <translation type="vanished">رنگهای تصادفی</translation>
</message> </message>
</context> </context>
<context> <context>
@ -2936,13 +2944,13 @@ This means that AmneziaWG keeps the fast performance of the original while addin
<context> <context>
<name>Settings</name> <name>Settings</name>
<message> <message>
<location filename="../settings.cpp" line="26"/> <location filename="../settings.cpp" line="30"/>
<source>Server #1</source> <source>Server #1</source>
<translation>Server #1</translation> <translation>Server #1</translation>
</message> </message>
<message> <message>
<location filename="../settings.cpp" line="202"/> <location filename="../settings.cpp" line="206"/>
<location filename="../settings.cpp" line="209"/> <location filename="../settings.cpp" line="213"/>
<source>Server</source> <source>Server</source>
<translation>Server</translation> <translation>Server</translation>
</message> </message>
@ -2950,22 +2958,22 @@ This means that AmneziaWG keeps the fast performance of the original while addin
<context> <context>
<name>SettingsController</name> <name>SettingsController</name>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="25"/> <location filename="../ui/controllers/settingsController.cpp" line="26"/>
<source>Software version</source> <source>Software version</source>
<translation>نسخه نرمافزار</translation> <translation>نسخه نرمافزار</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="137"/> <location filename="../ui/controllers/settingsController.cpp" line="139"/>
<source>All settings have been reset to default values</source> <source>All settings have been reset to default values</source>
<translation>تمام تنظیمات به مقادیر پیش فرض ریست شد</translation> <translation>تمام تنظیمات به مقادیر پیش فرض ریست شد</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="143"/> <location filename="../ui/controllers/settingsController.cpp" line="145"/>
<source>Cached profiles cleared</source> <source>Cached profiles cleared</source>
<translation>پروفایل ذخیره شده پاک شد</translation> <translation>پروفایل ذخیره شده پاک شد</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="122"/> <location filename="../ui/controllers/settingsController.cpp" line="123"/>
<source>Backup file is corrupted</source> <source>Backup file is corrupted</source>
<translation>فایل بکآپ خراب شده است</translation> <translation>فایل بکآپ خراب شده است</translation>
</message> </message>

View file

@ -15,15 +15,13 @@
<context> <context>
<name>AndroidController</name> <name>AndroidController</name>
<message> <message>
<location filename="../platforms/android/android_controller.cpp" line="236"/>
<source>AmneziaVPN</source> <source>AmneziaVPN</source>
<translation>AmneziaVPN</translation> <translation type="vanished">AmneziaVPN</translation>
</message> </message>
<message> <message>
<location filename="../platforms/android/android_controller.cpp" line="239"/>
<source>VPN Connected</source> <source>VPN Connected</source>
<extracomment>Refers to the app - which is currently running the background and waiting</extracomment> <extracomment>Refers to the app - which is currently running the background and waiting</extracomment>
<translation>VPN Подключен</translation> <translation type="vanished">VPN Подключен</translation>
</message> </message>
</context> </context>
<context> <context>
@ -151,7 +149,7 @@
<context> <context>
<name>ImportController</name> <name>ImportController</name>
<message> <message>
<location filename="../ui/controllers/importController.cpp" line="435"/> <location filename="../ui/controllers/importController.cpp" line="411"/>
<source>Scanned %1 of %2.</source> <source>Scanned %1 of %2.</source>
<translation>Отсканировано %1 из%2.</translation> <translation>Отсканировано %1 из%2.</translation>
</message> </message>
@ -946,6 +944,11 @@ Already installed containers were found on the server. All installed containers
<source>Show other methods on Github</source> <source>Show other methods on Github</source>
<translation>Показать другие способы на Github</translation> <translation>Показать другие способы на Github</translation>
</message> </message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="104"/>
<source>https://github.com/amnezia-vpn/amnezia-client#donate</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="113"/> <location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="113"/>
<source>Contacts</source> <source>Contacts</source>
@ -1428,22 +1431,22 @@ Already installed containers were found on the server. All installed containers
<translation>Имя сервера</translation> <translation>Имя сервера</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="110"/> <location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="111"/>
<source>Save</source> <source>Save</source>
<translation>Сохранить</translation> <translation>Сохранить</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="137"/> <location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="142"/>
<source>Protocols</source> <source>Protocols</source>
<translation>Протоколы</translation> <translation>Протоколы</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="143"/> <location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="148"/>
<source>Services</source> <source>Services</source>
<translation>Сервисы</translation> <translation>Сервисы</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="147"/> <location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="152"/>
<source>Data</source> <source>Data</source>
<translation>Данные</translation> <translation>Данные</translation>
</message> </message>
@ -1854,6 +1857,11 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<source>I have nothing</source> <source>I have nothing</source>
<translation>У меня ничего нет</translation> <translation>У меня ничего нет</translation>
</message> </message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardStart.qml" line="138"/>
<source>https://amnezia.org/instructions/0_starter-guide</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>PageSetupWizardTextKey</name> <name>PageSetupWizardTextKey</name>
@ -1941,8 +1949,8 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation type="vanished">Доступ к управлению сервером. Пользователь, с которым вы делитесь полным доступом к соединению, сможет добавлять и удалять ваши протоколы и службы на сервере, а также изменять настройки.</translation> <translation type="vanished">Доступ к управлению сервером. Пользователь, с которым вы делитесь полным доступом к соединению, сможет добавлять и удалять ваши протоколы и службы на сервере, а также изменять настройки.</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="279"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="280"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="280"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="281"/>
<source>Server</source> <source>Server</source>
<translation>Сервер</translation> <translation>Сервер</translation>
</message> </message>
@ -2017,7 +2025,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="231"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="231"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="483"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="486"/>
<source>Users</source> <source>Users</source>
<translation type="unfinished">Пользователи</translation> <translation type="unfinished">Пользователи</translation>
</message> </message>
@ -2027,47 +2035,52 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation type="unfinished">Имя пользователя</translation> <translation type="unfinished">Имя пользователя</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="499"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="502"/>
<source>Search</source> <source>Search</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="595"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="584"/>
<source>Creation date: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="598"/>
<source>Rename</source> <source>Rename</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="624"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="627"/>
<source>Client name</source> <source>Client name</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="632"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="636"/>
<source>Save</source> <source>Save</source>
<translation type="unfinished">Сохранить</translation> <translation type="unfinished">Сохранить</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="660"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="668"/>
<source>Revoke</source> <source>Revoke</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="663"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="671"/>
<source>Revoke the config for a user - </source> <source>Revoke the config for a user - %1?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="664"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="672"/>
<source>The user will no longer be able to connect to your server.</source> <source>The user will no longer be able to connect to your server.</source>
<translation type="unfinished">Пользователь больше не сможет подключаться к вашему серверу</translation> <translation type="unfinished">Пользователь больше не сможет подключаться к вашему серверу</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="665"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="673"/>
<source>Continue</source> <source>Continue</source>
<translation type="unfinished">Продолжить</translation> <translation type="unfinished">Продолжить</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="666"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="674"/>
<source>Cancel</source> <source>Cancel</source>
<translation type="unfinished">Отменить</translation> <translation type="unfinished">Отменить</translation>
</message> </message>
@ -2081,20 +2094,20 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation>Поделиться доступом к VPN, без возможности управления сервером</translation> <translation>Поделиться доступом к VPN, без возможности управления сервером</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="331"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="332"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="332"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="333"/>
<source>Protocol</source> <source>Protocol</source>
<translation>Протокол</translation> <translation>Протокол</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="428"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="429"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="429"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="430"/>
<source>Connection format</source> <source>Connection format</source>
<translation>Формат подключения</translation> <translation>Формат подключения</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="186"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="186"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="468"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="469"/>
<source>Share</source> <source>Share</source>
<translation>Поделиться</translation> <translation>Поделиться</translation>
</message> </message>
@ -2124,12 +2137,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation type="unfinished">Сервер</translation> <translation type="unfinished">Сервер</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="102"/> <location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="100"/>
<source>Accessing </source> <source>Accessing </source>
<translation type="unfinished">Доступ </translation> <translation type="unfinished">Доступ </translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="103"/> <location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="101"/>
<source>File with accessing settings to </source> <source>File with accessing settings to </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -2160,38 +2173,38 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::DeletePasswordJobPrivate</name> <name>QKeychain::DeletePasswordJobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="104"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="104"/>
<source>Password entry not found</source> <source>Password entry not found</source>
<translation>Password entry not found</translation> <translation>Password entry not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="108"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="108"/>
<source>Could not decrypt data</source> <source>Could not decrypt data</source>
<translation>Could not decrypt data</translation> <translation>Could not decrypt data</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="552"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="585"/>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="560"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="593"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation>Unknown error</translation> <translation>Unknown error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="578"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="614"/>
<source>Could not open wallet: %1; %2</source> <source>Could not open wallet: %1; %2</source>
<translation>Could not open wallet: %1; %2</translation> <translation>Could not open wallet: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="177"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="177"/>
<source>Password not found</source> <source>Password not found</source>
<translation>Password not found</translation> <translation>Password not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="173"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
<source>Could not open keystore</source> <source>Could not open keystore</source>
<translation>Could not open keystore</translation> <translation>Could not open keystore</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="179"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
<source>Could not remove private key from keystore</source> <source>Could not remove private key from keystore</source>
<translation>Could not remove private key from keystore</translation> <translation>Could not remove private key from keystore</translation>
</message> </message>
@ -2199,12 +2212,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::JobPrivate</name> <name>QKeychain::JobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="265"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="295"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation>Unknown error</translation> <translation>Unknown error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="509"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="542"/>
<source>Access to keychain denied</source> <source>Access to keychain denied</source>
<translation>Access to keychain denied</translation> <translation>Access to keychain denied</translation>
</message> </message>
@ -2212,27 +2225,27 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::PlainTextStore</name> <name>QKeychain::PlainTextStore</name>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="65"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="65"/>
<source>Could not store data in settings: access error</source> <source>Could not store data in settings: access error</source>
<translation>Could not store data in settings: access error</translation> <translation>Could not store data in settings: access error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="67"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="67"/>
<source>Could not store data in settings: format error</source> <source>Could not store data in settings: format error</source>
<translation>Could not store data in settings: format error</translation> <translation>Could not store data in settings: format error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="85"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="85"/>
<source>Could not delete data from settings: access error</source> <source>Could not delete data from settings: access error</source>
<translation>Could not delete data from settings: access error</translation> <translation>Could not delete data from settings: access error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="87"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="87"/>
<source>Could not delete data from settings: format error</source> <source>Could not delete data from settings: format error</source>
<translation>Could not delete data from settings: format error</translation> <translation>Could not delete data from settings: format error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="104"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="104"/>
<source>Entry not found</source> <source>Entry not found</source>
<translation>Entry not found</translation> <translation>Entry not found</translation>
</message> </message>
@ -2240,80 +2253,80 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::ReadPasswordJobPrivate</name> <name>QKeychain::ReadPasswordJobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="32"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="32"/>
<source>Password entry not found</source> <source>Password entry not found</source>
<translation>Password entry not found</translation> <translation>Password entry not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="36"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="36"/>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="139"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="139"/>
<source>Could not decrypt data</source> <source>Could not decrypt data</source>
<translation>Could not decrypt data</translation> <translation>Could not decrypt data</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="178"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="205"/>
<source>D-Bus is not running</source> <source>D-Bus is not running</source>
<translation>D-Bus is not running</translation> <translation>D-Bus is not running</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="187"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="214"/>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="197"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="224"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation>Unknown error</translation> <translation>Unknown error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="286"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="316"/>
<source>No keychain service available</source> <source>No keychain service available</source>
<translation>No keychain service available</translation> <translation>No keychain service available</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="288"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="318"/>
<source>Could not open wallet: %1; %2</source> <source>Could not open wallet: %1; %2</source>
<translation>Could not open wallet: %1; %2</translation> <translation>Could not open wallet: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="333"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="363"/>
<source>Access to keychain denied</source> <source>Access to keychain denied</source>
<translation>Access to keychain denied</translation> <translation>Access to keychain denied</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="354"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="384"/>
<source>Could not determine data type: %1; %2</source> <source>Could not determine data type: %1; %2</source>
<translation>Could not determine data type: %1; %2</translation> <translation>Could not determine data type: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="363"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="393"/>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="52"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="52"/>
<source>Entry not found</source> <source>Entry not found</source>
<translation>Entry not found</translation> <translation>Entry not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="372"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="402"/>
<source>Unsupported entry type &apos;Map&apos;</source> <source>Unsupported entry type &apos;Map&apos;</source>
<translation>Unsupported entry type &apos;Map&apos;</translation> <translation>Unsupported entry type &apos;Map&apos;</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="375"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="405"/>
<source>Unknown kwallet entry type &apos;%1&apos;</source> <source>Unknown kwallet entry type &apos;%1&apos;</source>
<translation>Unknown kwallet entry type &apos;%1&apos;</translation> <translation>Unknown kwallet entry type &apos;%1&apos;</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="96"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="96"/>
<source>Password not found</source> <source>Password not found</source>
<translation>Password not found</translation> <translation>Password not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="60"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="60"/>
<source>Could not open keystore</source> <source>Could not open keystore</source>
<translation>Could not open keystore</translation> <translation>Could not open keystore</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="68"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="68"/>
<source>Could not retrieve private key from keystore</source> <source>Could not retrieve private key from keystore</source>
<translation>Could not retrieve private key from keystore</translation> <translation>Could not retrieve private key from keystore</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="75"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="75"/>
<source>Could not create decryption cipher</source> <source>Could not create decryption cipher</source>
<translation>Could not create decryption cipher</translation> <translation>Could not create decryption cipher</translation>
</message> </message>
@ -2321,73 +2334,73 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::WritePasswordJobPrivate</name> <name>QKeychain::WritePasswordJobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="78"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="78"/>
<source>Credential size exceeds maximum size of %1</source> <source>Credential size exceeds maximum size of %1</source>
<translation>Credential size exceeds maximum size of %1</translation> <translation>Credential size exceeds maximum size of %1</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="87"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="87"/>
<source>Credential key exceeds maximum size of %1</source> <source>Credential key exceeds maximum size of %1</source>
<translation>Credential key exceeds maximum size of %1</translation> <translation>Credential key exceeds maximum size of %1</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="92"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="92"/>
<source>Writing credentials failed: Win32 error code %1</source> <source>Writing credentials failed: Win32 error code %1</source>
<translation>Writing credentials failed: Win32 error code %1</translation> <translation>Writing credentials failed: Win32 error code %1</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="162"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="162"/>
<source>Encryption failed</source> <source>Encryption failed</source>
<translation>Encryption failed</translation> <translation>Encryption failed</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="415"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="445"/>
<source>D-Bus is not running</source> <source>D-Bus is not running</source>
<translation>D-Bus is not running</translation> <translation>D-Bus is not running</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="425"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="455"/>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="452"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="482"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation>Unknown error</translation> <translation>Unknown error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="468"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="501"/>
<source>Could not open wallet: %1; %2</source> <source>Could not open wallet: %1; %2</source>
<translation>Could not open wallet: %1; %2</translation> <translation>Could not open wallet: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="144"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="144"/>
<source>Password not found</source> <source>Password not found</source>
<translation>Password not found</translation> <translation>Password not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="95"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="95"/>
<source>Could not open keystore</source> <source>Could not open keystore</source>
<translation>Could not open keystore</translation> <translation>Could not open keystore</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="124"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
<source>Could not create private key generator</source> <source>Could not create private key generator</source>
<translation>Could not create private key generator</translation> <translation>Could not create private key generator</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="131"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="131"/>
<source>Could not generate new private key</source> <source>Could not generate new private key</source>
<translation>Could not generate new private key</translation> <translation>Could not generate new private key</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="139"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="139"/>
<source>Could not retrieve private key from keystore</source> <source>Could not retrieve private key from keystore</source>
<translation>Could not retrieve private key from keystore</translation> <translation>Could not retrieve private key from keystore</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="147"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="147"/>
<source>Could not create encryption cipher</source> <source>Could not create encryption cipher</source>
<translation>Could not create encryption cipher</translation> <translation>Could not create encryption cipher</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="155"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="155"/>
<source>Could not encrypt data</source> <source>Could not encrypt data</source>
<translation>Could not encrypt data</translation> <translation>Could not encrypt data</translation>
</message> </message>
@ -2594,7 +2607,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation>VPN pool error: no available addresses</translation> <translation>VPN pool error: no available addresses</translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="64"/> <location filename="../core/errorstrings.cpp" line="63"/>
<source>VPN connection error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../core/errorstrings.cpp" line="67"/>
<source>Internal error</source> <source>Internal error</source>
<translation>Internal error</translation> <translation>Internal error</translation>
</message> </message>
@ -2822,62 +2840,62 @@ This means that AmneziaWG keeps the fast performance of the original while addin
<translation>Сервис SFTP</translation> <translation>Сервис SFTP</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/libsecret.cpp" line="119"/> <location filename="../3rd/qtkeychain/qtkeychain/libsecret.cpp" line="119"/>
<source>Entry not found</source> <source>Entry not found</source>
<translation>Entry not found</translation> <translation>Entry not found</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="225"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="255"/>
<source>Access to keychain denied</source> <source>Access to keychain denied</source>
<translation>Access to keychain denied</translation> <translation>Access to keychain denied</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="227"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="257"/>
<source>No keyring daemon</source> <source>No keyring daemon</source>
<translation>No keyring daemon</translation> <translation>No keyring daemon</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="229"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="259"/>
<source>Already unlocked</source> <source>Already unlocked</source>
<translation>Already unlocked</translation> <translation>Already unlocked</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="231"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="261"/>
<source>No such keyring</source> <source>No such keyring</source>
<translation>No such keyring</translation> <translation>No such keyring</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="233"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="263"/>
<source>Bad arguments</source> <source>Bad arguments</source>
<translation>Bad arguments</translation> <translation>Bad arguments</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="235"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="265"/>
<source>I/O error</source> <source>I/O error</source>
<translation>I/O error</translation> <translation>I/O error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="237"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="267"/>
<source>Cancelled</source> <source>Cancelled</source>
<translation>Cancelled</translation> <translation>Cancelled</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="239"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="269"/>
<source>Keyring already exists</source> <source>Keyring already exists</source>
<translation>Keyring already exists</translation> <translation>Keyring already exists</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="241"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="271"/>
<source>No match</source> <source>No match</source>
<translation>No match</translation> <translation>No match</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="246"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="276"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation>Unknown error</translation> <translation>Unknown error</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="72"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="72"/>
<source>error 0x%1: %2</source> <source>error 0x%1: %2</source>
<translation>error 0x%1: %2</translation> <translation>error 0x%1: %2</translation>
</message> </message>
@ -2893,13 +2911,13 @@ This means that AmneziaWG keeps the fast performance of the original while addin
<context> <context>
<name>Settings</name> <name>Settings</name>
<message> <message>
<location filename="../settings.cpp" line="26"/> <location filename="../settings.cpp" line="30"/>
<source>Server #1</source> <source>Server #1</source>
<translation>Server #1</translation> <translation>Server #1</translation>
</message> </message>
<message> <message>
<location filename="../settings.cpp" line="202"/> <location filename="../settings.cpp" line="206"/>
<location filename="../settings.cpp" line="209"/> <location filename="../settings.cpp" line="213"/>
<source>Server</source> <source>Server</source>
<translation>Server</translation> <translation>Server</translation>
</message> </message>
@ -2907,22 +2925,22 @@ This means that AmneziaWG keeps the fast performance of the original while addin
<context> <context>
<name>SettingsController</name> <name>SettingsController</name>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="25"/> <location filename="../ui/controllers/settingsController.cpp" line="26"/>
<source>Software version</source> <source>Software version</source>
<translation>Версия ПО</translation> <translation>Версия ПО</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="137"/> <location filename="../ui/controllers/settingsController.cpp" line="139"/>
<source>All settings have been reset to default values</source> <source>All settings have been reset to default values</source>
<translation>Все настройки были сброшены к значению &quot;По умолчанию&quot;</translation> <translation>Все настройки были сброшены к значению &quot;По умолчанию&quot;</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="143"/> <location filename="../ui/controllers/settingsController.cpp" line="145"/>
<source>Cached profiles cleared</source> <source>Cached profiles cleared</source>
<translation>Кэш профиля очищен</translation> <translation>Кэш профиля очищен</translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="122"/> <location filename="../ui/controllers/settingsController.cpp" line="123"/>
<source>Backup file is corrupted</source> <source>Backup file is corrupted</source>
<translation>Backup файл поврежден</translation> <translation>Backup файл поврежден</translation>
</message> </message>
@ -3054,7 +3072,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="429"/> <location filename="../vpnconnection.cpp" line="432"/>
<source>Mbps</source> <source>Mbps</source>
<translation>Mbps</translation> <translation>Mbps</translation>
</message> </message>

View file

@ -11,15 +11,9 @@
<context> <context>
<name>AndroidController</name> <name>AndroidController</name>
<message> <message>
<location filename="../platforms/android/android_controller.cpp" line="236"/>
<source>AmneziaVPN</source>
<translation></translation>
</message>
<message>
<location filename="../platforms/android/android_controller.cpp" line="239"/>
<source>VPN Connected</source> <source>VPN Connected</source>
<extracomment>Refers to the app - which is currently running the background and waiting</extracomment> <extracomment>Refers to the app - which is currently running the background and waiting</extracomment>
<translation>VPN已连接</translation> <translation type="vanished">VPN已连接</translation>
</message> </message>
</context> </context>
<context> <context>
@ -158,7 +152,7 @@
<context> <context>
<name>ImportController</name> <name>ImportController</name>
<message> <message>
<location filename="../ui/controllers/importController.cpp" line="435"/> <location filename="../ui/controllers/importController.cpp" line="411"/>
<source>Scanned %1 of %2.</source> <source>Scanned %1 of %2.</source>
<translation> %1 of %2.</translation> <translation> %1 of %2.</translation>
</message> </message>
@ -997,6 +991,11 @@ And if you don&apos;t like the app, all the more support it - the donation will
<source>Show other methods on Github</source> <source>Show other methods on Github</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="104"/>
<source>https://github.com/amnezia-vpn/amnezia-client#donate</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="113"/> <location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="113"/>
<source>Contacts</source> <source>Contacts</source>
@ -1511,22 +1510,22 @@ And if you don&apos;t like the app, all the more support it - the donation will
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="110"/> <location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="111"/>
<source>Save</source> <source>Save</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="137"/> <location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="142"/>
<source>Protocols</source> <source>Protocols</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="143"/> <location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="148"/>
<source>Services</source> <source>Services</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="147"/> <location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="152"/>
<source>Data</source> <source>Data</source>
<translation></translation> <translation></translation>
</message> </message>
@ -1957,6 +1956,11 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<source>I have nothing</source> <source>I have nothing</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardStart.qml" line="138"/>
<source>https://amnezia.org/instructions/0_starter-guide</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>PageSetupWizardTextKey</name> <name>PageSetupWizardTextKey</name>
@ -2078,7 +2082,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="231"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="231"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="483"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="486"/>
<source>Users</source> <source>Users</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -2088,47 +2092,52 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation> VPN 访</translation> <translation> VPN 访</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="499"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="502"/>
<source>Search</source> <source>Search</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="595"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="584"/>
<source>Creation date: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="598"/>
<source>Rename</source> <source>Rename</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="624"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="627"/>
<source>Client name</source> <source>Client name</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="632"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="636"/>
<source>Save</source> <source>Save</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="660"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="668"/>
<source>Revoke</source> <source>Revoke</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="663"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="671"/>
<source>Revoke the config for a user - </source> <source>Revoke the config for a user - %1?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="664"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="672"/>
<source>The user will no longer be able to connect to your server.</source> <source>The user will no longer be able to connect to your server.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="665"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="673"/>
<source>Continue</source> <source>Continue</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="666"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="674"/>
<source>Cancel</source> <source>Cancel</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -2170,8 +2179,8 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation type="obsolete"></translation> <translation type="obsolete"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="279"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="280"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="280"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="281"/>
<source>Server</source> <source>Server</source>
<translation></translation> <translation></translation>
</message> </message>
@ -2193,8 +2202,8 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation type="obsolete"></translation> <translation type="obsolete"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="331"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="332"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="332"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="333"/>
<source>Protocol</source> <source>Protocol</source>
<translation></translation> <translation></translation>
</message> </message>
@ -2214,14 +2223,14 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="428"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="429"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="429"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="430"/>
<source>Connection format</source> <source>Connection format</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="186"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="186"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="468"/> <location filename="../ui/qml/Pages2/PageShare.qml" line="469"/>
<source>Share</source> <source>Share</source>
<translation></translation> <translation></translation>
</message> </message>
@ -2251,12 +2260,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="102"/> <location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="100"/>
<source>Accessing </source> <source>Accessing </source>
<translation type="unfinished">访</translation> <translation type="unfinished">访</translation>
</message> </message>
<message> <message>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="103"/> <location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="101"/>
<source>File with accessing settings to </source> <source>File with accessing settings to </source>
<translation type="unfinished">访:</translation> <translation type="unfinished">访:</translation>
</message> </message>
@ -2287,38 +2296,38 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::DeletePasswordJobPrivate</name> <name>QKeychain::DeletePasswordJobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="104"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="104"/>
<source>Password entry not found</source> <source>Password entry not found</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="108"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="108"/>
<source>Could not decrypt data</source> <source>Could not decrypt data</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="552"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="585"/>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="560"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="593"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="578"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="614"/>
<source>Could not open wallet: %1; %2</source> <source>Could not open wallet: %1; %2</source>
<translation>: %1; %2</translation> <translation>: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="177"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="177"/>
<source>Password not found</source> <source>Password not found</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="173"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
<source>Could not open keystore</source> <source>Could not open keystore</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="179"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
<source>Could not remove private key from keystore</source> <source>Could not remove private key from keystore</source>
<translation></translation> <translation></translation>
</message> </message>
@ -2326,12 +2335,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::JobPrivate</name> <name>QKeychain::JobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="265"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="295"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="509"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="542"/>
<source>Access to keychain denied</source> <source>Access to keychain denied</source>
<translation>访</translation> <translation>访</translation>
</message> </message>
@ -2339,27 +2348,27 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::PlainTextStore</name> <name>QKeychain::PlainTextStore</name>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="65"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="65"/>
<source>Could not store data in settings: access error</source> <source>Could not store data in settings: access error</source>
<translation>访</translation> <translation>访</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="67"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="67"/>
<source>Could not store data in settings: format error</source> <source>Could not store data in settings: format error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="85"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="85"/>
<source>Could not delete data from settings: access error</source> <source>Could not delete data from settings: access error</source>
<translation>访</translation> <translation>访</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="87"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="87"/>
<source>Could not delete data from settings: format error</source> <source>Could not delete data from settings: format error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/plaintextstore.cpp" line="104"/> <location filename="../3rd/qtkeychain/qtkeychain/plaintextstore.cpp" line="104"/>
<source>Entry not found</source> <source>Entry not found</source>
<translation></translation> <translation></translation>
</message> </message>
@ -2367,80 +2376,80 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::ReadPasswordJobPrivate</name> <name>QKeychain::ReadPasswordJobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="32"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="32"/>
<source>Password entry not found</source> <source>Password entry not found</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="36"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="36"/>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="139"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="139"/>
<source>Could not decrypt data</source> <source>Could not decrypt data</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="178"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="205"/>
<source>D-Bus is not running</source> <source>D-Bus is not running</source>
<translation>D-Bus未运行</translation> <translation>D-Bus未运行</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="187"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="214"/>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="197"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="224"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="286"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="316"/>
<source>No keychain service available</source> <source>No keychain service available</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="288"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="318"/>
<source>Could not open wallet: %1; %2</source> <source>Could not open wallet: %1; %2</source>
<translation>: %1; %2</translation> <translation>: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="333"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="363"/>
<source>Access to keychain denied</source> <source>Access to keychain denied</source>
<translation>访</translation> <translation>访</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="354"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="384"/>
<source>Could not determine data type: %1; %2</source> <source>Could not determine data type: %1; %2</source>
<translation>: %1 %2</translation> <translation>: %1 %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="363"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="393"/>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="52"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="52"/>
<source>Entry not found</source> <source>Entry not found</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="372"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="402"/>
<source>Unsupported entry type &apos;Map&apos;</source> <source>Unsupported entry type &apos;Map&apos;</source>
<translation> &apos;Map&apos;</translation> <translation> &apos;Map&apos;</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="375"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="405"/>
<source>Unknown kwallet entry type &apos;%1&apos;</source> <source>Unknown kwallet entry type &apos;%1&apos;</source>
<translation> &apos;%1&apos;</translation> <translation> &apos;%1&apos;</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="96"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="96"/>
<source>Password not found</source> <source>Password not found</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="60"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="60"/>
<source>Could not open keystore</source> <source>Could not open keystore</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="68"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="68"/>
<source>Could not retrieve private key from keystore</source> <source>Could not retrieve private key from keystore</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="75"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="75"/>
<source>Could not create decryption cipher</source> <source>Could not create decryption cipher</source>
<translation></translation> <translation></translation>
</message> </message>
@ -2448,73 +2457,73 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<context> <context>
<name>QKeychain::WritePasswordJobPrivate</name> <name>QKeychain::WritePasswordJobPrivate</name>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="78"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="78"/>
<source>Credential size exceeds maximum size of %1</source> <source>Credential size exceeds maximum size of %1</source>
<translation>: %1</translation> <translation>: %1</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="87"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="87"/>
<source>Credential key exceeds maximum size of %1</source> <source>Credential key exceeds maximum size of %1</source>
<translation>: %1</translation> <translation>: %1</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="92"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="92"/>
<source>Writing credentials failed: Win32 error code %1</source> <source>Writing credentials failed: Win32 error code %1</source>
<translation>Win32错误码: %1</translation> <translation>Win32错误码: %1</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_win.cpp" line="162"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_win.cpp" line="162"/>
<source>Encryption failed</source> <source>Encryption failed</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="415"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="445"/>
<source>D-Bus is not running</source> <source>D-Bus is not running</source>
<translation>D-Bus未运行</translation> <translation>D-Bus未运行</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="425"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="455"/>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="452"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="482"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="468"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="501"/>
<source>Could not open wallet: %1; %2</source> <source>Could not open wallet: %1; %2</source>
<translation>: %1; %2</translation> <translation>: %1; %2</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="144"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="144"/>
<source>Password not found</source> <source>Password not found</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="95"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="95"/>
<source>Could not open keystore</source> <source>Could not open keystore</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="124"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
<source>Could not create private key generator</source> <source>Could not create private key generator</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="131"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="131"/>
<source>Could not generate new private key</source> <source>Could not generate new private key</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="139"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="139"/>
<source>Could not retrieve private key from keystore</source> <source>Could not retrieve private key from keystore</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="147"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="147"/>
<source>Could not create encryption cipher</source> <source>Could not create encryption cipher</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_android.cpp" line="155"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="155"/>
<source>Could not encrypt data</source> <source>Could not encrypt data</source>
<translation></translation> <translation></translation>
</message> </message>
@ -2666,6 +2675,11 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<source>Sftp error: No media was in remote drive</source> <source>Sftp error: No media was in remote drive</source>
<translation>Sftp 错误: 远程驱动器中没有媒介</translation> <translation>Sftp 错误: 远程驱动器中没有媒介</translation>
</message> </message>
<message>
<location filename="../core/errorstrings.cpp" line="63"/>
<source>VPN connection error</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Failed to save config to disk</source> <source>Failed to save config to disk</source>
<translation type="vanished"></translation> <translation type="vanished"></translation>
@ -2730,7 +2744,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation type="vanished"></translation> <translation type="vanished"></translation>
</message> </message>
<message> <message>
<location filename="../core/errorstrings.cpp" line="64"/> <location filename="../core/errorstrings.cpp" line="67"/>
<source>Internal error</source> <source>Internal error</source>
<translation></translation> <translation></translation>
</message> </message>
@ -2970,62 +2984,62 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<translation>Sftp - FTP </translation> <translation>Sftp - FTP </translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/libsecret.cpp" line="119"/> <location filename="../3rd/qtkeychain/qtkeychain/libsecret.cpp" line="119"/>
<source>Entry not found</source> <source>Entry not found</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="225"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="255"/>
<source>Access to keychain denied</source> <source>Access to keychain denied</source>
<translation>访</translation> <translation>访</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="227"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="257"/>
<source>No keyring daemon</source> <source>No keyring daemon</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="229"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="259"/>
<source>Already unlocked</source> <source>Already unlocked</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="231"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="261"/>
<source>No such keyring</source> <source>No such keyring</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="233"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="263"/>
<source>Bad arguments</source> <source>Bad arguments</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="235"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="265"/>
<source>I/O error</source> <source>I/O error</source>
<translation>I/O错误</translation> <translation>I/O错误</translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="237"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="267"/>
<source>Cancelled</source> <source>Cancelled</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="239"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="269"/>
<source>Keyring already exists</source> <source>Keyring already exists</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="241"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="271"/>
<source>No match</source> <source>No match</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_unix.cpp" line="246"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_unix.cpp" line="276"/>
<source>Unknown error</source> <source>Unknown error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../3rd/qtkeychain/keychain_haiku.cpp" line="72"/> <location filename="../3rd/qtkeychain/qtkeychain/keychain_haiku.cpp" line="72"/>
<source>error 0x%1: %2</source> <source>error 0x%1: %2</source>
<translation> 0x%1: %2</translation> <translation> 0x%1: %2</translation>
</message> </message>
@ -3041,13 +3055,13 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<context> <context>
<name>Settings</name> <name>Settings</name>
<message> <message>
<location filename="../settings.cpp" line="26"/> <location filename="../settings.cpp" line="30"/>
<source>Server #1</source> <source>Server #1</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../settings.cpp" line="202"/> <location filename="../settings.cpp" line="206"/>
<location filename="../settings.cpp" line="209"/> <location filename="../settings.cpp" line="213"/>
<source>Server</source> <source>Server</source>
<translation></translation> <translation></translation>
</message> </message>
@ -3055,22 +3069,22 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<context> <context>
<name>SettingsController</name> <name>SettingsController</name>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="25"/> <location filename="../ui/controllers/settingsController.cpp" line="26"/>
<source>Software version</source> <source>Software version</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="122"/> <location filename="../ui/controllers/settingsController.cpp" line="123"/>
<source>Backup file is corrupted</source> <source>Backup file is corrupted</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="137"/> <location filename="../ui/controllers/settingsController.cpp" line="139"/>
<source>All settings have been reset to default values</source> <source>All settings have been reset to default values</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../ui/controllers/settingsController.cpp" line="143"/> <location filename="../ui/controllers/settingsController.cpp" line="145"/>
<source>Cached profiles cleared</source> <source>Cached profiles cleared</source>
<translation></translation> <translation></translation>
</message> </message>
@ -3206,7 +3220,7 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<context> <context>
<name>VpnConnection</name> <name>VpnConnection</name>
<message> <message>
<location filename="../vpnconnection.cpp" line="429"/> <location filename="../vpnconnection.cpp" line="432"/>
<source>Mbps</source> <source>Mbps</source>
<translation></translation> <translation></translation>
</message> </message>

View file

@ -15,7 +15,7 @@
#include "core/errorstrings.h" #include "core/errorstrings.h"
#include "systemController.h" #include "systemController.h"
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
#include "platforms/android/androidutils.h" #include "platforms/android/android_utils.h"
#endif #endif
#include "qrcodegen.hpp" #include "qrcodegen.hpp"

View file

@ -7,7 +7,7 @@
#endif #endif
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
#include "../../platforms/android/androidutils.h" #include "platforms/android/android_utils.h"
#include <QJniObject> #include <QJniObject>
#endif #endif
#if defined Q_OS_MAC #if defined Q_OS_MAC

View file

@ -7,8 +7,7 @@
#include "ui/qautostart.h" #include "ui/qautostart.h"
#include "version.h" #include "version.h"
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
#include "../../platforms/android/android_controller.h" #include "platforms/android/android_utils.h"
#include "../../platforms/android/androidutils.h"
#include <QJniObject> #include <QJniObject>
#endif #endif

View file

@ -60,6 +60,11 @@ QString SystemController::getFileName(const QString &acceptLabel, const QString
const QString &selectedFile, const bool isSaveMode, const QString &defaultSuffix) const QString &selectedFile, const bool isSaveMode, const QString &defaultSuffix)
{ {
QString fileName; QString fileName;
#ifdef Q_OS_ANDROID
Q_ASSERT(!isSaveMode);
return AndroidController::instance()->openFile(nameFilter);
#endif
#ifdef Q_OS_IOS #ifdef Q_OS_IOS
MobileUtils mobileUtils; MobileUtils mobileUtils;
@ -108,20 +113,6 @@ QString SystemController::getFileName(const QString &acceptLabel, const QString
} }
fileName = mainFileDialog->property("selectedFile").toString(); fileName = mainFileDialog->property("selectedFile").toString();
#ifdef Q_OS_ANDROID
// patch for files containing spaces etc
const QString sep { "raw%3A%2F" };
if (fileName.startsWith("content://") && fileName.contains(sep)) {
QString contentUrl = fileName.split(sep).at(0);
QString rawUrl = fileName.split(sep).at(1);
rawUrl.replace(" ", "%20");
fileName = contentUrl + sep + rawUrl;
}
return fileName;
#endif
return QUrl(fileName).toLocalFile(); return QUrl(fileName).toLocalFile();
} }

View file

@ -245,8 +245,13 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson(); const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
ServerController serverController(m_settings); ServerController serverController(m_settings);
const QString clientsTableFile = QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container)); if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks
|| container == DockerContainer::Cloak) {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
} else {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
}
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
@ -273,8 +278,13 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson(); const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
ServerController serverController(m_settings); ServerController serverController(m_settings);
const QString clientsTableFile = QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container)); if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks
|| container == DockerContainer::Cloak) {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
} else {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
}
ErrorCode error = ErrorCode error =
serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
@ -345,8 +355,13 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson(); const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
const QString clientsTableFile = QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container)); if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks
|| container == DockerContainer::Cloak) {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
} else {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
}
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server"; logger.error() << "Failed to upload the clientsTable file to the server";
@ -395,8 +410,13 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson(); const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
const QString clientsTableFile = QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
QString("/opt/amnezia/%1/clientsTable").arg(ContainerProps::containerTypeToString(container)); if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks
|| container == DockerContainer::Cloak) {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
} else {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
}
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile); error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server"; logger.error() << "Failed to upload the clientsTable file to the server";

View file

@ -15,6 +15,10 @@ ServersModel::ServersModel(std::shared_ptr<Settings> settings, QObject *parent)
auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString()); auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString());
emit ServersModel::defaultContainerChanged(defaultContainer); emit ServersModel::defaultContainerChanged(defaultContainer);
}); });
connect(this, &ServersModel::currentlyProcessedServerIndexChanged, this, [this](const int serverIndex) {
auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString());
emit ServersModel::defaultContainerChanged(defaultContainer);
});
} }
int ServersModel::rowCount(const QModelIndex &parent) const int ServersModel::rowCount(const QModelIndex &parent) const
@ -269,6 +273,7 @@ void ServersModel::removeServer()
if (m_settings->serversCount() == 0) { if (m_settings->serversCount() == 0) {
setDefaultServerIndex(-1); setDefaultServerIndex(-1);
} }
setCurrentlyProcessedServerIndex(m_defaultServerIndex);
endResetModel(); endResetModel();
} }
@ -526,3 +531,8 @@ void ServersModel::toggleAmneziaDns(bool enabled)
emit defaultServerDescriptionChanged(); emit defaultServerDescriptionChanged();
} }
bool ServersModel::isDefaultServerFromApi()
{
return m_settings->server(m_defaultServerIndex).value(config_key::configVersion).toInt();
}

View file

@ -97,6 +97,8 @@ public slots:
void toggleAmneziaDns(bool enabled); void toggleAmneziaDns(bool enabled);
bool isDefaultServerFromApi();
protected: protected:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;

View file

@ -26,6 +26,22 @@ ListView {
id: containersRadioButtonGroup id: containersRadioButtonGroup
} }
Connections {
target: ServersModel
function onCurrentlyProcessedServerIndexChanged() {
menuContent.checkCurrentItem()
}
}
function checkCurrentItem() {
var item = menuContent.itemAtIndex(currentIndex)
if (item !== null) {
var radioButton = item.children[0].children[0]
radioButton.checked = true
}
}
delegate: Item { delegate: Item {
implicitWidth: rootWidth implicitWidth: rootWidth
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight

View file

@ -31,6 +31,7 @@ PageType {
containersDropDown.rootButtonClickedFunction() containersDropDown.rootButtonClickedFunction()
} }
} }
function onForceCloseDrawer() { function onForceCloseDrawer() {
buttonContent.state = "collapsed" buttonContent.state = "collapsed"
} }

View file

@ -28,6 +28,14 @@ PageType {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
contentHeight: content.height contentHeight: content.height
enabled: !ServersModel.isDefaultServerFromApi()
Component.onCompleted: {
if (ServersModel.isDefaultServerFromApi()) {
PageController.showNotificationMessage(qsTr("Default server does not support custom dns"))
}
}
ColumnLayout { ColumnLayout {
id: content id: content

View file

@ -55,6 +55,9 @@ PageType {
model: SortFilterProxyModel { model: SortFilterProxyModel {
id: proxyContainersModel id: proxyContainersModel
sourceModel: ContainersModel sourceModel: ContainersModel
sorters: [
RoleSorter { roleName: "isInstalled"; sortOrder: Qt.DescendingOrder }
]
} }
Component.onCompleted: updateContainersModelFilters() Component.onCompleted: updateContainersModelFilters()

View file

@ -21,7 +21,13 @@ PageType {
id: root id: root
property bool pageEnabled: { property bool pageEnabled: {
return !ConnectionController.isConnected return !ConnectionController.isConnected && !ServersModel.isDefaultServerFromApi()
}
Component.onCompleted: {
if (ServersModel.isDefaultServerFromApi()) {
PageController.showNotificationMessage(qsTr("Default server does not support split tunneling function"))
}
} }
Connections { Connections {

View file

@ -42,6 +42,7 @@ PageType {
function onInstallServerFinished(finishedMessage) { function onInstallServerFinished(finishedMessage) {
if (!ConnectionController.isConnected) { if (!ConnectionController.isConnected) {
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1); ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
} }
PageController.goToStartPage() PageController.goToStartPage()

View file

@ -26,6 +26,7 @@ PageType {
function onImportFinished() { function onImportFinished() {
if (!ConnectionController.isConnected) { if (!ConnectionController.isConnected) {
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1); ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
} }
PageController.goToStartPage() PageController.goToStartPage()

View file

@ -64,24 +64,26 @@ void VpnConnection::onConnectionStateChanged(Vpn::ConnectionState state)
IpcClient::Interface()->resetIpStack(); IpcClient::Interface()->resetIpStack();
IpcClient::Interface()->flushDns(); IpcClient::Interface()->flushDns();
if (m_settings->routeMode() != Settings::VpnAllSites) { if (!m_vpnConfiguration.value(config_key::configVersion).toInt()) {
IpcClient::Interface()->routeDeleteList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0"); if (m_settings->routeMode() != Settings::VpnAllSites) {
// qDebug() << "VpnConnection::onConnectionStateChanged :: adding custom routes, count:" << forwardIps.size(); IpcClient::Interface()->routeDeleteList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0");
} // qDebug() << "VpnConnection::onConnectionStateChanged :: adding custom routes, count:" << forwardIps.size();
QString dns1 = m_vpnConfiguration.value(config_key::dns1).toString(); }
QString dns2 = m_vpnConfiguration.value(config_key::dns2).toString(); QString dns1 = m_vpnConfiguration.value(config_key::dns1).toString();
QString dns2 = m_vpnConfiguration.value(config_key::dns2).toString();
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << dns1 << dns2); IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << dns1 << dns2);
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) { if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
QTimer::singleShot(1000, m_vpnProtocol.data(), QTimer::singleShot(1000, m_vpnProtocol.data(),
[this]() { addSitesRoutes(m_vpnProtocol->vpnGateway(), m_settings->routeMode()); }); [this]() { addSitesRoutes(m_vpnProtocol->vpnGateway(), m_settings->routeMode()); });
} else if (m_settings->routeMode() == Settings::VpnAllExceptSites) { } else if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0/1"); IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0/1");
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "128.0.0.0/1"); IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "128.0.0.0/1");
IpcClient::Interface()->routeAddList(m_vpnProtocol->routeGateway(), QStringList() << remoteAddress()); IpcClient::Interface()->routeAddList(m_vpnProtocol->routeGateway(), QStringList() << remoteAddress());
addSitesRoutes(m_vpnProtocol->routeGateway(), m_settings->routeMode()); addSitesRoutes(m_vpnProtocol->routeGateway(), m_settings->routeMode());
}
} }
} else if (state == Vpn::ConnectionState::Error) { } else if (state == Vpn::ConnectionState::Error) {
@ -296,6 +298,7 @@ QJsonObject VpnConnection::createVpnConfiguration(int serverIndex, const ServerC
vpnConfiguration[config_key::hostName] = server.value(config_key::hostName).toString(); vpnConfiguration[config_key::hostName] = server.value(config_key::hostName).toString();
vpnConfiguration[config_key::description] = server.value(config_key::description).toString(); vpnConfiguration[config_key::description] = server.value(config_key::description).toString();
vpnConfiguration[config_key::configVersion] = server.value(config_key::configVersion).toInt();
// TODO: try to get hostName, port, description for 3rd party configs // TODO: try to get hostName, port, description for 3rd party configs
// vpnConfiguration[config_key::port] = ...; // vpnConfiguration[config_key::port] = ...;

View file

@ -7,15 +7,18 @@ usage() {
cat <<EOT cat <<EOT
Usage: Usage:
build_android [options] build_android [options] <artifact_types>
Build AmneziaVPN android client. By default, a signed Android App Bundle (AAB) is built. Build AmneziaVPN android client.
Options: Artifact types:
-d, --debug Build debug version -u, --aab Build Android App Bundle (AAB)
-a, --apk (<abi_list> | all) Build APKs for the specified ABIs or for all available ABIs -a, --apk (<abi_list> | all) Build APKs for the specified ABIs or for all available ABIs
Available ABIs: 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' Available ABIs: 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
<abi_list> - list of ABIs delimited by ';' <abi_list> - list of ABIs delimited by ';'
Options:
-d, --debug Build debug version
-b, --build-platform <platform> The SDK platform used for building the Java code of the application -b, --build-platform <platform> The SDK platform used for building the Java code of the application
By default, the latest available platform is used By default, the latest available platform is used
-m, --move Move the build result to the root of the build directory -m, --move Move the build result to the root of the build directory
@ -25,14 +28,14 @@ EOT
} }
BUILD_TYPE="release" BUILD_TYPE="release"
AAB=1
opts=$(getopt -l debug,apk:,build-platform:,move,help -o "da:b:mh" -- "$@") opts=$(getopt -l debug,aab,apk:,build-platform:,move,help -o "dua:b:mh" -- "$@")
eval set -- "$opts" eval set -- "$opts"
while true; do while true; do
case "$1" in case "$1" in
-d | --debug) BUILD_TYPE="debug"; shift;; -d | --debug) BUILD_TYPE="debug"; shift;;
-a | --apk) ABIS=$2; unset AAB; shift 2;; -u | --aab) AAB=1; shift;;
-a | --apk) ABIS=$2; shift 2;;
-b | --build-platform) ANDROID_BUILD_PLATFORM=$2; shift 2;; -b | --build-platform) ANDROID_BUILD_PLATFORM=$2; shift 2;;
-m | --move) MOVE_RESULT=1; shift;; -m | --move) MOVE_RESULT=1; shift;;
-h | --help) usage; exit 0;; -h | --help) usage; exit 0;;
@ -49,6 +52,11 @@ if [[ -v ABIS && \
exit 1 exit 1
fi fi
# At least one artifact type must be specified
if [[ ! (-v AAB || -v ABIS) ]]; then
usage; exit 0
fi
echo "Build script started..." echo "Build script started..."
PROJECT_DIR=$(pwd) PROJECT_DIR=$(pwd)
@ -137,7 +145,8 @@ gradle_opts=()
if [ -v AAB ]; then if [ -v AAB ]; then
gradle_opts+=(bundle"${BUILD_TYPE^}") gradle_opts+=(bundle"${BUILD_TYPE^}")
else fi
if [ -v ABIS ]; then
gradle_opts+=(assemble"${BUILD_TYPE^}") gradle_opts+=(assemble"${BUILD_TYPE^}")
fi fi
@ -151,7 +160,9 @@ if [[ -v CI || -v MOVE_RESULT ]]; then
if [ -v AAB ]; then if [ -v AAB ]; then
mv -u $OUT_APP_DIR/android-build/build/outputs/bundle/$BUILD_TYPE/AmneziaVPN-$BUILD_TYPE.aab \ mv -u $OUT_APP_DIR/android-build/build/outputs/bundle/$BUILD_TYPE/AmneziaVPN-$BUILD_TYPE.aab \
$PROJECT_DIR/deploy/build/ $PROJECT_DIR/deploy/build/
else fi
if [ -v ABIS ]; then
if [ "$ABIS" = "all" ]; then if [ "$ABIS" = "all" ]; then
ABIS="x86;x86_64;armeabi-v7a;arm64-v8a" ABIS="x86;x86_64;armeabi-v7a;arm64-v8a"
fi fi

View file

@ -83,6 +83,4 @@ ldd $CQTDEPLOYER_DIR/bin/binarycreator
cp -r $PROJECT_DIR/deploy/installer $BUILD_DIR cp -r $PROJECT_DIR/deploy/installer $BUILD_DIR
$CQTDEPLOYER_DIR/binarycreator.sh --offline-only -v -c $BUILD_DIR/installer/config/linux.xml -p $BUILD_DIR/installer/packages -f $PROJECT_DIR/deploy/AmneziaVPN_Linux_Installer $CQTDEPLOYER_DIR/binarycreator.sh --offline-only -v -c $BUILD_DIR/installer/config/linux.xml -p $BUILD_DIR/installer/packages -f $PROJECT_DIR/deploy/AmneziaVPN_Linux_Installer.bin