mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-21 02:01:03 +07:00
Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b45f609531 | |||
| ce01523a88 | |||
| c3805195af | |||
| 2ef267bc44 | |||
| 94bae4b859 | |||
| 425acc5f8b | |||
| bb87c0838d | |||
| 268adfb0a1 | |||
| c681611102 | |||
| 4fc2a23f49 | |||
| 23f4a6ec8e | |||
| 504862c2b8 | |||
| a22a9448ca | |||
| 862e83ddf5 | |||
| 8735eee662 | |||
| ff82cf5dc4 | |||
| 8648790583 | |||
| b881d92a80 | |||
| 7ad7f31e4d | |||
| 138e6f70a4 | |||
| 6f94f4646a | |||
| 4a01d2cf20 | |||
| 8948601caa | |||
| aa92ccd06d | |||
| 253ae75795 | |||
| 87cb5f620a | |||
| 46cd740a84 | |||
| 76e5039578 | |||
| c6b131aa4c | |||
| 5e72bf945c | |||
| eebf7eccec | |||
| 168c293bfe | |||
| aae3cdcac1 | |||
| 96566f04ee | |||
| fff15fffe2 | |||
| 4e5a03e7f1 | |||
| 7571bbc36e | |||
| db4a1a62e5 | |||
| 581773ce03 | |||
| 46058f614e | |||
| 9cab51fb00 | |||
| 918be16372 | |||
| 175477d31f | |||
| cd70b7e619 | |||
| 22011e263e | |||
| 88a2b9a07a | |||
| 248f487d4e | |||
| 51618fb882 | |||
| b83e74427e |
@@ -16,6 +16,7 @@ jobs:
|
|||||||
QT_VERSION: 6.6.2
|
QT_VERSION: 6.6.2
|
||||||
QIF_VERSION: 4.7
|
QIF_VERSION: 4.7
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install Qt'
|
- name: 'Install Qt'
|
||||||
@@ -82,6 +83,7 @@ jobs:
|
|||||||
QIF_VERSION: 4.7
|
QIF_VERSION: 4.7
|
||||||
BUILD_ARCH: 64
|
BUILD_ARCH: 64
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Get sources'
|
- name: 'Get sources'
|
||||||
@@ -144,6 +146,7 @@ jobs:
|
|||||||
CC: cc
|
CC: cc
|
||||||
CXX: c++
|
CXX: c++
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Setup xcode'
|
- name: 'Setup xcode'
|
||||||
@@ -178,7 +181,7 @@ jobs:
|
|||||||
- name: 'Install go'
|
- name: 'Install go'
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.20'
|
go-version: '1.22.1'
|
||||||
cache: false
|
cache: false
|
||||||
|
|
||||||
- name: 'Setup gomobile'
|
- name: 'Setup gomobile'
|
||||||
@@ -235,6 +238,7 @@ jobs:
|
|||||||
QT_VERSION: 6.4.3
|
QT_VERSION: 6.4.3
|
||||||
QIF_VERSION: 4.6
|
QIF_VERSION: 4.6
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Setup xcode'
|
- name: 'Setup xcode'
|
||||||
@@ -297,24 +301,25 @@ jobs:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
ANDROID_BUILD_PLATFORM: android-34
|
ANDROID_BUILD_PLATFORM: android-34
|
||||||
QT_VERSION: 6.6.2
|
QT_VERSION: 6.7.2
|
||||||
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
|
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install desktop Qt'
|
- name: 'Install desktop Qt'
|
||||||
uses: jurplel/install-qt-action@v3
|
uses: jurplel/install-qt-action@v4
|
||||||
with:
|
with:
|
||||||
version: ${{ env.QT_VERSION }}
|
version: ${{ env.QT_VERSION }}
|
||||||
host: 'linux'
|
host: 'linux'
|
||||||
target: 'desktop'
|
target: 'desktop'
|
||||||
arch: 'gcc_64'
|
arch: 'linux_gcc_64'
|
||||||
modules: ${{ env.QT_MODULES }}
|
modules: ${{ env.QT_MODULES }}
|
||||||
dir: ${{ runner.temp }}
|
dir: ${{ runner.temp }}
|
||||||
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
||||||
|
|
||||||
- name: 'Install android_x86_64 Qt'
|
- name: 'Install android_x86_64 Qt'
|
||||||
uses: jurplel/install-qt-action@v3
|
uses: jurplel/install-qt-action@v4
|
||||||
with:
|
with:
|
||||||
version: ${{ env.QT_VERSION }}
|
version: ${{ env.QT_VERSION }}
|
||||||
host: 'linux'
|
host: 'linux'
|
||||||
@@ -325,7 +330,7 @@ jobs:
|
|||||||
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
||||||
|
|
||||||
- name: 'Install android_x86 Qt'
|
- name: 'Install android_x86 Qt'
|
||||||
uses: jurplel/install-qt-action@v3
|
uses: jurplel/install-qt-action@v4
|
||||||
with:
|
with:
|
||||||
version: ${{ env.QT_VERSION }}
|
version: ${{ env.QT_VERSION }}
|
||||||
host: 'linux'
|
host: 'linux'
|
||||||
@@ -336,7 +341,7 @@ jobs:
|
|||||||
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
||||||
|
|
||||||
- name: 'Install android_armv7 Qt'
|
- name: 'Install android_armv7 Qt'
|
||||||
uses: jurplel/install-qt-action@v3
|
uses: jurplel/install-qt-action@v4
|
||||||
with:
|
with:
|
||||||
version: ${{ env.QT_VERSION }}
|
version: ${{ env.QT_VERSION }}
|
||||||
host: 'linux'
|
host: 'linux'
|
||||||
@@ -347,7 +352,7 @@ jobs:
|
|||||||
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
||||||
|
|
||||||
- name: 'Install android_arm64_v8a Qt'
|
- name: 'Install android_arm64_v8a Qt'
|
||||||
uses: jurplel/install-qt-action@v3
|
uses: jurplel/install-qt-action@v4
|
||||||
with:
|
with:
|
||||||
version: ${{ env.QT_VERSION }}
|
version: ${{ env.QT_VERSION }}
|
||||||
host: 'linux'
|
host: 'linux'
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ jobs:
|
|||||||
QT_VERSION: 6.4.1
|
QT_VERSION: 6.4.1
|
||||||
QIF_VERSION: 4.5
|
QIF_VERSION: 4.5
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install desktop Qt'
|
- name: 'Install desktop Qt'
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
|||||||
|
|
||||||
set(PROJECT AmneziaVPN)
|
set(PROJECT AmneziaVPN)
|
||||||
|
|
||||||
project(${PROJECT} VERSION 4.7.0.0
|
project(${PROJECT} VERSION 4.8.1.8
|
||||||
DESCRIPTION "AmneziaVPN"
|
DESCRIPTION "AmneziaVPN"
|
||||||
HOMEPAGE_URL "https://amnezia.org/"
|
HOMEPAGE_URL "https://amnezia.org/"
|
||||||
)
|
)
|
||||||
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
|
|||||||
set(RELEASE_DATE "${CURRENT_DATE}")
|
set(RELEASE_DATE "${CURRENT_DATE}")
|
||||||
|
|
||||||
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
|
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
|
||||||
set(APP_ANDROID_VERSION_CODE 57)
|
set(APP_ANDROID_VERSION_CODE 63)
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
set(MZ_PLATFORM_NAME "linux")
|
set(MZ_PLATFORM_NAME "linux")
|
||||||
|
|||||||
+1
-1
Submodule client/3rd-prebuilt updated: c38a587fcd...ba580dc5bd
Vendored
+1
-1
Submodule client/3rd/OpenVPNAdapter updated: dea6040996...7c821a8d5c
Vendored
+1
-1
Submodule client/3rd/qtkeychain updated: 74776e2a3e...7460df6a97
@@ -27,6 +27,9 @@ add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
|
|||||||
add_definitions(-DPROD_AGW_PUBLIC_KEY="$ENV{PROD_AGW_PUBLIC_KEY}")
|
add_definitions(-DPROD_AGW_PUBLIC_KEY="$ENV{PROD_AGW_PUBLIC_KEY}")
|
||||||
add_definitions(-DPROD_PROXY_STORAGE_KEY="$ENV{PROD_PROXY_STORAGE_KEY}")
|
add_definitions(-DPROD_PROXY_STORAGE_KEY="$ENV{PROD_PROXY_STORAGE_KEY}")
|
||||||
|
|
||||||
|
add_definitions(-DDEV_AGW_PUBLIC_KEY="$ENV{DEV_AGW_PUBLIC_KEY}")
|
||||||
|
add_definitions(-DDEV_AGW_ENDPOINT="$ENV{DEV_AGW_ENDPOINT}")
|
||||||
|
|
||||||
if(IOS)
|
if(IOS)
|
||||||
set(PACKAGES ${PACKAGES} Multimedia)
|
set(PACKAGES ${PACKAGES} Multimedia)
|
||||||
endif()
|
endif()
|
||||||
@@ -58,6 +61,7 @@ qt_add_executable(${PROJECT} MANUAL_FINALIZATION)
|
|||||||
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
||||||
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_interface.rep)
|
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_interface.rep)
|
||||||
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_interface.rep)
|
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_interface.rep)
|
||||||
|
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_tun2socks.rep)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt6_add_resources(QRC ${QRC} ${CMAKE_CURRENT_LIST_DIR}/resources.qrc)
|
qt6_add_resources(QRC ${QRC} ${CMAKE_CURRENT_LIST_DIR}/resources.qrc)
|
||||||
@@ -110,6 +114,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/cmake/3rdparty.cmake)
|
|||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_CURRENT_LIST_DIR}/../ipc
|
${CMAKE_CURRENT_LIST_DIR}/../ipc
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/../common/logger
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
@@ -131,7 +136,6 @@ set(HEADERS ${HEADERS}
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h
|
${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.h
|
${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/ui/pages.h
|
${CMAKE_CURRENT_LIST_DIR}/ui/pages.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/ui/property_helper.h
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.h
|
${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.h
|
${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.h
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/version.h
|
${CMAKE_CURRENT_BINARY_DIR}/version.h
|
||||||
@@ -140,6 +144,7 @@ set(HEADERS ${HEADERS}
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/serialization.h
|
${CMAKE_CURRENT_LIST_DIR}/core/serialization/serialization.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/transfer.h
|
${CMAKE_CURRENT_LIST_DIR}/core/serialization/transfer.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/core/enums/apiEnums.h
|
${CMAKE_CURRENT_LIST_DIR}/core/enums/apiEnums.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# Mozilla headres
|
# Mozilla headres
|
||||||
@@ -190,6 +195,7 @@ set(SOURCES ${SOURCES}
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/trojan.cpp
|
${CMAKE_CURRENT_LIST_DIR}/core/serialization/trojan.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess.cpp
|
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess_new.cpp
|
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess_new.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Mozilla sources
|
# Mozilla sources
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ void AmneziaApplication::init()
|
|||||||
bool enabled = m_settings->isSaveLogs();
|
bool enabled = m_settings->isSaveLogs();
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
if (!Logger::init()) {
|
if (!Logger::init(false)) {
|
||||||
qWarning() << "Initialization of debug subsystem failed";
|
qWarning() << "Initialization of debug subsystem failed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
<manifest
|
<manifest
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="org.amnezia.vpn"
|
|
||||||
android:versionName="-- %%INSERT_VERSION_NAME%% --"
|
android:versionName="-- %%INSERT_VERSION_NAME%% --"
|
||||||
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
|
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
@@ -46,7 +45,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:windowSoftInputMode="stateUnchanged|adjustResize"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -68,9 +67,6 @@
|
|||||||
android:name="android.app.lib_name"
|
android:name="android.app.lib_name"
|
||||||
android:value="-- %%INSERT_APP_LIB_NAME%% --" />
|
android:value="-- %%INSERT_APP_LIB_NAME%% --" />
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="android.app.extract_android_style"
|
|
||||||
android:value="minimal" />
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
@@ -88,6 +84,13 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/Translucent" />
|
android:theme="@style/Translucent" />
|
||||||
|
|
||||||
|
<activity android:name=".AuthActivity"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:taskAffinity=""
|
||||||
|
android:exported="false"
|
||||||
|
android:theme="@style/Translucent" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ImportConfigActivity"
|
android:name=".ImportConfigActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
|
|||||||
@@ -1,81 +1,21 @@
|
|||||||
package org.amnezia.vpn.protocol.awg
|
package org.amnezia.vpn.protocol.awg
|
||||||
|
|
||||||
import org.amnezia.vpn.protocol.wireguard.Wireguard
|
import org.amnezia.vpn.protocol.wireguard.Wireguard
|
||||||
|
import org.amnezia.vpn.protocol.wireguard.WireguardConfig
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
/**
|
|
||||||
* Config example:
|
|
||||||
* {
|
|
||||||
* "protocol": "awg",
|
|
||||||
* "description": "Server 1",
|
|
||||||
* "dns1": "1.1.1.1",
|
|
||||||
* "dns2": "1.0.0.1",
|
|
||||||
* "hostName": "100.100.100.0",
|
|
||||||
* "splitTunnelSites": [
|
|
||||||
* ],
|
|
||||||
* "splitTunnelType": 0,
|
|
||||||
* "awg_config_data": {
|
|
||||||
* "H1": "969537490",
|
|
||||||
* "H2": "481688153",
|
|
||||||
* "H3": "2049399200",
|
|
||||||
* "H4": "52029755",
|
|
||||||
* "Jc": "3",
|
|
||||||
* "Jmax": "1000",
|
|
||||||
* "Jmin": "50",
|
|
||||||
* "S1": "49",
|
|
||||||
* "S2": "60",
|
|
||||||
* "client_ip": "10.8.1.1",
|
|
||||||
* "hostName": "100.100.100.0",
|
|
||||||
* "port": 12345,
|
|
||||||
* "client_pub_key": "clientPublicKeyBase64",
|
|
||||||
* "client_priv_key": "privateKeyBase64",
|
|
||||||
* "psk_key": "presharedKeyBase64",
|
|
||||||
* "server_pub_key": "publicKeyBase64",
|
|
||||||
* "config": "[Interface]
|
|
||||||
* Address = 10.8.1.1/32
|
|
||||||
* DNS = 1.1.1.1, 1.0.0.1
|
|
||||||
* PrivateKey = privateKeyBase64
|
|
||||||
* Jc = 3
|
|
||||||
* Jmin = 50
|
|
||||||
* Jmax = 1000
|
|
||||||
* S1 = 49
|
|
||||||
* S2 = 60
|
|
||||||
* H1 = 969537490
|
|
||||||
* H2 = 481688153
|
|
||||||
* H3 = 2049399200
|
|
||||||
* H4 = 52029755
|
|
||||||
*
|
|
||||||
* [Peer]
|
|
||||||
* PublicKey = publicKeyBase64
|
|
||||||
* PresharedKey = presharedKeyBase64
|
|
||||||
* AllowedIPs = 0.0.0.0/0, ::/0
|
|
||||||
* Endpoint = 100.100.100.0:12345
|
|
||||||
* PersistentKeepalive = 25
|
|
||||||
* "
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Awg : Wireguard() {
|
class Awg : Wireguard() {
|
||||||
|
|
||||||
override val ifName: String = "awg0"
|
override val ifName: String = "awg0"
|
||||||
|
|
||||||
override fun parseConfig(config: JSONObject): AwgConfig {
|
override fun parseConfig(config: JSONObject): WireguardConfig {
|
||||||
val configDataJson = config.getJSONObject("awg_config_data")
|
val configData = config.getJSONObject("awg_config_data")
|
||||||
val configData = parseConfigData(configDataJson.getString("config"))
|
return WireguardConfig.build {
|
||||||
return AwgConfig.build {
|
setUseProtocolExtension(true)
|
||||||
configWireguard(configData, configDataJson)
|
configExtensionParameters(configData)
|
||||||
|
configWireguard(config, configData)
|
||||||
configSplitTunneling(config)
|
configSplitTunneling(config)
|
||||||
configAppSplitTunneling(config)
|
configAppSplitTunneling(config)
|
||||||
configData["Jc"]?.let { setJc(it.toInt()) }
|
|
||||||
configData["Jmin"]?.let { setJmin(it.toInt()) }
|
|
||||||
configData["Jmax"]?.let { setJmax(it.toInt()) }
|
|
||||||
configData["S1"]?.let { setS1(it.toInt()) }
|
|
||||||
configData["S2"]?.let { setS2(it.toInt()) }
|
|
||||||
configData["H1"]?.let { setH1(it.toLong()) }
|
|
||||||
configData["H2"]?.let { setH2(it.toLong()) }
|
|
||||||
configData["H3"]?.let { setH3(it.toLong()) }
|
|
||||||
configData["H4"]?.let { setH4(it.toLong()) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
package org.amnezia.vpn.protocol.awg
|
|
||||||
|
|
||||||
import org.amnezia.vpn.protocol.BadConfigException
|
|
||||||
import org.amnezia.vpn.protocol.wireguard.WireguardConfig
|
|
||||||
|
|
||||||
class AwgConfig private constructor(
|
|
||||||
wireguardConfigBuilder: WireguardConfig.Builder,
|
|
||||||
val jc: Int,
|
|
||||||
val jmin: Int,
|
|
||||||
val jmax: Int,
|
|
||||||
val s1: Int,
|
|
||||||
val s2: Int,
|
|
||||||
val h1: Long,
|
|
||||||
val h2: Long,
|
|
||||||
val h3: Long,
|
|
||||||
val h4: Long
|
|
||||||
) : WireguardConfig(wireguardConfigBuilder) {
|
|
||||||
|
|
||||||
private constructor(builder: Builder) : this(
|
|
||||||
builder,
|
|
||||||
builder.jc,
|
|
||||||
builder.jmin,
|
|
||||||
builder.jmax,
|
|
||||||
builder.s1,
|
|
||||||
builder.s2,
|
|
||||||
builder.h1,
|
|
||||||
builder.h2,
|
|
||||||
builder.h3,
|
|
||||||
builder.h4
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun appendDeviceLine(sb: StringBuilder) = with(sb) {
|
|
||||||
super.appendDeviceLine(this)
|
|
||||||
appendLine("jc=$jc")
|
|
||||||
appendLine("jmin=$jmin")
|
|
||||||
appendLine("jmax=$jmax")
|
|
||||||
appendLine("s1=$s1")
|
|
||||||
appendLine("s2=$s2")
|
|
||||||
appendLine("h1=$h1")
|
|
||||||
appendLine("h2=$h2")
|
|
||||||
appendLine("h3=$h3")
|
|
||||||
appendLine("h4=$h4")
|
|
||||||
}
|
|
||||||
|
|
||||||
class Builder : WireguardConfig.Builder() {
|
|
||||||
|
|
||||||
private var _jc: Int? = null
|
|
||||||
internal var jc: Int
|
|
||||||
get() = _jc ?: throw BadConfigException("AWG: parameter jc is undefined")
|
|
||||||
private set(value) { _jc = value }
|
|
||||||
|
|
||||||
private var _jmin: Int? = null
|
|
||||||
internal var jmin: Int
|
|
||||||
get() = _jmin ?: throw BadConfigException("AWG: parameter jmin is undefined")
|
|
||||||
private set(value) { _jmin = value }
|
|
||||||
|
|
||||||
private var _jmax: Int? = null
|
|
||||||
internal var jmax: Int
|
|
||||||
get() = _jmax ?: throw BadConfigException("AWG: parameter jmax is undefined")
|
|
||||||
private set(value) { _jmax = value }
|
|
||||||
|
|
||||||
private var _s1: Int? = null
|
|
||||||
internal var s1: Int
|
|
||||||
get() = _s1 ?: throw BadConfigException("AWG: parameter s1 is undefined")
|
|
||||||
private set(value) { _s1 = value }
|
|
||||||
|
|
||||||
private var _s2: Int? = null
|
|
||||||
internal var s2: Int
|
|
||||||
get() = _s2 ?: throw BadConfigException("AWG: parameter s2 is undefined")
|
|
||||||
private set(value) { _s2 = value }
|
|
||||||
|
|
||||||
private var _h1: Long? = null
|
|
||||||
internal var h1: Long
|
|
||||||
get() = _h1 ?: throw BadConfigException("AWG: parameter h1 is undefined")
|
|
||||||
private set(value) { _h1 = value }
|
|
||||||
|
|
||||||
private var _h2: Long? = null
|
|
||||||
internal var h2: Long
|
|
||||||
get() = _h2 ?: throw BadConfigException("AWG: parameter h2 is undefined")
|
|
||||||
private set(value) { _h2 = value }
|
|
||||||
|
|
||||||
private var _h3: Long? = null
|
|
||||||
internal var h3: Long
|
|
||||||
get() = _h3 ?: throw BadConfigException("AWG: parameter h3 is undefined")
|
|
||||||
private set(value) { _h3 = value }
|
|
||||||
|
|
||||||
private var _h4: Long? = null
|
|
||||||
internal var h4: Long
|
|
||||||
get() = _h4 ?: throw BadConfigException("AWG: parameter h4 is undefined")
|
|
||||||
private set(value) { _h4 = value }
|
|
||||||
|
|
||||||
fun setJc(jc: Int) = apply { this.jc = jc }
|
|
||||||
fun setJmin(jmin: Int) = apply { this.jmin = jmin }
|
|
||||||
fun setJmax(jmax: Int) = apply { this.jmax = jmax }
|
|
||||||
fun setS1(s1: Int) = apply { this.s1 = s1 }
|
|
||||||
fun setS2(s2: Int) = apply { this.s2 = s2 }
|
|
||||||
fun setH1(h1: Long) = apply { this.h1 = h1 }
|
|
||||||
fun setH2(h2: Long) = apply { this.h2 = h2 }
|
|
||||||
fun setH3(h3: Long) = apply { this.h3 = h3 }
|
|
||||||
fun setH4(h4: Long) = apply { this.h4 = h4 }
|
|
||||||
|
|
||||||
override fun build(): AwgConfig = configBuild().run { AwgConfig(this@Builder) }
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
inline fun build(block: Builder.() -> Unit): AwgConfig = Builder().apply(block).build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,3 +3,6 @@
|
|||||||
// android.bundle.enableUncompressedNativeLibs is deprecated
|
// android.bundle.enableUncompressedNativeLibs is deprecated
|
||||||
// disable adding gradle property android.bundle.enableUncompressedNativeLibs by androiddeployqt
|
// disable adding gradle property android.bundle.enableUncompressedNativeLibs by androiddeployqt
|
||||||
useLegacyPackaging
|
useLegacyPackaging
|
||||||
|
|
||||||
|
// package name for androiddeployqt
|
||||||
|
namespace = "org.amnezia.vpn"
|
||||||
|
|||||||
@@ -115,9 +115,11 @@ dependencies {
|
|||||||
implementation(project(":xray"))
|
implementation(project(":xray"))
|
||||||
implementation(libs.androidx.core)
|
implementation(libs.androidx.core)
|
||||||
implementation(libs.androidx.activity)
|
implementation(libs.androidx.activity)
|
||||||
|
implementation(libs.androidx.fragment)
|
||||||
implementation(libs.kotlinx.coroutines)
|
implementation(libs.kotlinx.coroutines)
|
||||||
implementation(libs.kotlinx.serialization.protobuf)
|
implementation(libs.kotlinx.serialization.protobuf)
|
||||||
implementation(libs.bundles.androidx.camera)
|
implementation(libs.bundles.androidx.camera)
|
||||||
implementation(libs.google.mlkit)
|
implementation(libs.google.mlkit)
|
||||||
implementation(libs.androidx.datastore)
|
implementation(libs.androidx.datastore)
|
||||||
|
implementation(libs.androidx.biometric)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,40 +3,16 @@ package org.amnezia.vpn.protocol.cloak
|
|||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import net.openvpn.ovpn3.ClientAPI_Config
|
import net.openvpn.ovpn3.ClientAPI_Config
|
||||||
import org.amnezia.vpn.protocol.openvpn.OpenVpn
|
import org.amnezia.vpn.protocol.openvpn.OpenVpn
|
||||||
|
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
/**
|
|
||||||
* Config Example:
|
|
||||||
* {
|
|
||||||
* "protocol": "cloak",
|
|
||||||
* "description": "Server 1",
|
|
||||||
* "dns1": "1.1.1.1",
|
|
||||||
* "dns2": "1.0.0.1",
|
|
||||||
* "hostName": "100.100.100.0",
|
|
||||||
* "splitTunnelSites": [
|
|
||||||
* ],
|
|
||||||
* "splitTunnelType": 0,
|
|
||||||
* "openvpn_config_data": {
|
|
||||||
* "config": "openVpnConfig"
|
|
||||||
* }
|
|
||||||
* "cloak_config_data": {
|
|
||||||
* "BrowserSig": "chrome",
|
|
||||||
* "EncryptionMethod": "aes-gcm",
|
|
||||||
* "NumConn": 1,
|
|
||||||
* "ProxyMethod": "openvpn",
|
|
||||||
* "PublicKey": "PublicKey=",
|
|
||||||
* "RemoteHost": "100.100.100.0",
|
|
||||||
* "RemotePort": "443",
|
|
||||||
* "ServerName": "servername",
|
|
||||||
* "StreamTimeout": 300,
|
|
||||||
* "Transport": "direct",
|
|
||||||
* "UID": "UID="
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Cloak : OpenVpn() {
|
class Cloak : OpenVpn() {
|
||||||
|
|
||||||
|
override fun internalInit() {
|
||||||
|
super.internalInit()
|
||||||
|
if (!isInitialized) loadSharedLibrary(context, "ck-ovpn-plugin")
|
||||||
|
}
|
||||||
|
|
||||||
override fun parseConfig(config: JSONObject): ClientAPI_Config {
|
override fun parseConfig(config: JSONObject): ClientAPI_Config {
|
||||||
val openVpnConfig = ClientAPI_Config()
|
val openVpnConfig = ClientAPI_Config()
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,28 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.2.0"
|
agp = "8.5.2"
|
||||||
kotlin = "1.9.20"
|
kotlin = "1.9.24"
|
||||||
androidx-core = "1.12.0"
|
androidx-core = "1.13.1"
|
||||||
androidx-activity = "1.8.1"
|
androidx-activity = "1.9.1"
|
||||||
androidx-annotation = "1.7.0"
|
androidx-annotation = "1.8.2"
|
||||||
androidx-camera = "1.3.0"
|
androidx-biometric = "1.2.0-alpha05"
|
||||||
|
androidx-camera = "1.3.4"
|
||||||
|
androidx-fragment = "1.8.2"
|
||||||
androidx-security-crypto = "1.1.0-alpha06"
|
androidx-security-crypto = "1.1.0-alpha06"
|
||||||
androidx-datastore = "1.1.0-beta01"
|
androidx-datastore = "1.1.1"
|
||||||
kotlinx-coroutines = "1.7.3"
|
kotlinx-coroutines = "1.8.1"
|
||||||
kotlinx-serialization = "1.6.3"
|
kotlinx-serialization = "1.6.3"
|
||||||
google-mlkit = "17.2.0"
|
google-mlkit = "17.3.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
|
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
|
||||||
androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" }
|
androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" }
|
||||||
androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "androidx-annotation" }
|
androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "androidx-annotation" }
|
||||||
|
androidx-biometric = { module = "androidx.biometric:biometric-ktx", version.ref = "androidx-biometric" }
|
||||||
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "androidx-camera" }
|
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "androidx-camera" }
|
||||||
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "androidx-camera" }
|
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "androidx-camera" }
|
||||||
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "androidx-camera" }
|
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "androidx-camera" }
|
||||||
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "androidx-camera" }
|
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "androidx-camera" }
|
||||||
|
androidx-fragment = { module = "androidx.fragment:fragment-ktx", version.ref = "androidx-fragment" }
|
||||||
androidx-security-crypto = { module = "androidx.security:security-crypto-ktx", version.ref = "androidx-security-crypto" }
|
androidx-security-crypto = { module = "androidx.security:security-crypto-ktx", version.ref = "androidx-security-crypto" }
|
||||||
androidx-datastore = { module = "androidx.datastore:datastore-preferences", version.ref = "androidx-datastore" }
|
androidx-datastore = { module = "androidx.datastore:datastore-preferences", version.ref = "androidx-datastore" }
|
||||||
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
|
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
|
||||||
|
|||||||
Binary file not shown.
+1
-3
@@ -1,7 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
|
||||||
networkTimeout=10000
|
|
||||||
validateDistributionUrl=true
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
Vendored
+5
-2
@@ -15,6 +15,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@@ -84,7 +86,8 @@ done
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||||
|
' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
|||||||
Vendored
+12
-10
@@ -13,6 +13,8 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
|||||||
@@ -11,28 +11,12 @@ import org.amnezia.vpn.protocol.Protocol
|
|||||||
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
|
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
|
||||||
import org.amnezia.vpn.protocol.Statistics
|
import org.amnezia.vpn.protocol.Statistics
|
||||||
import org.amnezia.vpn.protocol.VpnStartException
|
import org.amnezia.vpn.protocol.VpnStartException
|
||||||
|
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
|
||||||
import org.amnezia.vpn.util.net.InetNetwork
|
import org.amnezia.vpn.util.net.InetNetwork
|
||||||
import org.amnezia.vpn.util.net.getLocalNetworks
|
import org.amnezia.vpn.util.net.getLocalNetworks
|
||||||
import org.amnezia.vpn.util.net.parseInetAddress
|
import org.amnezia.vpn.util.net.parseInetAddress
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
/**
|
|
||||||
* Config Example:
|
|
||||||
* {
|
|
||||||
* "protocol": "openvpn",
|
|
||||||
* "description": "Server 1",
|
|
||||||
* "dns1": "1.1.1.1",
|
|
||||||
* "dns2": "1.0.0.1",
|
|
||||||
* "hostName": "100.100.100.0",
|
|
||||||
* "splitTunnelSites": [
|
|
||||||
* ],
|
|
||||||
* "splitTunnelType": 0,
|
|
||||||
* "openvpn_config_data": {
|
|
||||||
* "config": "openVpnConfig"
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
open class OpenVpn : Protocol() {
|
open class OpenVpn : Protocol() {
|
||||||
|
|
||||||
private var openVpnClient: OpenVpnClient? = null
|
private var openVpnClient: OpenVpnClient? = null
|
||||||
@@ -51,14 +35,17 @@ open class OpenVpn : Protocol() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun internalInit() {
|
override fun internalInit() {
|
||||||
if (!isInitialized) loadSharedLibrary(context, "ovpn3")
|
if (!isInitialized) {
|
||||||
|
loadSharedLibrary(context, "ovpn3")
|
||||||
|
loadSharedLibrary(context, "ovpnutil")
|
||||||
|
}
|
||||||
if (this::scope.isInitialized) {
|
if (this::scope.isInitialized) {
|
||||||
scope.cancel()
|
scope.cancel()
|
||||||
}
|
}
|
||||||
scope = CoroutineScope(Dispatchers.IO)
|
scope = CoroutineScope(Dispatchers.IO)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
override suspend fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
||||||
val configBuilder = OpenVpnConfig.Builder()
|
val configBuilder = OpenVpnConfig.Builder()
|
||||||
|
|
||||||
openVpnClient = OpenVpnClient(
|
openVpnClient = OpenVpnClient(
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.amnezia.vpn.protocol
|
|||||||
|
|
||||||
sealed class ProtocolException(message: String? = null, cause: Throwable? = null) : Exception(message, cause)
|
sealed class ProtocolException(message: String? = null, cause: Throwable? = null) : Exception(message, cause)
|
||||||
|
|
||||||
class LoadLibraryException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
|
|
||||||
class BadConfigException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
|
class BadConfigException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
|
||||||
|
|
||||||
class VpnStartException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
|
class VpnStartException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ abstract class Protocol {
|
|||||||
|
|
||||||
protected abstract fun internalInit()
|
protected abstract fun internalInit()
|
||||||
|
|
||||||
abstract fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean)
|
abstract suspend fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean)
|
||||||
|
|
||||||
abstract fun stopVpn()
|
abstract fun stopVpn()
|
||||||
|
|
||||||
@@ -158,60 +158,6 @@ abstract class Protocol {
|
|||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||||
vpnBuilder.setMetered(false)
|
vpnBuilder.setMetered(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private fun extractLibrary(context: Context, libraryName: String, destination: File): Boolean {
|
|
||||||
Log.d(TAG, "Extracting library: $libraryName")
|
|
||||||
val apks = hashSetOf<String>()
|
|
||||||
context.applicationInfo.run {
|
|
||||||
sourceDir?.let { apks += it }
|
|
||||||
splitSourceDirs?.let { apks += it }
|
|
||||||
}
|
|
||||||
for (abi in Build.SUPPORTED_ABIS) {
|
|
||||||
for (apk in apks) {
|
|
||||||
ZipFile(File(apk), ZipFile.OPEN_READ).use { zipFile ->
|
|
||||||
val mappedName = System.mapLibraryName(libraryName)
|
|
||||||
val libraryZipPath = listOf("lib", abi, mappedName).joinToString(File.separator)
|
|
||||||
val zipEntry = zipFile.getEntry(libraryZipPath)
|
|
||||||
zipEntry?.let {
|
|
||||||
Log.d(TAG, "Extracting apk:/$libraryZipPath to ${destination.absolutePath}")
|
|
||||||
FileOutputStream(destination).use { outStream ->
|
|
||||||
zipFile.getInputStream(zipEntry).use { inStream ->
|
|
||||||
inStream.copyTo(outStream, 32 * 1024)
|
|
||||||
outStream.fd.sync()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("UnsafeDynamicallyLoadedCode")
|
|
||||||
fun loadSharedLibrary(context: Context, libraryName: String) {
|
|
||||||
Log.d(TAG, "Loading library: $libraryName")
|
|
||||||
try {
|
|
||||||
System.loadLibrary(libraryName)
|
|
||||||
return
|
|
||||||
} catch (_: UnsatisfiedLinkError) {
|
|
||||||
Log.d(TAG, "Failed to load library, try to extract it from apk")
|
|
||||||
}
|
|
||||||
var tempFile: File? = null
|
|
||||||
try {
|
|
||||||
tempFile = File.createTempFile("lib", ".so", context.codeCacheDir)
|
|
||||||
if (extractLibrary(context, libraryName, tempFile)) {
|
|
||||||
System.load(tempFile.absolutePath)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
throw LoadLibraryException("Failed to load library apk: $libraryName", e)
|
|
||||||
} finally {
|
|
||||||
tempFile?.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun VpnService.Builder.addAddress(addr: InetNetwork) = addAddress(addr.address, addr.mask)
|
private fun VpnService.Builder.addAddress(addr: InetNetwork) = addAddress(addr.address, addr.mask)
|
||||||
|
|||||||
@@ -21,5 +21,5 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(fileTree(mapOf("dir" to "../libs", "include" to listOf("*.jar"))))
|
api(fileTree(mapOf("dir" to "../libs", "include" to listOf("*.jar"))))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
<!-- DO NOT EDIT THIS: This file is populated automatically by the deployment tool. -->
|
<!-- DO NOT EDIT THIS: This file is populated automatically by the deployment tool. -->
|
||||||
|
|
||||||
<array name="bundled_libs">
|
<array name="bundled_libs">
|
||||||
<!-- %%INSERT_EXTRA_LIBS%% -->
|
|
||||||
</array>
|
</array>
|
||||||
|
|
||||||
<array name="qt_libs">
|
<array name="qt_libs">
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<color name="black">#FF0E0E11</color>
|
||||||
<style name="NoActionBar">
|
<style name="NoActionBar">
|
||||||
|
<item name="android:windowBackground">@color/black</item>
|
||||||
|
<item name="android:colorBackground">@color/black</item>
|
||||||
<item name="android:windowActionBar">false</item>
|
<item name="android:windowActionBar">false</item>
|
||||||
<item name="android:windowNoTitle">true</item>
|
<item name="android:windowNoTitle">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ dependencyResolutionManagement {
|
|||||||
includeBuild("./gradle/plugins")
|
includeBuild("./gradle/plugins")
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.settings") version "8.2.0"
|
id("com.android.settings") version "8.5.2"
|
||||||
id("settings-property-delegate")
|
id("settings-property-delegate")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import kotlinx.coroutines.withContext
|
|||||||
import org.amnezia.vpn.protocol.getStatistics
|
import org.amnezia.vpn.protocol.getStatistics
|
||||||
import org.amnezia.vpn.protocol.getStatus
|
import org.amnezia.vpn.protocol.getStatus
|
||||||
import org.amnezia.vpn.qt.QtAndroidController
|
import org.amnezia.vpn.qt.QtAndroidController
|
||||||
|
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
|
||||||
import org.amnezia.vpn.util.Log
|
import org.amnezia.vpn.util.Log
|
||||||
import org.amnezia.vpn.util.Prefs
|
import org.amnezia.vpn.util.Prefs
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
@@ -158,6 +159,11 @@ class AmneziaActivity : QtActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
Log.d(TAG, "Create Amnezia activity: $intent")
|
Log.d(TAG, "Create Amnezia activity: $intent")
|
||||||
|
loadLibs()
|
||||||
|
window.apply {
|
||||||
|
addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
||||||
|
statusBarColor = getColor(R.color.black)
|
||||||
|
}
|
||||||
mainScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
mainScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
||||||
val proto = mainScope.async(Dispatchers.IO) {
|
val proto = mainScope.async(Dispatchers.IO) {
|
||||||
VpnStateStore.getVpnState().vpnProto
|
VpnStateStore.getVpnState().vpnProto
|
||||||
@@ -175,6 +181,17 @@ class AmneziaActivity : QtActivity() {
|
|||||||
runBlocking { vpnProto = proto.await() }
|
runBlocking { vpnProto = proto.await() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadLibs() {
|
||||||
|
listOf(
|
||||||
|
"rsapss",
|
||||||
|
"crypto_3",
|
||||||
|
"ssl_3",
|
||||||
|
"ssh"
|
||||||
|
).forEach {
|
||||||
|
loadSharedLibrary(this.applicationContext, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun registerBroadcastReceivers() {
|
private fun registerBroadcastReceivers() {
|
||||||
notificationStateReceiver = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
notificationStateReceiver = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
registerBroadcastReceiver(
|
registerBroadcastReceiver(
|
||||||
@@ -610,6 +627,14 @@ class AmneziaActivity : QtActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
fun setNavigationBarColor(color: Int) {
|
||||||
|
Log.v(TAG, "Change navigation bar color: ${"#%08X".format(color)}")
|
||||||
|
mainScope.launch {
|
||||||
|
window.navigationBarColor = color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
fun minimizeApp() {
|
fun minimizeApp() {
|
||||||
Log.v(TAG, "Minimize application")
|
Log.v(TAG, "Minimize application")
|
||||||
@@ -684,6 +709,17 @@ class AmneziaActivity : QtActivity() {
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
fun requestAuthentication() {
|
||||||
|
Log.v(TAG, "Request authentication")
|
||||||
|
mainScope.launch {
|
||||||
|
qtInitialized.await()
|
||||||
|
Intent(this@AmneziaActivity, AuthActivity::class.java).also {
|
||||||
|
startActivity(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utils methods
|
* Utils methods
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import kotlinx.coroutines.Job
|
|||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.TimeoutCancellationException
|
import kotlinx.coroutines.TimeoutCancellationException
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.cancelAndJoin
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
@@ -39,7 +40,6 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withTimeout
|
import kotlinx.coroutines.withTimeout
|
||||||
import org.amnezia.vpn.protocol.BadConfigException
|
import org.amnezia.vpn.protocol.BadConfigException
|
||||||
import org.amnezia.vpn.protocol.LoadLibraryException
|
|
||||||
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
|
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
|
||||||
import org.amnezia.vpn.protocol.ProtocolState.CONNECTING
|
import org.amnezia.vpn.protocol.ProtocolState.CONNECTING
|
||||||
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
|
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
|
||||||
@@ -49,6 +49,7 @@ import org.amnezia.vpn.protocol.ProtocolState.UNKNOWN
|
|||||||
import org.amnezia.vpn.protocol.VpnException
|
import org.amnezia.vpn.protocol.VpnException
|
||||||
import org.amnezia.vpn.protocol.VpnStartException
|
import org.amnezia.vpn.protocol.VpnStartException
|
||||||
import org.amnezia.vpn.protocol.putStatus
|
import org.amnezia.vpn.protocol.putStatus
|
||||||
|
import org.amnezia.vpn.util.LoadLibraryException
|
||||||
import org.amnezia.vpn.util.Log
|
import org.amnezia.vpn.util.Log
|
||||||
import org.amnezia.vpn.util.Prefs
|
import org.amnezia.vpn.util.Prefs
|
||||||
import org.amnezia.vpn.util.net.NetworkState
|
import org.amnezia.vpn.util.net.NetworkState
|
||||||
@@ -111,6 +112,10 @@ open class AmneziaVpnService : VpnService() {
|
|||||||
get() = clientMessengers.any { it.value.name == ACTIVITY_MESSENGER_NAME }
|
get() = clientMessengers.any { it.value.name == ACTIVITY_MESSENGER_NAME }
|
||||||
|
|
||||||
private val connectionExceptionHandler = CoroutineExceptionHandler { _, e ->
|
private val connectionExceptionHandler = CoroutineExceptionHandler { _, e ->
|
||||||
|
connectionJob?.cancel()
|
||||||
|
connectionJob = null
|
||||||
|
disconnectionJob?.cancel()
|
||||||
|
disconnectionJob = null
|
||||||
protocolState.value = DISCONNECTED
|
protocolState.value = DISCONNECTED
|
||||||
when (e) {
|
when (e) {
|
||||||
is IllegalArgumentException,
|
is IllegalArgumentException,
|
||||||
@@ -531,7 +536,7 @@ open class AmneziaVpnService : VpnService() {
|
|||||||
protocolState.value = DISCONNECTING
|
protocolState.value = DISCONNECTING
|
||||||
|
|
||||||
disconnectionJob = connectionScope.launch {
|
disconnectionJob = connectionScope.launch {
|
||||||
connectionJob?.join()
|
connectionJob?.cancelAndJoin()
|
||||||
connectionJob = null
|
connectionJob = null
|
||||||
|
|
||||||
vpnProto?.protocol?.stopVpn()
|
vpnProto?.protocol?.stopVpn()
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package org.amnezia.vpn
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.biometric.BiometricManager
|
||||||
|
import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG
|
||||||
|
import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||||
|
import androidx.biometric.BiometricPrompt
|
||||||
|
import androidx.biometric.BiometricPrompt.AuthenticationResult
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import org.amnezia.vpn.qt.QtAndroidController
|
||||||
|
import org.amnezia.vpn.util.Log
|
||||||
|
|
||||||
|
private const val TAG = "AuthActivity"
|
||||||
|
|
||||||
|
private const val AUTHENTICATORS = BIOMETRIC_STRONG or DEVICE_CREDENTIAL
|
||||||
|
|
||||||
|
class AuthActivity : FragmentActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
val biometricManager = BiometricManager.from(applicationContext)
|
||||||
|
when (biometricManager.canAuthenticate(AUTHENTICATORS)) {
|
||||||
|
BiometricManager.BIOMETRIC_SUCCESS -> {
|
||||||
|
showBiometricPrompt(biometricManager)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> {
|
||||||
|
Log.w(TAG, "Unknown biometric status")
|
||||||
|
showBiometricPrompt(biometricManager)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> {
|
||||||
|
Log.e(TAG, "The specified options are incompatible with the current Android " +
|
||||||
|
"version ${Build.VERSION.SDK_INT}")
|
||||||
|
}
|
||||||
|
|
||||||
|
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> {
|
||||||
|
Log.w(TAG, "The hardware is unavailable")
|
||||||
|
}
|
||||||
|
|
||||||
|
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> {
|
||||||
|
Log.w(TAG, "No biometric or device credential is enrolled")
|
||||||
|
}
|
||||||
|
|
||||||
|
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> {
|
||||||
|
Log.w(TAG, "There is no suitable hardware")
|
||||||
|
}
|
||||||
|
|
||||||
|
BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> {
|
||||||
|
Log.w(TAG, "A security vulnerability has been discovered with one or " +
|
||||||
|
"more hardware sensors")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QtAndroidController.onAuthResult(true)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showBiometricPrompt(biometricManager: BiometricManager) {
|
||||||
|
val executor = ContextCompat.getMainExecutor(applicationContext)
|
||||||
|
val biometricPrompt = BiometricPrompt(this, executor,
|
||||||
|
object : BiometricPrompt.AuthenticationCallback() {
|
||||||
|
override fun onAuthenticationSucceeded(result: AuthenticationResult) {
|
||||||
|
super.onAuthenticationSucceeded(result)
|
||||||
|
Log.d(TAG, "Authentication succeeded")
|
||||||
|
QtAndroidController.onAuthResult(true)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationFailed() {
|
||||||
|
super.onAuthenticationFailed()
|
||||||
|
Log.w(TAG, "Authentication failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||||
|
super.onAuthenticationError(errorCode, errString)
|
||||||
|
Log.e(TAG, "Authentication error $errorCode: $errString")
|
||||||
|
QtAndroidController.onAuthResult(false)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val promptInfo = BiometricPrompt.PromptInfo.Builder()
|
||||||
|
.setAllowedAuthenticators(AUTHENTICATORS)
|
||||||
|
.setTitle("AmneziaVPN")
|
||||||
|
.setSubtitle(biometricManager.getStrings(AUTHENTICATORS)?.promptMessage)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
biometricPrompt.authenticate(promptInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package org.amnezia.vpn;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.app.KeyguardManager;
|
|
||||||
import android.content.Intent;
|
|
||||||
import org.qtproject.qt.android.bindings.QtActivity;
|
|
||||||
|
|
||||||
|
|
||||||
import static android.content.Context.KEYGUARD_SERVICE;
|
|
||||||
|
|
||||||
public class AuthHelper extends QtActivity {
|
|
||||||
|
|
||||||
static final String TAG = "AuthHelper";
|
|
||||||
|
|
||||||
public static Intent getAuthIntent(Context context) {
|
|
||||||
KeyguardManager mKeyguardManager = (KeyguardManager)context.getSystemService(KEYGUARD_SERVICE);
|
|
||||||
if (mKeyguardManager.isDeviceSecure()) {
|
|
||||||
return mKeyguardManager.createConfirmDeviceCredentialIntent(null, null);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -33,10 +33,10 @@ class ImportConfigActivity : ComponentActivity() {
|
|||||||
intent?.let(::readConfig)
|
intent?.let(::readConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent?) {
|
override fun onNewIntent(intent: Intent) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
Log.d(TAG, "onNewIntent: $intent")
|
Log.d(TAG, "onNewIntent: $intent")
|
||||||
intent?.let(::readConfig)
|
intent.let(::readConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readConfig(intent: Intent) {
|
private fun readConfig(intent: Intent) {
|
||||||
|
|||||||
@@ -25,5 +25,7 @@ object QtAndroidController {
|
|||||||
|
|
||||||
external fun onConfigImported(data: String)
|
external fun onConfigImported(data: String)
|
||||||
|
|
||||||
|
external fun onAuthResult(result: Boolean)
|
||||||
|
|
||||||
external fun decodeQrCode(data: String): Boolean
|
external fun decodeQrCode(data: String): Boolean
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package org.amnezia.vpn.util
|
||||||
|
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
inline fun <reified T> JSONArray.asSequence(): Sequence<T> =
|
||||||
|
(0..<length()).asSequence().map { get(it) as T }
|
||||||
|
|
||||||
|
fun JSONObject.optStringOrNull(name: String) = optString(name).ifEmpty { null }
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package org.amnezia.vpn.util
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.util.zip.ZipFile
|
||||||
|
|
||||||
|
private const val TAG = "LibraryLoader"
|
||||||
|
|
||||||
|
object LibraryLoader {
|
||||||
|
private fun extractLibrary(context: Context, libraryName: String, destination: File): Boolean {
|
||||||
|
Log.d(TAG, "Extracting library: $libraryName")
|
||||||
|
val apks = hashSetOf<String>()
|
||||||
|
context.applicationInfo.run {
|
||||||
|
sourceDir?.let { apks += it }
|
||||||
|
splitSourceDirs?.let { apks += it }
|
||||||
|
}
|
||||||
|
for (abi in Build.SUPPORTED_ABIS) {
|
||||||
|
for (apk in apks) {
|
||||||
|
ZipFile(File(apk), ZipFile.OPEN_READ).use { zipFile ->
|
||||||
|
val mappedName = System.mapLibraryName(libraryName)
|
||||||
|
val libraryZipPath = listOf("lib", abi, mappedName).joinToString(File.separator)
|
||||||
|
val zipEntry = zipFile.getEntry(libraryZipPath)
|
||||||
|
zipEntry?.let {
|
||||||
|
Log.d(TAG, "Extracting apk:/$libraryZipPath to ${destination.absolutePath}")
|
||||||
|
FileOutputStream(destination).use { outStream ->
|
||||||
|
zipFile.getInputStream(zipEntry).use { inStream ->
|
||||||
|
inStream.copyTo(outStream, 32 * 1024)
|
||||||
|
outStream.fd.sync()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeDynamicallyLoadedCode")
|
||||||
|
fun loadSharedLibrary(context: Context, libraryName: String) {
|
||||||
|
Log.d(TAG, "Loading library: $libraryName")
|
||||||
|
try {
|
||||||
|
System.loadLibrary(libraryName)
|
||||||
|
return
|
||||||
|
} catch (_: UnsatisfiedLinkError) {
|
||||||
|
Log.d(TAG, "Failed to load library, try to extract it from apk")
|
||||||
|
}
|
||||||
|
var tempFile: File? = null
|
||||||
|
try {
|
||||||
|
tempFile = File.createTempFile("lib", ".so", context.codeCacheDir)
|
||||||
|
if (extractLibrary(context, libraryName, tempFile)) {
|
||||||
|
System.load(tempFile.absolutePath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
throw LoadLibraryException("Failed to load library apk: $libraryName", e)
|
||||||
|
} finally {
|
||||||
|
tempFile?.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadLibraryException(message: String? = null, cause: Throwable? = null) : Exception(message, cause)
|
||||||
@@ -88,7 +88,7 @@ class NetworkState(
|
|||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
connectivityManager.registerBestMatchingNetworkCallback(networkRequest, networkCallback, handler)
|
connectivityManager.registerBestMatchingNetworkCallback(networkRequest, networkCallback, handler)
|
||||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val numberAttempts = 3
|
val numberAttempts = 300
|
||||||
var attemptCount = 0
|
var attemptCount = 0
|
||||||
while(true) {
|
while(true) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ fun getLocalNetworks(context: Context, ipv6: Boolean): List<InetNetwork> {
|
|||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseInetAddress(address: String): InetAddress = parseNumericAddressCompat(address)
|
fun parseInetAddress(address: String): InetAddress = InetAddress.getByName(address)
|
||||||
|
|
||||||
private val parseNumericAddressCompat: (String) -> InetAddress =
|
private val parseNumericAddressCompat: (String) -> InetAddress =
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
@@ -60,7 +60,7 @@ private val parseNumericAddressCompat: (String) -> InetAddress =
|
|||||||
internal fun convertIpv6ToCanonicalForm(ipv6: String): String = ipv6
|
internal fun convertIpv6ToCanonicalForm(ipv6: String): String = ipv6
|
||||||
.replace("((?:(?:^|:)0+\\b){2,}):?(?!\\S*\\b\\1:0+\\b)(\\S*)".toRegex(), "::$2")
|
.replace("((?:(?:^|:)0+\\b){2,}):?(?!\\S*\\b\\1:0+\\b)(\\S*)".toRegex(), "::$2")
|
||||||
|
|
||||||
internal val InetAddress.ip: String
|
val InetAddress.ip: String
|
||||||
get() = if (this is Inet4Address) {
|
get() = if (this is Inet4Address) {
|
||||||
hostAddress!!
|
hostAddress!!
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+78
-68
@@ -1,54 +1,26 @@
|
|||||||
package org.amnezia.vpn.protocol.wireguard
|
package org.amnezia.vpn.protocol.wireguard
|
||||||
|
|
||||||
import android.net.VpnService.Builder
|
import android.net.VpnService.Builder
|
||||||
import java.util.TreeMap
|
import java.io.IOException
|
||||||
|
import java.util.Locale
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import org.amnezia.awg.GoBackend
|
import org.amnezia.awg.GoBackend
|
||||||
import org.amnezia.vpn.protocol.Protocol
|
import org.amnezia.vpn.protocol.Protocol
|
||||||
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
|
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
|
||||||
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
|
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
|
||||||
import org.amnezia.vpn.protocol.Statistics
|
import org.amnezia.vpn.protocol.Statistics
|
||||||
import org.amnezia.vpn.protocol.VpnStartException
|
import org.amnezia.vpn.protocol.VpnStartException
|
||||||
|
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
|
||||||
import org.amnezia.vpn.util.Log
|
import org.amnezia.vpn.util.Log
|
||||||
|
import org.amnezia.vpn.util.asSequence
|
||||||
import org.amnezia.vpn.util.net.InetEndpoint
|
import org.amnezia.vpn.util.net.InetEndpoint
|
||||||
import org.amnezia.vpn.util.net.InetNetwork
|
import org.amnezia.vpn.util.net.InetNetwork
|
||||||
import org.amnezia.vpn.util.net.parseInetAddress
|
import org.amnezia.vpn.util.net.parseInetAddress
|
||||||
|
import org.amnezia.vpn.util.optStringOrNull
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
/**
|
|
||||||
* Config example:
|
|
||||||
* {
|
|
||||||
* "protocol": "wireguard",
|
|
||||||
* "description": "Server 1",
|
|
||||||
* "dns1": "1.1.1.1",
|
|
||||||
* "dns2": "1.0.0.1",
|
|
||||||
* "hostName": "100.100.100.0",
|
|
||||||
* "splitTunnelSites": [
|
|
||||||
* ],
|
|
||||||
* "splitTunnelType": 0,
|
|
||||||
* "wireguard_config_data": {
|
|
||||||
* "client_ip": "10.8.1.1",
|
|
||||||
* "hostName": "100.100.100.0",
|
|
||||||
* "port": 12345,
|
|
||||||
* "client_pub_key": "clientPublicKeyBase64",
|
|
||||||
* "client_priv_key": "privateKeyBase64",
|
|
||||||
* "psk_key": "presharedKeyBase64",
|
|
||||||
* "server_pub_key": "publicKeyBase64",
|
|
||||||
* "config": "[Interface]
|
|
||||||
* Address = 10.8.1.1/32
|
|
||||||
* DNS = 1.1.1.1, 1.0.0.1
|
|
||||||
* PrivateKey = privateKeyBase64
|
|
||||||
*
|
|
||||||
* [Peer]
|
|
||||||
* PublicKey = publicKeyBase64
|
|
||||||
* PresharedKey = presharedKeyBase64
|
|
||||||
* AllowedIPs = 0.0.0.0/0, ::/0
|
|
||||||
* Endpoint = 100.100.100.0:12345
|
|
||||||
* PersistentKeepalive = 25
|
|
||||||
* "
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
private const val TAG = "Wireguard"
|
private const val TAG = "Wireguard"
|
||||||
|
|
||||||
open class Wireguard : Protocol() {
|
open class Wireguard : Protocol() {
|
||||||
@@ -79,67 +51,105 @@ open class Wireguard : Protocol() {
|
|||||||
if (!isInitialized) loadSharedLibrary(context, "wg-go")
|
if (!isInitialized) loadSharedLibrary(context, "wg-go")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
override suspend fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
||||||
val wireguardConfig = parseConfig(config)
|
val wireguardConfig = parseConfig(config)
|
||||||
|
val startTime = System.currentTimeMillis()
|
||||||
start(wireguardConfig, vpnBuilder, protect)
|
start(wireguardConfig, vpnBuilder, protect)
|
||||||
|
waitForConnection(startTime)
|
||||||
state.value = CONNECTED
|
state.value = CONNECTED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun waitForConnection(startTime: Long) {
|
||||||
|
Log.d(TAG, "Waiting for connection")
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val time = String.format(Locale.ROOT,"%.3f", startTime / 1000.0)
|
||||||
|
try {
|
||||||
|
delay(1000)
|
||||||
|
var log = getLogcat(time)
|
||||||
|
Log.d(TAG, "First waiting log: $log")
|
||||||
|
// check that there is a connection log,
|
||||||
|
// to avoid infinite connection
|
||||||
|
if (!log.contains("Attaching to interface")) {
|
||||||
|
Log.w(TAG, "Logs do not contain a connection log")
|
||||||
|
return@withContext
|
||||||
|
}
|
||||||
|
while (!log.contains("Received handshake response")) {
|
||||||
|
delay(1000)
|
||||||
|
log = getLogcat(time)
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.e(TAG, "Failed to get logcat: $e")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLogcat(time: String): String =
|
||||||
|
ProcessBuilder("logcat", "--buffer=main", "--format=raw", "*:S AmneziaWG/awg0", "-t", time)
|
||||||
|
.redirectErrorStream(true)
|
||||||
|
.start()
|
||||||
|
.inputStream.reader().readText()
|
||||||
|
|
||||||
protected open fun parseConfig(config: JSONObject): WireguardConfig {
|
protected open fun parseConfig(config: JSONObject): WireguardConfig {
|
||||||
val configDataJson = config.getJSONObject("wireguard_config_data")
|
val configData = config.getJSONObject("wireguard_config_data")
|
||||||
val configData = parseConfigData(configDataJson.getString("config"))
|
|
||||||
return WireguardConfig.build {
|
return WireguardConfig.build {
|
||||||
configWireguard(configData, configDataJson)
|
configWireguard(config, configData)
|
||||||
configSplitTunneling(config)
|
configSplitTunneling(config)
|
||||||
configAppSplitTunneling(config)
|
configAppSplitTunneling(config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun WireguardConfig.Builder.configWireguard(configData: Map<String, String>, configDataJson: JSONObject) {
|
protected fun WireguardConfig.Builder.configWireguard(config: JSONObject, configData: JSONObject) {
|
||||||
configData["Address"]?.split(",")?.map { address ->
|
configData.getString("client_ip").split(",").map { address ->
|
||||||
InetNetwork.parse(address.trim())
|
InetNetwork.parse(address.trim())
|
||||||
}?.forEach(::addAddress)
|
}.forEach(::addAddress)
|
||||||
|
|
||||||
configData["DNS"]?.split(",")?.map { dns ->
|
config.optStringOrNull("dns1")?.let { dns ->
|
||||||
parseInetAddress(dns.trim())
|
addDnsServer(parseInetAddress(dns.trim()))
|
||||||
}?.forEach(::addDnsServer)
|
}
|
||||||
|
|
||||||
|
config.optStringOrNull("dns2")?.let { dns ->
|
||||||
|
addDnsServer(parseInetAddress(dns.trim()))
|
||||||
|
}
|
||||||
|
|
||||||
val defRoutes = hashSetOf(
|
val defRoutes = hashSetOf(
|
||||||
InetNetwork("0.0.0.0", 0),
|
InetNetwork("0.0.0.0", 0),
|
||||||
InetNetwork("::", 0)
|
InetNetwork("::", 0)
|
||||||
)
|
)
|
||||||
val routes = hashSetOf<InetNetwork>()
|
val routes = hashSetOf<InetNetwork>()
|
||||||
configData["AllowedIPs"]?.split(",")?.map { route ->
|
configData.getJSONArray("allowed_ips").asSequence<String>().map { route ->
|
||||||
InetNetwork.parse(route.trim())
|
InetNetwork.parse(route.trim())
|
||||||
}?.forEach(routes::add)
|
}.forEach(routes::add)
|
||||||
// if the allowed IPs list contains at least one non-default route, disable global split tunneling
|
// if the allowed IPs list contains at least one non-default route, disable global split tunneling
|
||||||
if (routes.any { it !in defRoutes }) disableSplitTunneling()
|
if (routes.any { it !in defRoutes }) disableSplitTunneling()
|
||||||
addRoutes(routes)
|
addRoutes(routes)
|
||||||
|
|
||||||
configDataJson.optString("mtu").let { mtu ->
|
configData.optStringOrNull("mtu")?.let { setMtu(it.toInt()) }
|
||||||
if (mtu.isNotEmpty()) {
|
|
||||||
setMtu(mtu.toInt())
|
val host = configData.getString("hostName").let { parseInetAddress(it.trim()) }
|
||||||
} else {
|
val port = configData.getInt("port")
|
||||||
configData["MTU"]?.let { setMtu(it.toInt()) }
|
setEndpoint(InetEndpoint(host, port))
|
||||||
}
|
|
||||||
|
if (configData.optBoolean("isObfuscationEnabled")) {
|
||||||
|
setUseProtocolExtension(true)
|
||||||
|
configExtensionParameters(configData)
|
||||||
}
|
}
|
||||||
|
|
||||||
configData["Endpoint"]?.let { setEndpoint(InetEndpoint.parse(it)) }
|
configData.optStringOrNull("persistent_keep_alive")?.let { setPersistentKeepalive(it.toInt()) }
|
||||||
configData["PersistentKeepalive"]?.let { setPersistentKeepalive(it.toInt()) }
|
configData.getString("client_priv_key").let { setPrivateKeyHex(it.base64ToHex()) }
|
||||||
configData["PrivateKey"]?.let { setPrivateKeyHex(it.base64ToHex()) }
|
configData.getString("server_pub_key").let { setPublicKeyHex(it.base64ToHex()) }
|
||||||
configData["PublicKey"]?.let { setPublicKeyHex(it.base64ToHex()) }
|
configData.optStringOrNull("psk_key")?.let { setPreSharedKeyHex(it.base64ToHex()) }
|
||||||
configData["PresharedKey"]?.let { setPreSharedKeyHex(it.base64ToHex()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun parseConfigData(data: String): Map<String, String> {
|
protected fun WireguardConfig.Builder.configExtensionParameters(configData: JSONObject) {
|
||||||
val parsedData = TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER)
|
configData.optStringOrNull("Jc")?.let { setJc(it.toInt()) }
|
||||||
data.lineSequence()
|
configData.optStringOrNull("Jmin")?.let { setJmin(it.toInt()) }
|
||||||
.filter { it.isNotEmpty() && !it.startsWith('[') }
|
configData.optStringOrNull("Jmax")?.let { setJmax(it.toInt()) }
|
||||||
.forEach { line ->
|
configData.optStringOrNull("S1")?.let { setS1(it.toInt()) }
|
||||||
val attr = line.split("=", limit = 2)
|
configData.optStringOrNull("S2")?.let { setS2(it.toInt()) }
|
||||||
parsedData[attr.first().trim()] = attr.last().trim()
|
configData.optStringOrNull("H1")?.let { setH1(it.toLong()) }
|
||||||
}
|
configData.optStringOrNull("H2")?.let { setH2(it.toLong()) }
|
||||||
return parsedData
|
configData.optStringOrNull("H3")?.let { setH3(it.toLong()) }
|
||||||
|
configData.optStringOrNull("H4")?.let { setH4(it.toLong()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
||||||
|
|||||||
+71
-2
@@ -1,6 +1,7 @@
|
|||||||
package org.amnezia.vpn.protocol.wireguard
|
package org.amnezia.vpn.protocol.wireguard
|
||||||
|
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
|
import org.amnezia.vpn.protocol.BadConfigException
|
||||||
import org.amnezia.vpn.protocol.ProtocolConfig
|
import org.amnezia.vpn.protocol.ProtocolConfig
|
||||||
import org.amnezia.vpn.util.net.InetEndpoint
|
import org.amnezia.vpn.util.net.InetEndpoint
|
||||||
|
|
||||||
@@ -12,7 +13,17 @@ open class WireguardConfig protected constructor(
|
|||||||
val persistentKeepalive: Int,
|
val persistentKeepalive: Int,
|
||||||
val publicKeyHex: String,
|
val publicKeyHex: String,
|
||||||
val preSharedKeyHex: String?,
|
val preSharedKeyHex: String?,
|
||||||
val privateKeyHex: String
|
val privateKeyHex: String,
|
||||||
|
val useProtocolExtension: Boolean,
|
||||||
|
val jc: Int?,
|
||||||
|
val jmin: Int?,
|
||||||
|
val jmax: Int?,
|
||||||
|
val s1: Int?,
|
||||||
|
val s2: Int?,
|
||||||
|
val h1: Long?,
|
||||||
|
val h2: Long?,
|
||||||
|
val h3: Long?,
|
||||||
|
val h4: Long?
|
||||||
) : ProtocolConfig(protocolConfigBuilder) {
|
) : ProtocolConfig(protocolConfigBuilder) {
|
||||||
|
|
||||||
protected constructor(builder: Builder) : this(
|
protected constructor(builder: Builder) : this(
|
||||||
@@ -21,7 +32,17 @@ open class WireguardConfig protected constructor(
|
|||||||
builder.persistentKeepalive,
|
builder.persistentKeepalive,
|
||||||
builder.publicKeyHex,
|
builder.publicKeyHex,
|
||||||
builder.preSharedKeyHex,
|
builder.preSharedKeyHex,
|
||||||
builder.privateKeyHex
|
builder.privateKeyHex,
|
||||||
|
builder.useProtocolExtension,
|
||||||
|
builder.jc,
|
||||||
|
builder.jmin,
|
||||||
|
builder.jmax,
|
||||||
|
builder.s1,
|
||||||
|
builder.s2,
|
||||||
|
builder.h1,
|
||||||
|
builder.h2,
|
||||||
|
builder.h3,
|
||||||
|
builder.h4
|
||||||
)
|
)
|
||||||
|
|
||||||
fun toWgUserspaceString(): String = with(StringBuilder()) {
|
fun toWgUserspaceString(): String = with(StringBuilder()) {
|
||||||
@@ -33,6 +54,30 @@ open class WireguardConfig protected constructor(
|
|||||||
|
|
||||||
open fun appendDeviceLine(sb: StringBuilder) = with(sb) {
|
open fun appendDeviceLine(sb: StringBuilder) = with(sb) {
|
||||||
appendLine("private_key=$privateKeyHex")
|
appendLine("private_key=$privateKeyHex")
|
||||||
|
if (useProtocolExtension) {
|
||||||
|
validateProtocolExtensionParameters()
|
||||||
|
appendLine("jc=$jc")
|
||||||
|
appendLine("jmin=$jmin")
|
||||||
|
appendLine("jmax=$jmax")
|
||||||
|
appendLine("s1=$s1")
|
||||||
|
appendLine("s2=$s2")
|
||||||
|
appendLine("h1=$h1")
|
||||||
|
appendLine("h2=$h2")
|
||||||
|
appendLine("h3=$h3")
|
||||||
|
appendLine("h4=$h4")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateProtocolExtensionParameters() {
|
||||||
|
if (jc == null) throw BadConfigException("Parameter jc is undefined")
|
||||||
|
if (jmin == null) throw BadConfigException("Parameter jmin is undefined")
|
||||||
|
if (jmax == null) throw BadConfigException("Parameter jmax is undefined")
|
||||||
|
if (s1 == null) throw BadConfigException("Parameter s1 is undefined")
|
||||||
|
if (s2 == null) throw BadConfigException("Parameter s2 is undefined")
|
||||||
|
if (h1 == null) throw BadConfigException("Parameter h1 is undefined")
|
||||||
|
if (h2 == null) throw BadConfigException("Parameter h2 is undefined")
|
||||||
|
if (h3 == null) throw BadConfigException("Parameter h3 is undefined")
|
||||||
|
if (h4 == null) throw BadConfigException("Parameter h4 is undefined")
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun appendPeerLine(sb: StringBuilder) = with(sb) {
|
open fun appendPeerLine(sb: StringBuilder) = with(sb) {
|
||||||
@@ -65,6 +110,18 @@ open class WireguardConfig protected constructor(
|
|||||||
|
|
||||||
override var mtu: Int = WIREGUARD_DEFAULT_MTU
|
override var mtu: Int = WIREGUARD_DEFAULT_MTU
|
||||||
|
|
||||||
|
internal var useProtocolExtension: Boolean = false
|
||||||
|
|
||||||
|
internal var jc: Int? = null
|
||||||
|
internal var jmin: Int? = null
|
||||||
|
internal var jmax: Int? = null
|
||||||
|
internal var s1: Int? = null
|
||||||
|
internal var s2: Int? = null
|
||||||
|
internal var h1: Long? = null
|
||||||
|
internal var h2: Long? = null
|
||||||
|
internal var h3: Long? = null
|
||||||
|
internal var h4: Long? = null
|
||||||
|
|
||||||
fun setEndpoint(endpoint: InetEndpoint) = apply { this.endpoint = endpoint }
|
fun setEndpoint(endpoint: InetEndpoint) = apply { this.endpoint = endpoint }
|
||||||
|
|
||||||
fun setPersistentKeepalive(persistentKeepalive: Int) = apply { this.persistentKeepalive = persistentKeepalive }
|
fun setPersistentKeepalive(persistentKeepalive: Int) = apply { this.persistentKeepalive = persistentKeepalive }
|
||||||
@@ -75,6 +132,18 @@ open class WireguardConfig protected constructor(
|
|||||||
|
|
||||||
fun setPrivateKeyHex(privateKeyHex: String) = apply { this.privateKeyHex = privateKeyHex }
|
fun setPrivateKeyHex(privateKeyHex: String) = apply { this.privateKeyHex = privateKeyHex }
|
||||||
|
|
||||||
|
fun setUseProtocolExtension(useProtocolExtension: Boolean) = apply { this.useProtocolExtension = useProtocolExtension }
|
||||||
|
|
||||||
|
fun setJc(jc: Int) = apply { this.jc = jc }
|
||||||
|
fun setJmin(jmin: Int) = apply { this.jmin = jmin }
|
||||||
|
fun setJmax(jmax: Int) = apply { this.jmax = jmax }
|
||||||
|
fun setS1(s1: Int) = apply { this.s1 = s1 }
|
||||||
|
fun setS2(s2: Int) = apply { this.s2 = s2 }
|
||||||
|
fun setH1(h1: Long) = apply { this.h1 = h1 }
|
||||||
|
fun setH2(h2: Long) = apply { this.h2 = h2 }
|
||||||
|
fun setH3(h3: Long) = apply { this.h3 = h3 }
|
||||||
|
fun setH4(h4: Long) = apply { this.h4 = h4 }
|
||||||
|
|
||||||
override fun build(): WireguardConfig = configBuild().run { WireguardConfig(this@Builder) }
|
override fun build(): WireguardConfig = configBuild().run { WireguardConfig(this@Builder) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,72 +17,10 @@ import org.amnezia.vpn.protocol.xray.libXray.Logger
|
|||||||
import org.amnezia.vpn.protocol.xray.libXray.Tun2SocksConfig
|
import org.amnezia.vpn.protocol.xray.libXray.Tun2SocksConfig
|
||||||
import org.amnezia.vpn.util.Log
|
import org.amnezia.vpn.util.Log
|
||||||
import org.amnezia.vpn.util.net.InetNetwork
|
import org.amnezia.vpn.util.net.InetNetwork
|
||||||
|
import org.amnezia.vpn.util.net.ip
|
||||||
import org.amnezia.vpn.util.net.parseInetAddress
|
import org.amnezia.vpn.util.net.parseInetAddress
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
/**
|
|
||||||
* Config example:
|
|
||||||
* {
|
|
||||||
* "appSplitTunnelType": 0,
|
|
||||||
* "config_version": 0,
|
|
||||||
* "description": "Server 1",
|
|
||||||
* "dns1": "1.1.1.1",
|
|
||||||
* "dns2": "1.0.0.1",
|
|
||||||
* "hostName": "100.100.100.0",
|
|
||||||
* "protocol": "xray",
|
|
||||||
* "splitTunnelApps": [],
|
|
||||||
* "splitTunnelSites": [],
|
|
||||||
* "splitTunnelType": 0,
|
|
||||||
* "xray_config_data": {
|
|
||||||
* "inbounds": [
|
|
||||||
* {
|
|
||||||
* "listen": "127.0.0.1",
|
|
||||||
* "port": 8080,
|
|
||||||
* "protocol": "socks",
|
|
||||||
* "settings": {
|
|
||||||
* "udp": true
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ],
|
|
||||||
* "log": {
|
|
||||||
* "loglevel": "error"
|
|
||||||
* },
|
|
||||||
* "outbounds": [
|
|
||||||
* {
|
|
||||||
* "protocol": "vless",
|
|
||||||
* "settings": {
|
|
||||||
* "vnext": [
|
|
||||||
* {
|
|
||||||
* "address": "100.100.100.0",
|
|
||||||
* "port": 443,
|
|
||||||
* "users": [
|
|
||||||
* {
|
|
||||||
* "encryption": "none",
|
|
||||||
* "flow": "xtls-rprx-vision",
|
|
||||||
* "id": "id"
|
|
||||||
* }
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* ]
|
|
||||||
* },
|
|
||||||
* "streamSettings": {
|
|
||||||
* "network": "tcp",
|
|
||||||
* "realitySettings": {
|
|
||||||
* "fingerprint": "chrome",
|
|
||||||
* "publicKey": "publicKey",
|
|
||||||
* "serverName": "google.com",
|
|
||||||
* "shortId": "id",
|
|
||||||
* "spiderX": ""
|
|
||||||
* },
|
|
||||||
* "security": "reality"
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
private const val TAG = "Xray"
|
private const val TAG = "Xray"
|
||||||
private const val LIBXRAY_TAG = "libXray"
|
private const val LIBXRAY_TAG = "libXray"
|
||||||
|
|
||||||
@@ -109,7 +47,7 @@ class Xray : Protocol() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
override suspend fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
||||||
if (isRunning) {
|
if (isRunning) {
|
||||||
Log.w(TAG, "XRay already running")
|
Log.w(TAG, "XRay already running")
|
||||||
return
|
return
|
||||||
@@ -124,7 +62,15 @@ class Xray : Protocol() {
|
|||||||
.put("loglevel", "warning")
|
.put("loglevel", "warning")
|
||||||
.put("access", "none") // disable access log
|
.put("access", "none") // disable access log
|
||||||
|
|
||||||
start(xrayConfig, xrayJsonConfig.toString(), vpnBuilder, protect)
|
var xrayJsonConfigString = xrayJsonConfig.toString()
|
||||||
|
config.getString("hostName").let { hostName ->
|
||||||
|
val ipAddress = parseInetAddress(hostName).ip
|
||||||
|
if (hostName != ipAddress) {
|
||||||
|
xrayJsonConfigString = xrayJsonConfigString.replace(hostName, ipAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start(xrayConfig, xrayJsonConfigString, vpnBuilder, protect)
|
||||||
state.value = CONNECTED
|
state.value = CONNECTED
|
||||||
isRunning = true
|
isRunning = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ 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_utils.h
|
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_utils.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
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/core/installedAppsImageProvider.h
|
${CMAKE_CURRENT_SOURCE_DIR}/core/installedAppsImageProvider.h
|
||||||
)
|
)
|
||||||
@@ -35,7 +34,6 @@ 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_utils.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_utils.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
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/core/installedAppsImageProvider.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/core/installedAppsImageProvider.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -95,6 +95,18 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
|||||||
stdOut.replace("/32", "");
|
stdOut.replace("/32", "");
|
||||||
QStringList ips = stdOut.split("\n", Qt::SkipEmptyParts);
|
QStringList ips = stdOut.split("\n", Qt::SkipEmptyParts);
|
||||||
|
|
||||||
|
// remove extra IPs from each line for case when user manually edited the wg0.conf
|
||||||
|
// and added there more IPs for route his itnernal networks, like:
|
||||||
|
// ...
|
||||||
|
// AllowedIPs = 10.8.1.6/32, 192.168.1.0/24, 192.168.2.0/24, ...
|
||||||
|
// ...
|
||||||
|
// without this code - next IP would be 1 if last item in 'ips' has format above
|
||||||
|
QStringList vpnIps;
|
||||||
|
for (const auto &ip : ips) {
|
||||||
|
vpnIps.append(ip.split(",", Qt::SkipEmptyParts).first().trimmed());
|
||||||
|
}
|
||||||
|
ips = vpnIps;
|
||||||
|
|
||||||
// Calc next IP address
|
// Calc next IP address
|
||||||
if (ips.isEmpty()) {
|
if (ips.isEmpty()) {
|
||||||
nextIpNumber = "2";
|
nextIpNumber = "2";
|
||||||
@@ -187,6 +199,10 @@ QString WireguardConfigurator::createConfig(const ServerCredentials &credentials
|
|||||||
jConfig[config_key::server_pub_key] = connData.serverPubKey;
|
jConfig[config_key::server_pub_key] = connData.serverPubKey;
|
||||||
jConfig[config_key::mtu] = wireguarConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
jConfig[config_key::mtu] = wireguarConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
||||||
|
|
||||||
|
jConfig[config_key::persistent_keep_alive] = "25";
|
||||||
|
QJsonArray allowedIps { "0.0.0.0/0", "::/0" };
|
||||||
|
jConfig[config_key::allowed_ips] = allowedIps;
|
||||||
|
|
||||||
jConfig[config_key::clientId] = connData.clientPubKey;
|
jConfig[config_key::clientId] = connData.clientPubKey;
|
||||||
|
|
||||||
return QJsonDocument(jConfig).toJson();
|
return QJsonDocument(jConfig).toJson();
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
#include "QRsa.h"
|
#include "QRsa.h"
|
||||||
|
|
||||||
#include "amnezia_application.h"
|
#include "amnezia_application.h"
|
||||||
#include "core/enums/apiEnums.h"
|
|
||||||
#include "configurators/wireguard_configurator.h"
|
#include "configurators/wireguard_configurator.h"
|
||||||
|
#include "core/enums/apiEnums.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -42,7 +42,7 @@ namespace
|
|||||||
constexpr char keyPayload[] = "key_payload";
|
constexpr char keyPayload[] = "key_payload";
|
||||||
}
|
}
|
||||||
|
|
||||||
const QStringList proxyStorageUrl = {""};
|
const QStringList proxyStorageUrl = { "" };
|
||||||
|
|
||||||
ErrorCode checkErrors(const QList<QSslError> &sslErrors, QNetworkReply *reply)
|
ErrorCode checkErrors(const QList<QSslError> &sslErrors, QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
@@ -65,7 +65,8 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiController::ApiController(const QString &gatewayEndpoint, QObject *parent) : QObject(parent), m_gatewayEndpoint(gatewayEndpoint)
|
ApiController::ApiController(const QString &gatewayEndpoint, bool isDevEnvironment, QObject *parent)
|
||||||
|
: QObject(parent), m_gatewayEndpoint(gatewayEndpoint), m_isDevEnvironment(isDevEnvironment)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +144,7 @@ QStringList ApiController::getProxyUrls()
|
|||||||
|
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
QList<QSslError> sslErrors;
|
QList<QSslError> sslErrors;
|
||||||
QNetworkReply* reply;
|
QNetworkReply *reply;
|
||||||
|
|
||||||
for (const auto &proxyStorageUrl : proxyStorageUrl) {
|
for (const auto &proxyStorageUrl : proxyStorageUrl) {
|
||||||
request.setUrl(proxyStorageUrl);
|
request.setUrl(proxyStorageUrl);
|
||||||
@@ -281,7 +282,7 @@ ErrorCode ApiController::getServicesList(QByteArray &responseBody)
|
|||||||
|
|
||||||
request.setUrl(QString("%1v1/services").arg(m_gatewayEndpoint));
|
request.setUrl(QString("%1v1/services").arg(m_gatewayEndpoint));
|
||||||
|
|
||||||
QNetworkReply* reply;
|
QNetworkReply *reply;
|
||||||
reply = amnApp->manager()->get(request);
|
reply = amnApp->manager()->get(request);
|
||||||
|
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
@@ -300,7 +301,8 @@ ErrorCode ApiController::getServicesList(QByteArray &responseBody)
|
|||||||
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
||||||
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
||||||
wait.exec();
|
wait.exec();
|
||||||
if (reply->error() != QNetworkReply::NetworkError::TimeoutError && reply->error() != QNetworkReply::NetworkError::OperationCanceledError) {
|
if (reply->error() != QNetworkReply::NetworkError::TimeoutError
|
||||||
|
&& reply->error() != QNetworkReply::NetworkError::OperationCanceledError) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
@@ -355,9 +357,9 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co
|
|||||||
|
|
||||||
EVP_PKEY *publicKey = nullptr;
|
EVP_PKEY *publicKey = nullptr;
|
||||||
try {
|
try {
|
||||||
QByteArray key = PROD_AGW_PUBLIC_KEY;
|
QByteArray rsaKey = m_isDevEnvironment ? DEV_AGW_PUBLIC_KEY : PROD_AGW_PUBLIC_KEY;
|
||||||
QSimpleCrypto::QRsa rsa;
|
QSimpleCrypto::QRsa rsa;
|
||||||
publicKey = rsa.getPublicKeyFromByteArray(key);
|
publicKey = rsa.getPublicKeyFromByteArray(rsaKey);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
qCritical() << "error loading public key from environment variables";
|
qCritical() << "error loading public key from environment variables";
|
||||||
return ErrorCode::ApiMissingAgwPublicKey;
|
return ErrorCode::ApiMissingAgwPublicKey;
|
||||||
@@ -375,7 +377,7 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co
|
|||||||
requestBody[configKey::keyPayload] = QString(encryptedKeyPayload.toBase64());
|
requestBody[configKey::keyPayload] = QString(encryptedKeyPayload.toBase64());
|
||||||
requestBody[configKey::apiPayload] = QString(encryptedApiPayload.toBase64());
|
requestBody[configKey::apiPayload] = QString(encryptedApiPayload.toBase64());
|
||||||
|
|
||||||
QNetworkReply* reply = manager.post(request, QJsonDocument(requestBody).toJson());
|
QNetworkReply *reply = manager.post(request, QJsonDocument(requestBody).toJson());
|
||||||
|
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
||||||
@@ -395,7 +397,8 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co
|
|||||||
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
||||||
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
||||||
wait.exec();
|
wait.exec();
|
||||||
if (reply->error() != QNetworkReply::NetworkError::TimeoutError && reply->error() != QNetworkReply::NetworkError::OperationCanceledError) {
|
if (reply->error() != QNetworkReply::NetworkError::TimeoutError
|
||||||
|
&& reply->error() != QNetworkReply::NetworkError::OperationCanceledError) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class ApiController : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ApiController(const QString &gatewayEndpoint, QObject *parent = nullptr);
|
explicit ApiController(const QString &gatewayEndpoint, bool isDevEnvironment, QObject *parent = nullptr);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateServerConfigFromApi(const QString &installationUuid, const int serverIndex, QJsonObject serverConfig);
|
void updateServerConfigFromApi(const QString &installationUuid, const int serverIndex, QJsonObject serverConfig);
|
||||||
@@ -44,6 +44,7 @@ private:
|
|||||||
|
|
||||||
QString m_gatewayEndpoint;
|
QString m_gatewayEndpoint;
|
||||||
QStringList m_proxyUrls;
|
QStringList m_proxyUrls;
|
||||||
|
bool m_isDevEnvironment = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APICONTROLLER_H
|
#endif // APICONTROLLER_H
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
qDebug().noquote() << lineToExec;
|
qDebug().noquote() << lineToExec;
|
||||||
Logger::appendSshLog("Run command:" + lineToExec);
|
|
||||||
|
|
||||||
error = m_sshClient.executeCommand(lineToExec, cbReadStdOut, cbReadStdErr);
|
error = m_sshClient.executeCommand(lineToExec, cbReadStdOut, cbReadStdErr);
|
||||||
if (error != ErrorCode::NoError) {
|
if (error != ErrorCode::NoError) {
|
||||||
@@ -100,13 +99,13 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
|
|||||||
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
|
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
|
||||||
{
|
{
|
||||||
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
||||||
Logger::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + ":\n" + script);
|
|
||||||
|
|
||||||
ErrorCode e = uploadTextFileToContainer(container, credentials, script, fileName);
|
ErrorCode e = uploadTextFileToContainer(container, credentials, script, fileName);
|
||||||
if (e)
|
if (e)
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
QString runner = QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash"));
|
QString runner =
|
||||||
|
QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash"));
|
||||||
e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
||||||
|
|
||||||
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
|
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
|
||||||
@@ -426,7 +425,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
|||||||
if (errorCode)
|
if (errorCode)
|
||||||
return errorCode;
|
return errorCode;
|
||||||
|
|
||||||
errorCode = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(),dockerFilePath);
|
errorCode = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(), dockerFilePath);
|
||||||
|
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return errorCode;
|
return errorCode;
|
||||||
@@ -437,7 +436,8 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
|||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
};
|
};
|
||||||
|
|
||||||
errorCode = runScript(credentials,
|
errorCode =
|
||||||
|
runScript(credentials,
|
||||||
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
|
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
|
||||||
cbReadStdOut);
|
cbReadStdOut);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
@@ -621,13 +621,15 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
|||||||
|
|
||||||
// Socks5 proxy vars
|
// Socks5 proxy vars
|
||||||
vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } });
|
vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } });
|
||||||
auto username = socks5ProxyConfig.value(config_key:: userName).toString();
|
auto username = socks5ProxyConfig.value(config_key::userName).toString();
|
||||||
auto password = socks5ProxyConfig.value(config_key::password).toString();
|
auto password = socks5ProxyConfig.value(config_key::password).toString();
|
||||||
QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : "";
|
QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : "";
|
||||||
vars.append({ { "$SOCKS5_USER", socks5user } });
|
vars.append({ { "$SOCKS5_USER", socks5user } });
|
||||||
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
|
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
|
||||||
|
|
||||||
QString serverIp = NetworkUtilities::getIPAddress(credentials.hostName);
|
QString serverIp = (container != DockerContainer::Awg && container != DockerContainer::WireGuard && container != DockerContainer::Xray)
|
||||||
|
? NetworkUtilities::getIPAddress(credentials.hostName)
|
||||||
|
: credentials.hostName;
|
||||||
if (!serverIp.isEmpty()) {
|
if (!serverIp.isEmpty()) {
|
||||||
vars.append({ { "$SERVER_IP_ADDRESS", serverIp } });
|
vars.append({ { "$SERVER_IP_ADDRESS", serverIp } });
|
||||||
} else {
|
} else {
|
||||||
@@ -713,7 +715,8 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential
|
|||||||
udpProtoScript.append("' | grep -i udp");
|
udpProtoScript.append("' | grep -i udp");
|
||||||
tcpProtoScript.append(" | grep LISTEN");
|
tcpProtoScript.append(" | grep LISTEN");
|
||||||
|
|
||||||
ErrorCode errorCode = runScript(credentials, replaceVars(tcpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
ErrorCode errorCode =
|
||||||
|
runScript(credentials, replaceVars(tcpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
||||||
if (errorCode != ErrorCode::NoError) {
|
if (errorCode != ErrorCode::NoError) {
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,13 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair<QStr
|
|||||||
protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString);
|
protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString);
|
||||||
|
|
||||||
QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
||||||
vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
if (container == DockerContainer::Awg || container == DockerContainer::WireGuard) {
|
||||||
|
// add mtu for old configs
|
||||||
|
if (vpnConfigData[config_key::mtu].toString().isEmpty()) {
|
||||||
|
vpnConfigData[config_key::mtu] = container == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData);
|
vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ QSharedPointer<IpcInterfaceReplica> IpcClient::Interface()
|
|||||||
return Instance()->m_ipcClient;
|
return Instance()->m_ipcClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSharedPointer<IpcProcessTun2SocksReplica> IpcClient::InterfaceTun2Socks()
|
||||||
|
{
|
||||||
|
if (!Instance()) return nullptr;
|
||||||
|
return Instance()->m_Tun2SocksClient;
|
||||||
|
}
|
||||||
|
|
||||||
bool IpcClient::init(IpcClient *instance)
|
bool IpcClient::init(IpcClient *instance)
|
||||||
{
|
{
|
||||||
m_instance = instance;
|
m_instance = instance;
|
||||||
@@ -44,6 +50,12 @@ bool IpcClient::init(IpcClient *instance)
|
|||||||
qWarning() << "IpcClient replica is not connected!";
|
qWarning() << "IpcClient replica is not connected!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instance()->m_Tun2SocksClient.reset(Instance()->m_ClientNode.acquire<IpcProcessTun2SocksReplica>());
|
||||||
|
Instance()->m_Tun2SocksClient->waitForSource(1000);
|
||||||
|
|
||||||
|
if (!Instance()->m_Tun2SocksClient->isReplicaValid()) {
|
||||||
|
qWarning() << "IpcClient::m_Tun2SocksClient replica is not connected!";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(Instance()->m_localSocket, &QLocalSocket::disconnected, [instance](){
|
connect(Instance()->m_localSocket, &QLocalSocket::disconnected, [instance](){
|
||||||
@@ -51,16 +63,16 @@ bool IpcClient::init(IpcClient *instance)
|
|||||||
});
|
});
|
||||||
|
|
||||||
Instance()->m_localSocket->connectToServer(amnezia::getIpcServiceUrl());
|
Instance()->m_localSocket->connectToServer(amnezia::getIpcServiceUrl());
|
||||||
|
|
||||||
Instance()->m_localSocket->waitForConnected();
|
Instance()->m_localSocket->waitForConnected();
|
||||||
|
|
||||||
if (!Instance()->m_ipcClient) {
|
if (!Instance()->m_ipcClient) {
|
||||||
qDebug() << "IpcClient::init failed";
|
qDebug() << "IpcClient::init failed";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "IpcClient::init succeed";
|
qDebug() << "IpcClient::init succeed";
|
||||||
|
|
||||||
return Instance()->m_ipcClient->isReplicaValid();
|
return (Instance()->m_ipcClient->isReplicaValid() && Instance()->m_Tun2SocksClient->isReplicaValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<PrivilegedProcess> IpcClient::CreatePrivilegedProcess()
|
QSharedPointer<PrivilegedProcess> IpcClient::CreatePrivilegedProcess()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
#include "rep_ipc_interface_replica.h"
|
#include "rep_ipc_interface_replica.h"
|
||||||
|
#include "rep_ipc_process_tun2socks_replica.h"
|
||||||
|
|
||||||
#include "privileged_process.h"
|
#include "privileged_process.h"
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ public:
|
|||||||
static IpcClient *Instance();
|
static IpcClient *Instance();
|
||||||
static bool init(IpcClient *instance);
|
static bool init(IpcClient *instance);
|
||||||
static QSharedPointer<IpcInterfaceReplica> Interface();
|
static QSharedPointer<IpcInterfaceReplica> Interface();
|
||||||
|
static QSharedPointer<IpcProcessTun2SocksReplica> InterfaceTun2Socks();
|
||||||
static QSharedPointer<PrivilegedProcess> CreatePrivilegedProcess();
|
static QSharedPointer<PrivilegedProcess> CreatePrivilegedProcess();
|
||||||
|
|
||||||
bool isSocketConnected() const;
|
bool isSocketConnected() const;
|
||||||
@@ -28,8 +30,11 @@ private:
|
|||||||
~IpcClient() override;
|
~IpcClient() override;
|
||||||
|
|
||||||
QRemoteObjectNode m_ClientNode;
|
QRemoteObjectNode m_ClientNode;
|
||||||
|
QRemoteObjectNode m_Tun2SocksNode;
|
||||||
QSharedPointer<IpcInterfaceReplica> m_ipcClient;
|
QSharedPointer<IpcInterfaceReplica> m_ipcClient;
|
||||||
QPointer<QLocalSocket> m_localSocket;
|
QPointer<QLocalSocket> m_localSocket;
|
||||||
|
QPointer<QLocalSocket> m_tun2socksSocket;
|
||||||
|
QSharedPointer<IpcProcessTun2SocksReplica> m_Tun2SocksClient;
|
||||||
|
|
||||||
struct ProcessDescriptor {
|
struct ProcessDescriptor {
|
||||||
ProcessDescriptor () {
|
ProcessDescriptor () {
|
||||||
|
|||||||
@@ -109,7 +109,10 @@ QStringList NetworkUtilities::summarizeRoutes(const QStringList &ips, const QStr
|
|||||||
|
|
||||||
QString NetworkUtilities::getIPAddress(const QString &host)
|
QString NetworkUtilities::getIPAddress(const QString &host)
|
||||||
{
|
{
|
||||||
if (ipAddressRegExp().match(host).hasMatch()) {
|
QHostAddress address(host);
|
||||||
|
if (QAbstractSocket::IPv4Protocol == address.protocol()) {
|
||||||
|
return host;
|
||||||
|
} else if (QAbstractSocket::IPv6Protocol == address.protocol()) {
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-107
@@ -1,107 +0,0 @@
|
|||||||
#ifndef LOGGER_H
|
|
||||||
#define LOGGER_H
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QString>
|
|
||||||
#include <QTextStream>
|
|
||||||
|
|
||||||
#include "ui/property_helper.h"
|
|
||||||
|
|
||||||
#include "mozilla/shared/loglevel.h"
|
|
||||||
|
|
||||||
class Logger : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
AUTO_PROPERTY(QString, sshLog)
|
|
||||||
AUTO_PROPERTY(QString, allLog)
|
|
||||||
|
|
||||||
public:
|
|
||||||
static Logger& Instance();
|
|
||||||
|
|
||||||
static void appendSshLog(const QString &log);
|
|
||||||
static void appendAllLog(const QString &log);
|
|
||||||
|
|
||||||
|
|
||||||
static bool init();
|
|
||||||
static void deInit();
|
|
||||||
static bool setServiceLogsEnabled(bool enabled);
|
|
||||||
static bool openLogsFolder();
|
|
||||||
static bool openServiceLogsFolder();
|
|
||||||
static QString appLogFileNamePath();
|
|
||||||
static void clearLogs();
|
|
||||||
static void clearServiceLogs();
|
|
||||||
static void cleanUp();
|
|
||||||
|
|
||||||
static QString userLogsFilePath();
|
|
||||||
static QString getLogFile();
|
|
||||||
|
|
||||||
// compat with Mozilla logger
|
|
||||||
Logger(const QString &className) { m_className = className; }
|
|
||||||
const QString& className() const { return m_className; }
|
|
||||||
|
|
||||||
class Log {
|
|
||||||
public:
|
|
||||||
Log(Logger* logger, LogLevel level);
|
|
||||||
~Log();
|
|
||||||
|
|
||||||
Log& operator<<(uint64_t t);
|
|
||||||
Log& operator<<(const char* t);
|
|
||||||
Log& operator<<(const QString& t);
|
|
||||||
Log& operator<<(const QStringList& t);
|
|
||||||
Log& operator<<(const QByteArray& t);
|
|
||||||
Log& operator<<(const QJsonObject& t);
|
|
||||||
Log& operator<<(QTextStreamFunction t);
|
|
||||||
Log& operator<<(const void* t);
|
|
||||||
|
|
||||||
// Q_ENUM
|
|
||||||
template <typename T>
|
|
||||||
typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, Log&>::type
|
|
||||||
operator<<(T t) {
|
|
||||||
const QMetaObject* meta = qt_getEnumMetaObject(t);
|
|
||||||
const char* name = qt_getEnumName(t);
|
|
||||||
addMetaEnum(typename QFlags<T>::Int(t), meta, name);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void addMetaEnum(quint64 value, const QMetaObject* meta, const char* name);
|
|
||||||
|
|
||||||
Logger* m_logger;
|
|
||||||
LogLevel m_logLevel;
|
|
||||||
|
|
||||||
struct Data {
|
|
||||||
Data() : m_ts(&m_buffer, QIODevice::WriteOnly) {}
|
|
||||||
|
|
||||||
QString m_buffer;
|
|
||||||
QTextStream m_ts;
|
|
||||||
};
|
|
||||||
|
|
||||||
Data* m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
Log error();
|
|
||||||
Log warning();
|
|
||||||
Log info();
|
|
||||||
Log debug();
|
|
||||||
QString sensitive(const QString& input);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Logger() {}
|
|
||||||
Logger(Logger const &) = delete;
|
|
||||||
Logger& operator= (Logger const&) = delete;
|
|
||||||
|
|
||||||
static QString userLogsDir();
|
|
||||||
|
|
||||||
static QFile m_file;
|
|
||||||
static QTextStream m_textStream;
|
|
||||||
static QString m_logFileName;
|
|
||||||
|
|
||||||
friend void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
|
|
||||||
|
|
||||||
// compat with Mozilla logger
|
|
||||||
QString m_className;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // LOGGER_H
|
|
||||||
@@ -149,7 +149,7 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
|||||||
QJsonArray jsAllowedIPAddesses;
|
QJsonArray jsAllowedIPAddesses;
|
||||||
|
|
||||||
QJsonArray plainAllowedIP = wgConfig.value(amnezia::config_key::allowed_ips).toArray();
|
QJsonArray plainAllowedIP = wgConfig.value(amnezia::config_key::allowed_ips).toArray();
|
||||||
QJsonArray defaultAllowedIP = QJsonArray::fromStringList(QString("0.0.0.0/0, ::/0").split(","));
|
QJsonArray defaultAllowedIP = { "0.0.0.0/0", "::/0" };
|
||||||
|
|
||||||
if (plainAllowedIP != defaultAllowedIP && !plainAllowedIP.isEmpty()) {
|
if (plainAllowedIP != defaultAllowedIP && !plainAllowedIP.isEmpty()) {
|
||||||
// Use AllowedIP list from WG config because of higher priority
|
// Use AllowedIP list from WG config because of higher priority
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ bool AndroidController::initialize()
|
|||||||
{"onStatisticsUpdate", "(JJ)V", reinterpret_cast<void *>(onStatisticsUpdate)},
|
{"onStatisticsUpdate", "(JJ)V", reinterpret_cast<void *>(onStatisticsUpdate)},
|
||||||
{"onFileOpened", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onFileOpened)},
|
{"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)},
|
||||||
|
{"onAuthResult", "(Z)V", reinterpret_cast<void *>(onAuthResult)},
|
||||||
{"decodeQrCode", "(Ljava/lang/String;)Z", reinterpret_cast<bool *>(decodeQrCode)}
|
{"decodeQrCode", "(Ljava/lang/String;)Z", reinterpret_cast<bool *>(decodeQrCode)}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -210,6 +211,11 @@ void AndroidController::setScreenshotsEnabled(bool enabled)
|
|||||||
callActivityMethod("setScreenshotsEnabled", "(Z)V", enabled);
|
callActivityMethod("setScreenshotsEnabled", "(Z)V", enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AndroidController::setNavigationBarColor(unsigned int color)
|
||||||
|
{
|
||||||
|
callActivityMethod("setNavigationBarColor", "(I)V", color);
|
||||||
|
}
|
||||||
|
|
||||||
void AndroidController::minimizeApp()
|
void AndroidController::minimizeApp()
|
||||||
{
|
{
|
||||||
callActivityMethod("minimizeApp", "()V");
|
callActivityMethod("minimizeApp", "()V");
|
||||||
@@ -265,6 +271,22 @@ void AndroidController::requestNotificationPermission()
|
|||||||
callActivityMethod("requestNotificationPermission", "()V");
|
callActivityMethod("requestNotificationPermission", "()V");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AndroidController::requestAuthentication()
|
||||||
|
{
|
||||||
|
QEventLoop wait;
|
||||||
|
bool result;
|
||||||
|
connect(this, &AndroidController::authenticationResult, this,
|
||||||
|
[&result, &wait](const bool &authResult){
|
||||||
|
qDebug() << "Android authentication result:" << authResult;
|
||||||
|
result = authResult;
|
||||||
|
wait.quit();
|
||||||
|
},
|
||||||
|
static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::SingleShotConnection));
|
||||||
|
callActivityMethod("requestAuthentication", "()V");
|
||||||
|
wait.exec();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Moving log processing to the Android side
|
// Moving log processing to the Android side
|
||||||
jclass AndroidController::log;
|
jclass AndroidController::log;
|
||||||
jmethodID AndroidController::logDebug;
|
jmethodID AndroidController::logDebug;
|
||||||
@@ -462,6 +484,14 @@ void AndroidController::onConfigImported(JNIEnv *env, jobject thiz, jstring data
|
|||||||
emit AndroidController::instance()->configImported(AndroidUtils::convertJString(env, data));
|
emit AndroidController::instance()->configImported(AndroidUtils::convertJString(env, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void AndroidController::onAuthResult(JNIEnv *env, jobject thiz, jboolean result)
|
||||||
|
{
|
||||||
|
Q_UNUSED(thiz);
|
||||||
|
|
||||||
|
emit AndroidController::instance()->authenticationResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool AndroidController::decodeQrCode(JNIEnv *env, jobject thiz, jstring data)
|
bool AndroidController::decodeQrCode(JNIEnv *env, jobject thiz, jstring data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,11 +41,13 @@ public:
|
|||||||
void exportLogsFile(const QString &fileName);
|
void exportLogsFile(const QString &fileName);
|
||||||
void clearLogs();
|
void clearLogs();
|
||||||
void setScreenshotsEnabled(bool enabled);
|
void setScreenshotsEnabled(bool enabled);
|
||||||
|
void setNavigationBarColor(unsigned int color);
|
||||||
void minimizeApp();
|
void minimizeApp();
|
||||||
QJsonArray getAppList();
|
QJsonArray getAppList();
|
||||||
QPixmap getAppIcon(const QString &package, QSize *size, const QSize &requestedSize);
|
QPixmap getAppIcon(const QString &package, QSize *size, const QSize &requestedSize);
|
||||||
bool isNotificationPermissionGranted();
|
bool isNotificationPermissionGranted();
|
||||||
void requestNotificationPermission();
|
void requestNotificationPermission();
|
||||||
|
bool requestAuthentication();
|
||||||
|
|
||||||
static bool initLogging();
|
static bool initLogging();
|
||||||
static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message);
|
static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message);
|
||||||
@@ -63,6 +65,7 @@ signals:
|
|||||||
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);
|
||||||
|
void authenticationResult(bool result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isWaitingStatus = true;
|
bool isWaitingStatus = true;
|
||||||
@@ -89,6 +92,7 @@ private:
|
|||||||
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 void onFileOpened(JNIEnv *env, jobject thiz, jstring uri);
|
||||||
|
static void onAuthResult(JNIEnv *env, jobject thiz, jboolean result);
|
||||||
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>
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
#include "authResultReceiver.h"
|
|
||||||
|
|
||||||
AuthResultReceiver::AuthResultReceiver(QSharedPointer<AuthResultNotifier> ¬ifier) : m_notifier(notifier)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthResultReceiver::handleActivityResult(int receiverRequestCode, int resultCode, const QJniObject &data)
|
|
||||||
{
|
|
||||||
qDebug() << "receiverRequestCode" << receiverRequestCode << "resultCode" << resultCode;
|
|
||||||
|
|
||||||
if (resultCode == -1) { // ResultOK
|
|
||||||
emit m_notifier->authSuccessful();
|
|
||||||
} else {
|
|
||||||
emit m_notifier->authFailed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#ifndef AUTHRESULTRECEIVER_H
|
|
||||||
#define AUTHRESULTRECEIVER_H
|
|
||||||
|
|
||||||
#include <QJniObject>
|
|
||||||
|
|
||||||
#include <private/qandroidextras_p.h>
|
|
||||||
|
|
||||||
class AuthResultNotifier : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
AuthResultNotifier(QObject *parent = nullptr) : QObject(parent) {};
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void authFailed();
|
|
||||||
void authSuccessful();
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Auth result handler for Android */
|
|
||||||
class AuthResultReceiver final : public QAndroidActivityResultReceiver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AuthResultReceiver(QSharedPointer<AuthResultNotifier> ¬ifier);
|
|
||||||
|
|
||||||
void handleActivityResult(int receiverRequestCode, int resultCode, const QJniObject &data) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QSharedPointer<AuthResultNotifier> m_notifier;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // AUTHRESULTRECEIVER_H
|
|
||||||
@@ -351,8 +351,6 @@ void IosController::vpnStatusDidChange(void *pNotification)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
qDebug() << "Disconnect error is absent";
|
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
@@ -501,6 +499,20 @@ bool IosController::setupWireGuard()
|
|||||||
wgConfig.insert(config_key::persistent_keep_alive, "25");
|
wgConfig.insert(config_key::persistent_keep_alive, "25");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.contains(config_key::isObfuscationEnabled) && config.value(config_key::isObfuscationEnabled).toBool()) {
|
||||||
|
wgConfig.insert(config_key::initPacketMagicHeader, config[config_key::initPacketMagicHeader]);
|
||||||
|
wgConfig.insert(config_key::responsePacketMagicHeader, config[config_key::responsePacketMagicHeader]);
|
||||||
|
wgConfig.insert(config_key::underloadPacketMagicHeader, config[config_key::underloadPacketMagicHeader]);
|
||||||
|
wgConfig.insert(config_key::transportPacketMagicHeader, config[config_key::transportPacketMagicHeader]);
|
||||||
|
|
||||||
|
wgConfig.insert(config_key::initPacketJunkSize, config[config_key::initPacketJunkSize]);
|
||||||
|
wgConfig.insert(config_key::responsePacketJunkSize, config[config_key::responsePacketJunkSize]);
|
||||||
|
|
||||||
|
wgConfig.insert(config_key::junkPacketCount, config[config_key::junkPacketCount]);
|
||||||
|
wgConfig.insert(config_key::junkPacketMinSize, config[config_key::junkPacketMinSize]);
|
||||||
|
wgConfig.insert(config_key::junkPacketMaxSize, config[config_key::junkPacketMaxSize]);
|
||||||
|
}
|
||||||
|
|
||||||
QJsonDocument wgConfigDoc(wgConfig);
|
QJsonDocument wgConfigDoc(wgConfig);
|
||||||
QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact));
|
QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
@@ -835,7 +847,7 @@ QString IosController::openFile() {
|
|||||||
|
|
||||||
void IosController::requestInetAccess() {
|
void IosController::requestInetAccess() {
|
||||||
NSURL *url = [NSURL URLWithString:@"http://captive.apple.com/generate_204"];
|
NSURL *url = [NSURL URLWithString:@"http://captive.apple.com/generate_204"];
|
||||||
if (url) {
|
if (!url) {
|
||||||
qDebug() << "IosController::requestInetAccess URL error";
|
qDebug() << "IosController::requestInetAccess URL error";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -847,7 +859,6 @@ void IosController::requestInetAccess() {
|
|||||||
} else {
|
} else {
|
||||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
|
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
|
||||||
QString responseBody = QString::fromUtf8((const char*)data.bytes, data.length);
|
QString responseBody = QString::fromUtf8((const char*)data.bytes, data.length);
|
||||||
qDebug() << "IosController::requestInetAccess server response:" << httpResponse.statusCode << "\n\n" <<responseBody;
|
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
[task resume];
|
[task resume];
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#include <QNetworkInterface>
|
#include <QNetworkInterface>
|
||||||
|
|
||||||
|
#include "core/networkUtilities.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "openvpnprotocol.h"
|
#include "openvpnprotocol.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
@@ -127,7 +128,6 @@ void OpenVpnProtocol::sendManagementCommand(const QString &command)
|
|||||||
|
|
||||||
uint OpenVpnProtocol::selectMgmtPort()
|
uint OpenVpnProtocol::selectMgmtPort()
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int i = 0; i < 100; ++i) {
|
for (int i = 0; i < 100; ++i) {
|
||||||
quint32 port = QRandomGenerator::global()->generate();
|
quint32 port = QRandomGenerator::global()->generate();
|
||||||
port = (double)(65000 - 15001) * port / UINT32_MAX + 15001;
|
port = (double)(65000 - 15001) * port / UINT32_MAX + 15001;
|
||||||
@@ -137,7 +137,6 @@ uint OpenVpnProtocol::selectMgmtPort()
|
|||||||
if (ok)
|
if (ok)
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_managementPort;
|
return m_managementPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +342,8 @@ void OpenVpnProtocol::updateVpnGateway(const QString &line)
|
|||||||
}
|
}
|
||||||
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
|
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
|
||||||
m_configData.insert("vpnGateway", m_vpnGateway);
|
m_configData.insert("vpnGateway", m_vpnGateway);
|
||||||
m_configData.insert("vpnServer", m_configData.value(amnezia::config_key::hostName).toString());
|
m_configData.insert("vpnServer",
|
||||||
|
NetworkUtilities::getIPAddress(m_configData.value(amnezia::config_key::hostName).toString()));
|
||||||
IpcClient::Interface()->enablePeerTraffic(m_configData);
|
IpcClient::Interface()->enablePeerTraffic(m_configData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,6 +352,8 @@ void OpenVpnProtocol::updateVpnGateway(const QString &line)
|
|||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
||||||
// killSwitch toggle
|
// killSwitch toggle
|
||||||
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
|
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
|
||||||
|
m_configData.insert("vpnServer",
|
||||||
|
NetworkUtilities::getIPAddress(m_configData.value(amnezia::config_key::hostName).toString()));
|
||||||
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
|
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ namespace amnezia
|
|||||||
constexpr char last_config[] = "last_config";
|
constexpr char last_config[] = "last_config";
|
||||||
|
|
||||||
constexpr char isThirdPartyConfig[] = "isThirdPartyConfig";
|
constexpr char isThirdPartyConfig[] = "isThirdPartyConfig";
|
||||||
|
constexpr char isObfuscationEnabled[] = "isObfuscationEnabled";
|
||||||
|
|
||||||
constexpr char junkPacketCount[] = "Jc";
|
constexpr char junkPacketCount[] = "Jc";
|
||||||
constexpr char junkPacketMinSize[] = "Jmin";
|
constexpr char junkPacketMinSize[] = "Jmin";
|
||||||
|
|||||||
@@ -4,9 +4,8 @@
|
|||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#include "logger.h"
|
|
||||||
#include "utilities.h"
|
|
||||||
#include "wireguardprotocol.h"
|
#include "wireguardprotocol.h"
|
||||||
|
#include "core/networkUtilities.h"
|
||||||
|
|
||||||
#include "mozilla/localsocketcontroller.h"
|
#include "mozilla/localsocketcontroller.h"
|
||||||
|
|
||||||
@@ -37,6 +36,12 @@ void WireguardProtocol::stop()
|
|||||||
|
|
||||||
ErrorCode WireguardProtocol::startMzImpl()
|
ErrorCode WireguardProtocol::startMzImpl()
|
||||||
{
|
{
|
||||||
|
QString protocolName = m_rawConfig.value("protocol").toString();
|
||||||
|
QJsonObject vpnConfigData = m_rawConfig.value(protocolName + "_config_data").toObject();
|
||||||
|
vpnConfigData[config_key::hostName] = NetworkUtilities::getIPAddress(vpnConfigData.value(config_key::hostName).toString());
|
||||||
|
m_rawConfig.insert(protocolName + "_config_data", vpnConfigData);
|
||||||
|
m_rawConfig[config_key::hostName] = NetworkUtilities::getIPAddress(m_rawConfig[config_key::hostName].toString());
|
||||||
|
|
||||||
m_impl->activate(m_rawConfig);
|
m_impl->activate(m_rawConfig);
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
}
|
}
|
||||||
|
|||||||
Regular → Executable
+23
-55
@@ -17,6 +17,7 @@ XrayProtocol::XrayProtocol(const QJsonObject &configuration, QObject *parent):
|
|||||||
m_routeGateway = NetworkUtilities::getGatewayAndIface();
|
m_routeGateway = NetworkUtilities::getGatewayAndIface();
|
||||||
m_vpnGateway = amnezia::protocols::xray::defaultLocalAddr;
|
m_vpnGateway = amnezia::protocols::xray::defaultLocalAddr;
|
||||||
m_vpnLocalAddress = amnezia::protocols::xray::defaultLocalAddr;
|
m_vpnLocalAddress = amnezia::protocols::xray::defaultLocalAddr;
|
||||||
|
m_t2sProcess = IpcClient::InterfaceTun2Socks();
|
||||||
}
|
}
|
||||||
|
|
||||||
XrayProtocol::~XrayProtocol()
|
XrayProtocol::~XrayProtocol()
|
||||||
@@ -43,7 +44,9 @@ ErrorCode XrayProtocol::start()
|
|||||||
m_xrayCfgFile.setAutoRemove(false);
|
m_xrayCfgFile.setAutoRemove(false);
|
||||||
#endif
|
#endif
|
||||||
m_xrayCfgFile.open();
|
m_xrayCfgFile.open();
|
||||||
m_xrayCfgFile.write(QJsonDocument(m_xrayConfig).toJson());
|
QString config = QJsonDocument(m_xrayConfig).toJson();
|
||||||
|
config.replace(m_remoteHost, m_remoteAddress);
|
||||||
|
m_xrayCfgFile.write(config.toUtf8());
|
||||||
m_xrayCfgFile.close();
|
m_xrayCfgFile.close();
|
||||||
|
|
||||||
QStringList args = QStringList() << "-c" << m_xrayCfgFile.fileName() << "-format=json";
|
QStringList args = QStringList() << "-c" << m_xrayCfgFile.fileName() << "-format=json";
|
||||||
@@ -63,7 +66,7 @@ ErrorCode XrayProtocol::start()
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(&m_xrayProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
|
connect(&m_xrayProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||||
qDebug().noquote() << "XrayProtocol finished, exitCode, exiStatus" << exitCode << exitStatus;
|
qDebug().noquote() << "XrayProtocol finished, exitCode, exitStatus" << exitCode << exitStatus;
|
||||||
setConnectionState(Vpn::ConnectionState::Disconnected);
|
setConnectionState(Vpn::ConnectionState::Disconnected);
|
||||||
if (exitStatus != QProcess::NormalExit) {
|
if (exitStatus != QProcess::NormalExit) {
|
||||||
emit protocolError(amnezia::ErrorCode::XrayExecutableCrashed);
|
emit protocolError(amnezia::ErrorCode::XrayExecutableCrashed);
|
||||||
@@ -89,63 +92,32 @@ ErrorCode XrayProtocol::start()
|
|||||||
|
|
||||||
ErrorCode XrayProtocol::startTun2Sock()
|
ErrorCode XrayProtocol::startTun2Sock()
|
||||||
{
|
{
|
||||||
if (!QFileInfo::exists(Utils::tun2socksPath())) {
|
m_t2sProcess->start();
|
||||||
setLastError(ErrorCode::Tun2SockExecutableMissing);
|
|
||||||
return lastError();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_t2sProcess = IpcClient::CreatePrivilegedProcess();
|
|
||||||
|
|
||||||
if (!m_t2sProcess) {
|
|
||||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
|
||||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_t2sProcess->waitForSource(1000);
|
|
||||||
if (!m_t2sProcess->isInitialized()) {
|
|
||||||
qWarning() << "IpcProcess replica is not connected!";
|
|
||||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
|
||||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString XrayConStr = "socks5://127.0.0.1:" + QString::number(m_localPort);
|
|
||||||
|
|
||||||
m_t2sProcess->setProgram(PermittedProcess::Tun2Socks);
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
m_configData.insert("inetAdapterIndex", NetworkUtilities::AdapterIndexTo(QHostAddress(m_remoteAddress)));
|
m_configData.insert("inetAdapterIndex", NetworkUtilities::AdapterIndexTo(QHostAddress(m_remoteAddress)));
|
||||||
QStringList arguments({"-device", "tun://tun2", "-proxy", XrayConStr, "-tun-post-up",
|
|
||||||
QString("cmd /c netsh interface ip set address name=\"tun2\" static %1 255.255.255.255").arg(amnezia::protocols::xray::defaultLocalAddr)});
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
QStringList arguments({"-device", "tun://tun2", "-proxy", XrayConStr});
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
QStringList arguments({"-device", "utun22", "-proxy", XrayConStr});
|
|
||||||
#endif
|
|
||||||
m_t2sProcess->setArguments(arguments);
|
|
||||||
|
|
||||||
qDebug() << arguments.join(" ");
|
connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::stateChanged, this,
|
||||||
connect(m_t2sProcess.data(), &PrivilegedProcess::errorOccurred,
|
[&](QProcess::ProcessState newState) { qDebug() << "PrivilegedProcess stateChanged" << newState; });
|
||||||
[&](QProcess::ProcessError error) { qDebug() << "PrivilegedProcess errorOccurred" << error; });
|
|
||||||
|
|
||||||
connect(m_t2sProcess.data(), &PrivilegedProcess::stateChanged,
|
connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::setConnectionState, this,
|
||||||
[&](QProcess::ProcessState newState) {
|
[&](int vpnState) {
|
||||||
qDebug() << "PrivilegedProcess stateChanged" << newState;
|
qDebug() << "PrivilegedProcess setConnectionState " << vpnState;
|
||||||
if (newState == QProcess::Running)
|
if (vpnState == Vpn::ConnectionState::Connected)
|
||||||
{
|
{
|
||||||
setConnectionState(Vpn::ConnectionState::Connecting);
|
setConnectionState(Vpn::ConnectionState::Connecting);
|
||||||
QList<QHostAddress> dnsAddr;
|
QList<QHostAddress> dnsAddr;
|
||||||
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns1).toString()));
|
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns1).toString()));
|
||||||
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns2).toString()));
|
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns2).toString()));
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QThread::msleep(8000);
|
||||||
|
#endif
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
QThread::msleep(5000);
|
QThread::msleep(5000);
|
||||||
IpcClient::Interface()->createTun("utun22", amnezia::protocols::xray::defaultLocalAddr);
|
IpcClient::Interface()->createTun("utun22", amnezia::protocols::xray::defaultLocalAddr);
|
||||||
IpcClient::Interface()->updateResolvers("utun22", dnsAddr);
|
IpcClient::Interface()->updateResolvers("utun22", dnsAddr);
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q_OS_WINDOWS
|
|
||||||
QThread::msleep(15000);
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
QThread::msleep(1000);
|
QThread::msleep(1000);
|
||||||
IpcClient::Interface()->createTun("tun2", amnezia::protocols::xray::defaultLocalAddr);
|
IpcClient::Interface()->createTun("tun2", amnezia::protocols::xray::defaultLocalAddr);
|
||||||
@@ -154,6 +126,7 @@ ErrorCode XrayProtocol::startTun2Sock()
|
|||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
||||||
// killSwitch toggle
|
// killSwitch toggle
|
||||||
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
|
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
|
||||||
|
m_configData.insert("vpnServer", m_remoteAddress);
|
||||||
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
|
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -167,7 +140,7 @@ ErrorCode XrayProtocol::startTun2Sock()
|
|||||||
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
|
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
|
||||||
QList<QNetworkInterface> netInterfaces = QNetworkInterface::allInterfaces();
|
QList<QNetworkInterface> netInterfaces = QNetworkInterface::allInterfaces();
|
||||||
for (int i = 0; i < netInterfaces.size(); i++) {
|
for (int i = 0; i < netInterfaces.size(); i++) {
|
||||||
for (int j=0; j < netInterfaces.at(i).addressEntries().size(); j++)
|
for (int j = 0; j < netInterfaces.at(i).addressEntries().size(); j++)
|
||||||
{
|
{
|
||||||
// killSwitch toggle
|
// killSwitch toggle
|
||||||
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
|
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
|
||||||
@@ -184,21 +157,15 @@ ErrorCode XrayProtocol::startTun2Sock()
|
|||||||
#endif
|
#endif
|
||||||
setConnectionState(Vpn::ConnectionState::Connected);
|
setConnectionState(Vpn::ConnectionState::Connected);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(Q_OS_MACOS)
|
#if !defined(Q_OS_MACOS)
|
||||||
connect(m_t2sProcess.data(), &PrivilegedProcess::finished, this,
|
if (vpnState == Vpn::ConnectionState::Disconnected) {
|
||||||
[&]() {
|
|
||||||
setConnectionState(Vpn::ConnectionState::Disconnected);
|
setConnectionState(Vpn::ConnectionState::Disconnected);
|
||||||
IpcClient::Interface()->deleteTun("tun2");
|
IpcClient::Interface()->deleteTun("tun2");
|
||||||
IpcClient::Interface()->StartRoutingIpv6();
|
IpcClient::Interface()->StartRoutingIpv6();
|
||||||
IpcClient::Interface()->clearSavedRoutes();
|
IpcClient::Interface()->clearSavedRoutes();
|
||||||
});
|
}
|
||||||
#endif
|
#endif
|
||||||
|
});
|
||||||
m_t2sProcess->start();
|
|
||||||
|
|
||||||
|
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
}
|
}
|
||||||
@@ -212,7 +179,7 @@ void XrayProtocol::stop()
|
|||||||
qDebug() << "XrayProtocol::stop()";
|
qDebug() << "XrayProtocol::stop()";
|
||||||
m_xrayProcess.terminate();
|
m_xrayProcess.terminate();
|
||||||
if (m_t2sProcess) {
|
if (m_t2sProcess) {
|
||||||
m_t2sProcess->close();
|
m_t2sProcess->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
@@ -238,7 +205,8 @@ void XrayProtocol::readXrayConfiguration(const QJsonObject &configuration)
|
|||||||
}
|
}
|
||||||
m_xrayConfig = xrayConfiguration;
|
m_xrayConfig = xrayConfiguration;
|
||||||
m_localPort = QString(amnezia::protocols::xray::defaultLocalProxyPort).toInt();
|
m_localPort = QString(amnezia::protocols::xray::defaultLocalProxyPort).toInt();
|
||||||
m_remoteAddress = configuration.value(amnezia::config_key::hostName).toString();
|
m_remoteHost = configuration.value(amnezia::config_key::hostName).toString();
|
||||||
|
m_remoteAddress = NetworkUtilities::getIPAddress(m_remoteHost);
|
||||||
m_routeMode = configuration.value(amnezia::config_key::splitTunnelType).toInt();
|
m_routeMode = configuration.value(amnezia::config_key::splitTunnelType).toInt();
|
||||||
m_primaryDNS = configuration.value(amnezia::config_key::dns1).toString();
|
m_primaryDNS = configuration.value(amnezia::config_key::dns1).toString();
|
||||||
m_secondaryDNS = configuration.value(amnezia::config_key::dns2).toString();
|
m_secondaryDNS = configuration.value(amnezia::config_key::dns2).toString();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ private:
|
|||||||
static QString tun2SocksExecPath();
|
static QString tun2SocksExecPath();
|
||||||
private:
|
private:
|
||||||
int m_localPort;
|
int m_localPort;
|
||||||
|
QString m_remoteHost;
|
||||||
QString m_remoteAddress;
|
QString m_remoteAddress;
|
||||||
int m_routeMode;
|
int m_routeMode;
|
||||||
QJsonObject m_configData;
|
QJsonObject m_configData;
|
||||||
@@ -33,9 +34,10 @@ private:
|
|||||||
QString m_secondaryDNS;
|
QString m_secondaryDNS;
|
||||||
#ifndef Q_OS_IOS
|
#ifndef Q_OS_IOS
|
||||||
QProcess m_xrayProcess;
|
QProcess m_xrayProcess;
|
||||||
QSharedPointer<PrivilegedProcess> m_t2sProcess;
|
QSharedPointer<IpcProcessTun2SocksReplica> m_t2sProcess;
|
||||||
#endif
|
#endif
|
||||||
QTemporaryFile m_xrayCfgFile;
|
QTemporaryFile m_xrayCfgFile;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // XRAYPROTOCOL_H
|
#endif // XRAYPROTOCOL_H
|
||||||
|
|||||||
@@ -199,6 +199,8 @@
|
|||||||
<file>server_scripts/socks5_proxy/Dockerfile</file>
|
<file>server_scripts/socks5_proxy/Dockerfile</file>
|
||||||
<file>server_scripts/socks5_proxy/configure_container.sh</file>
|
<file>server_scripts/socks5_proxy/configure_container.sh</file>
|
||||||
<file>server_scripts/socks5_proxy/start.sh</file>
|
<file>server_scripts/socks5_proxy/start.sh</file>
|
||||||
|
<file>ui/qml/Pages2/PageProtocolAwgClientSettings.qml</file>
|
||||||
|
<file>ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSetupWizardApiServicesList.qml</file>
|
<file>ui/qml/Pages2/PageSetupWizardApiServicesList.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml</file>
|
<file>ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml</file>
|
||||||
<file>ui/qml/Controls2/CardWithIconsType.qml</file>
|
<file>ui/qml/Controls2/CardWithIconsType.qml</file>
|
||||||
|
|||||||
@@ -174,13 +174,25 @@ bool SecureQSettings::restoreAppConfig(const QByteArray &json)
|
|||||||
QByteArray SecureQSettings::encryptText(const QByteArray &value) const
|
QByteArray SecureQSettings::encryptText(const QByteArray &value) const
|
||||||
{
|
{
|
||||||
QSimpleCrypto::QBlockCipher cipher;
|
QSimpleCrypto::QBlockCipher cipher;
|
||||||
return cipher.encryptAesBlockCipher(value, getEncKey(), getEncIv());
|
QByteArray result;
|
||||||
|
try {
|
||||||
|
result = cipher.encryptAesBlockCipher(value, getEncKey(), getEncIv());
|
||||||
|
} catch (...) { // todo change error handling in QSimpleCrypto?
|
||||||
|
qCritical() << "error when encrypting the settings value";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray SecureQSettings::decryptText(const QByteArray &ba) const
|
QByteArray SecureQSettings::decryptText(const QByteArray &ba) const
|
||||||
{
|
{
|
||||||
QSimpleCrypto::QBlockCipher cipher;
|
QSimpleCrypto::QBlockCipher cipher;
|
||||||
return cipher.decryptAesBlockCipher(ba, getEncKey(), getEncIv());
|
QByteArray result;
|
||||||
|
try {
|
||||||
|
result = cipher.decryptAesBlockCipher(ba, getEncKey(), getEncIv());
|
||||||
|
} catch (...) { // todo change error handling in QSimpleCrypto?
|
||||||
|
qCritical() << "error when decrypting the settings value";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SecureQSettings::encryptionRequired() const
|
bool SecureQSettings::encryptionRequired() const
|
||||||
|
|||||||
@@ -13,5 +13,5 @@ sudo docker network connect amnezia-dns-net $CONTAINER_NAME
|
|||||||
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi'
|
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi'
|
||||||
|
|
||||||
# Prevent to route packets outside of the container in case if server behind of the NAT
|
# Prevent to route packets outside of the container in case if server behind of the NAT
|
||||||
sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
#sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||||
|
|
||||||
echo "Container startup"
|
echo "Container startup"
|
||||||
ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
|
#ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
|
||||||
|
|
||||||
iptables -A INPUT -i lo -j ACCEPT
|
iptables -A INPUT -i lo -j ACCEPT
|
||||||
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
|||||||
+16
-1
@@ -227,7 +227,7 @@ void Settings::setSaveLogs(bool enabled)
|
|||||||
if (!isSaveLogs()) {
|
if (!isSaveLogs()) {
|
||||||
Logger::deInit();
|
Logger::deInit();
|
||||||
} else {
|
} else {
|
||||||
if (!Logger::init()) {
|
if (!Logger::init(false)) {
|
||||||
qWarning() << "Initialization of debug subsystem failed";
|
qWarning() << "Initialization of debug subsystem failed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -519,7 +519,22 @@ void Settings::setGatewayEndpoint(const QString &endpoint)
|
|||||||
m_gatewayEndpoint = endpoint;
|
m_gatewayEndpoint = endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Settings::setDevGatewayEndpoint()
|
||||||
|
{
|
||||||
|
m_gatewayEndpoint = DEV_AGW_ENDPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
QString Settings::getGatewayEndpoint()
|
QString Settings::getGatewayEndpoint()
|
||||||
{
|
{
|
||||||
return m_gatewayEndpoint;
|
return m_gatewayEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Settings::isDevGatewayEnv()
|
||||||
|
{
|
||||||
|
return m_isDevGatewayEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::toggleDevGatewayEnv(bool enabled)
|
||||||
|
{
|
||||||
|
m_isDevGatewayEnv = enabled;
|
||||||
|
}
|
||||||
|
|||||||
@@ -217,7 +217,10 @@ public:
|
|||||||
|
|
||||||
void resetGatewayEndpoint();
|
void resetGatewayEndpoint();
|
||||||
void setGatewayEndpoint(const QString &endpoint);
|
void setGatewayEndpoint(const QString &endpoint);
|
||||||
|
void setDevGatewayEndpoint();
|
||||||
QString getGatewayEndpoint();
|
QString getGatewayEndpoint();
|
||||||
|
bool isDevGatewayEnv();
|
||||||
|
void toggleDevGatewayEnv(bool enabled);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void saveLogsChanged(bool enabled);
|
void saveLogsChanged(bool enabled);
|
||||||
@@ -234,6 +237,7 @@ private:
|
|||||||
mutable SecureQSettings m_settings;
|
mutable SecureQSettings m_settings;
|
||||||
|
|
||||||
QString m_gatewayEndpoint;
|
QString m_gatewayEndpoint;
|
||||||
|
bool m_isDevGatewayEnv = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SETTINGS_H
|
#endif // SETTINGS_H
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,47 +4,52 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ApiServicesModel</name>
|
<name>ApiServicesModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="63"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||||
|
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="75"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||||
<source>%1 MBit/s</source>
|
<source>%1 MBit/s</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||||
<source>%1 days</source>
|
<source>%1 days</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||||
<source>Free</source>
|
<source>Free</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||||
<source>%1 $/month</source>
|
<source>%1 $/month</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -75,7 +80,7 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ConnectButton</name>
|
<name>ConnectButton</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Components/ConnectButton.qml" line="27"/>
|
<location filename="../ui/qml/Components/ConnectButton.qml" line="28"/>
|
||||||
<source>Unable to disconnect during configuration preparation</source>
|
<source>Unable to disconnect during configuration preparation</source>
|
||||||
<translation>कॉन्फ़िगरेशन तैयारी के दौरान डिस्कनेक्ट करने में असमर्थ</translation>
|
<translation>कॉन्फ़िगरेशन तैयारी के दौरान डिस्कनेक्ट करने में असमर्थ</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -187,9 +192,8 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ExportController</name>
|
<name>ExportController</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/exportController.cpp" line="30"/>
|
|
||||||
<source>Access error!</source>
|
<source>Access error!</source>
|
||||||
<translation>प्रवेश त्रुटि!</translation>
|
<translation type="vanished">प्रवेश त्रुटि!</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -255,18 +259,18 @@ Can't be disabled for current server</source>
|
|||||||
<translation>फाइल खोलने में असमर्थ</translation>
|
<translation>फाइल खोलने में असमर्थ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="186"/>
|
<location filename="../ui/controllers/importController.cpp" line="187"/>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="191"/>
|
<location filename="../ui/controllers/importController.cpp" line="192"/>
|
||||||
<source>Invalid configuration file</source>
|
<source>Invalid configuration file</source>
|
||||||
<translation>अमान्य कॉन्फ़िगरेशन फ़ाइल</translation>
|
<translation>अमान्य कॉन्फ़िगरेशन फ़ाइल</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="606"/>
|
<location filename="../ui/controllers/importController.cpp" line="617"/>
|
||||||
<source>Scanned %1 of %2.</source>
|
<source>Scanned %1 of %2.</source>
|
||||||
<translation>%2 में से %1 स्कैन किया गया.</translation>
|
<translation>%2 में से %1 स्कैन किया गया.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="641"/>
|
<location filename="../ui/controllers/importController.cpp" line="652"/>
|
||||||
<source>In the imported configuration, potentially dangerous lines were found:</source>
|
<source>In the imported configuration, potentially dangerous lines were found:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -443,6 +447,11 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<source>Gateway endpoint</source>
|
<source>Gateway endpoint</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="101"/>
|
||||||
|
<source>Dev gateway environment</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageHome</name>
|
<name>PageHome</name>
|
||||||
@@ -477,10 +486,63 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>सक्रिय कनेक्शन होने पर सर्वर बदलने में असमर्थ</translation>
|
<translation>सक्रिय कनेक्शन होने पर सर्वर बदलने में असमर्थ</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>PageProtocolAwgClientSettings</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="96"/>
|
||||||
|
<source>AmneziaWG settings</source>
|
||||||
|
<translation type="unfinished">Amneziaडब्ल्यूजी सेटिंग्स</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="104"/>
|
||||||
|
<source>MTU</source>
|
||||||
|
<translation type="unfinished">एमटीयू</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="184"/>
|
||||||
|
<source>Server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="194"/>
|
||||||
|
<source>Port</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="284"/>
|
||||||
|
<source>Save</source>
|
||||||
|
<translation type="unfinished">सहेजें</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="290"/>
|
||||||
|
<source>Save settings?</source>
|
||||||
|
<translation type="unfinished">सेटिंग्स सेव करें?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="291"/>
|
||||||
|
<source>Only the settings for this device will be changed</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="292"/>
|
||||||
|
<source>Continue</source>
|
||||||
|
<translation type="unfinished">जारी रखना</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="293"/>
|
||||||
|
<source>Cancel</source>
|
||||||
|
<translation type="unfinished">रद्द करना</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="297"/>
|
||||||
|
<source>Unable change settings while there is an active connection</source>
|
||||||
|
<translation type="unfinished">सक्रिय कनेक्शन होने पर सेटिंग बदलने में असमर्थ</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageProtocolAwgSettings</name>
|
<name>PageProtocolAwgSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="96"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="94"/>
|
||||||
<source>AmneziaWG settings</source>
|
<source>AmneziaWG settings</source>
|
||||||
<translation>Amneziaडब्ल्यूजी सेटिंग्स</translation>
|
<translation>Amneziaडब्ल्यूजी सेटिंग्स</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -490,92 +552,91 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>पोर्ट</translation>
|
<translation>पोर्ट</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
|
|
||||||
<source>MTU</source>
|
<source>MTU</source>
|
||||||
<translation>एमटीयू</translation>
|
<translation type="vanished">एमटीयू</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="147"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
|
||||||
<source>Jc - Junk packet count</source>
|
<source>Jc - Junk packet count</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="151"/>
|
||||||
<source>Jmin - Junk packet minimum size</source>
|
<source>Jmin - Junk packet minimum size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
|
||||||
<source>Jmax - Junk packet maximum size</source>
|
<source>Jmax - Junk packet maximum size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
|
||||||
<source>S1 - Init packet junk size</source>
|
<source>S1 - Init packet junk size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
|
||||||
<source>S2 - Response packet junk size</source>
|
<source>S2 - Response packet junk size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
|
||||||
<source>H1 - Init packet magic header</source>
|
<source>H1 - Init packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
|
||||||
<source>H2 - Response packet magic header</source>
|
<source>H2 - Response packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="298"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
|
||||||
<source>H4 - Transport packet magic header</source>
|
<source>H4 - Transport packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="320"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="299"/>
|
||||||
<source>H3 - Underload packet magic header</source>
|
<source>H3 - Underload packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="354"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="333"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>सहेजें</translation>
|
<translation>सहेजें</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="345"/>
|
||||||
<source>The values of the H1-H4 fields must be unique</source>
|
<source>The values of the H1-H4 fields must be unique</source>
|
||||||
<translation>H1-H4 फ़ील्ड का मान अद्वितीय होना चाहिए</translation>
|
<translation>H1-H4 फ़ील्ड का मान अद्वितीय होना चाहिए</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="369"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="351"/>
|
||||||
<source>The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)</source>
|
<source>The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)</source>
|
||||||
<translation>फ़ील्ड S1 + संदेश आरंभ आकार (148) का मान S2 + संदेश प्रतिक्रिया आकार (92) के बराबर नहीं होना चाहिए</translation>
|
<translation>फ़ील्ड S1 + संदेश आरंभ आकार (148) का मान S2 + संदेश प्रतिक्रिया आकार (92) के बराबर नहीं होना चाहिए</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="373"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="356"/>
|
||||||
<source>Save settings?</source>
|
<source>Save settings?</source>
|
||||||
<translation>सेटिंग्स सेव करें?</translation>
|
<translation>सेटिंग्स सेव करें?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="374"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="357"/>
|
||||||
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
||||||
<translation>वे सभी उपयोगकर्ता जिनके साथ आपने कनेक्शन साझा किया था, वे अब इससे कनेक्ट नहीं हो पाएंगे.</translation>
|
<translation>वे सभी उपयोगकर्ता जिनके साथ आपने कनेक्शन साझा किया था, वे अब इससे कनेक्ट नहीं हो पाएंगे.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="382"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>सक्रिय कनेक्शन होने पर सेटिंग बदलने में असमर्थ</translation>
|
<translation>सक्रिय कनेक्शन होने पर सेटिंग बदलने में असमर्थ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="375"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="358"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>जारी रखना</translation>
|
<translation>जारी रखना</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="376"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="359"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>रद्द करना</translation>
|
<translation>रद्द करना</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -862,30 +923,102 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>सक्रिय कनेक्शन होने पर सेटिंग बदलने में असमर्थ</translation>
|
<translation>सक्रिय कनेक्शन होने पर सेटिंग बदलने में असमर्थ</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>PageProtocolWireGuardClientSettings</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="93"/>
|
||||||
|
<source>WG settings</source>
|
||||||
|
<translation type="unfinished">डब्ल्यूजी सेटिंग्स</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="101"/>
|
||||||
|
<source>MTU</source>
|
||||||
|
<translation type="unfinished">एमटीयू</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="118"/>
|
||||||
|
<source>Server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="128"/>
|
||||||
|
<source>Port</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="151"/>
|
||||||
|
<source>Save</source>
|
||||||
|
<translation type="unfinished">सहेजें</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="157"/>
|
||||||
|
<source>Save settings?</source>
|
||||||
|
<translation type="unfinished">सेटिंग्स सेव करें?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="158"/>
|
||||||
|
<source>Only the settings for this device will be changed</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="159"/>
|
||||||
|
<source>Continue</source>
|
||||||
|
<translation type="unfinished">जारी रखना</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="160"/>
|
||||||
|
<source>Cancel</source>
|
||||||
|
<translation type="unfinished">रद्द करना</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="164"/>
|
||||||
|
<source>Unable change settings while there is an active connection</source>
|
||||||
|
<translation type="unfinished">सक्रिय कनेक्शन होने पर सेटिंग बदलने में असमर्थ</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageProtocolWireGuardSettings</name>
|
<name>PageProtocolWireGuardSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="94"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="97"/>
|
||||||
<source>WG settings</source>
|
<source>WG settings</source>
|
||||||
<translation>डब्ल्यूजी सेटिंग्स</translation>
|
<translation>डब्ल्यूजी सेटिंग्स</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="102"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="107"/>
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
<translation>बंदरगाह</translation>
|
<translation>बंदरगाह</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="123"/>
|
|
||||||
<source>MTU</source>
|
<source>MTU</source>
|
||||||
<translation>एमटीयू</translation>
|
<translation type="vanished">एमटीयू</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="149"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="131"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>सहेजें</translation>
|
<translation>सहेजें</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="157"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="138"/>
|
||||||
|
<source>Save settings?</source>
|
||||||
|
<translation type="unfinished">सेटिंग्स सेव करें?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="139"/>
|
||||||
|
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
||||||
|
<translation type="unfinished">वे सभी उपयोगकर्ता जिनके साथ आपने कनेक्शन साझा किया था, वे अब इससे कनेक्ट नहीं हो पाएंगे.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="140"/>
|
||||||
|
<source>Continue</source>
|
||||||
|
<translation type="unfinished">जारी रखना</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="141"/>
|
||||||
|
<source>Cancel</source>
|
||||||
|
<translation type="unfinished">रद्द करना</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="145"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>सक्रिय कनेक्शन होने पर सेटिंग बदलने में असमर्थ</translation>
|
<translation>सक्रिय कनेक्शन होने पर सेटिंग बदलने में असमर्थ</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1237,9 +1370,13 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
|
|
||||||
<source>Mail</source>
|
<source>Mail</source>
|
||||||
<translation>मेल</translation>
|
<translation type="vanished">मेल</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
|
||||||
|
<source>support@amnezia.org</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
|
||||||
@@ -1247,32 +1384,37 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>समीक्षाओं और बग रिपोर्टों के लिए</translation>
|
<translation>समीक्षाओं और बग रिपोर्टों के लिए</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="141"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="132"/>
|
||||||
|
<source>Copied</source>
|
||||||
|
<translation type="unfinished">कॉपी किया गया</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="143"/>
|
||||||
<source>GitHub</source>
|
<source>GitHub</source>
|
||||||
<translation>GitHub</translation>
|
<translation>GitHub</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="148"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="150"/>
|
||||||
<source>https://github.com/amnezia-vpn/amnezia-client</source>
|
<source>https://github.com/amnezia-vpn/amnezia-client</source>
|
||||||
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
|
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="159"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="161"/>
|
||||||
<source>Website</source>
|
<source>Website</source>
|
||||||
<translation>वेबसाइट</translation>
|
<translation>वेबसाइट</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="179"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="181"/>
|
||||||
<source>Software version: %1</source>
|
<source>Software version: %1</source>
|
||||||
<translation>सॉफ़्टवेयर संस्करण: %1</translation>
|
<translation>सॉफ़्टवेयर संस्करण: %1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="208"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="210"/>
|
||||||
<source>Check for updates</source>
|
<source>Check for updates</source>
|
||||||
<translation>अद्यतन के लिए जाँच</translation>
|
<translation>अद्यतन के लिए जाँच</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="231"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="233"/>
|
||||||
<source>Privacy Policy</source>
|
<source>Privacy Policy</source>
|
||||||
<translation>गोपनीयता नीति</translation>
|
<translation>गोपनीयता नीति</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1729,72 +1871,108 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<context>
|
<context>
|
||||||
<name>PageSettingsLogging</name>
|
<name>PageSettingsLogging</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="24"/>
|
|
||||||
<source>Logging is enabled. Note that logs will be automatically disabled after 14 days, and all log files will be deleted.</source>
|
<source>Logging is enabled. Note that logs will be automatically disabled after 14 days, and all log files will be deleted.</source>
|
||||||
<translation>लॉगिंग सक्षम है. ध्यान दें कि 14 दिनों के बाद लॉग स्वचालित रूप से अक्षम हो जाएंगे, और सभी लॉग फ़ाइलें हटा दी जाएंगी.</translation>
|
<translation type="vanished">लॉगिंग सक्षम है. ध्यान दें कि 14 दिनों के बाद लॉग स्वचालित रूप से अक्षम हो जाएंगे, और सभी लॉग फ़ाइलें हटा दी जाएंगी.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="69"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="56"/>
|
||||||
<source>Logging</source>
|
<source>Logging</source>
|
||||||
<translation>लॉगिंग</translation>
|
<translation>लॉगिंग</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="70"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="57"/>
|
||||||
<source>Enabling this function will save application's logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
|
<source>Enabling this function will save application's logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
|
||||||
<translation>इस फ़ंक्शन को सक्षम करने से एप्लिकेशन के लॉग स्वचालित रूप से सहेजे जाएंगे, डिफ़ॉल्ट रूप से, लॉगिंग कार्यक्षमता अक्षम है। एप्लिकेशन की खराबी की स्थिति में लॉग सेविंग सक्षम करें.</translation>
|
<translation>इस फ़ंक्शन को सक्षम करने से एप्लिकेशन के लॉग स्वचालित रूप से सहेजे जाएंगे, डिफ़ॉल्ट रूप से, लॉगिंग कार्यक्षमता अक्षम है। एप्लिकेशन की खराबी की स्थिति में लॉग सेविंग सक्षम करें.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="79"/>
|
|
||||||
<source>Save logs</source>
|
<source>Save logs</source>
|
||||||
<translation>लॉग सहेजें</translation>
|
<translation type="vanished">लॉग सहेजें</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="117"/>
|
|
||||||
<source>Open folder with logs</source>
|
<source>Open folder with logs</source>
|
||||||
<translation>लॉग के साथ फ़ोल्डर खोलें</translation>
|
<translation type="vanished">लॉग के साथ फ़ोल्डर खोलें</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="143"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="171"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="255"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>सहेजें</translation>
|
<translation>सहेजें</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="172"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="256"/>
|
||||||
<source>Logs files (*.log)</source>
|
<source>Logs files (*.log)</source>
|
||||||
<translation>लॉग फ़ाइलें (*.log)</translation>
|
<translation>लॉग फ़ाइलें (*.log)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="181"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="265"/>
|
||||||
<source>Logs file saved</source>
|
<source>Logs file saved</source>
|
||||||
<translation>लॉग फ़ाइल सहेजी गई</translation>
|
<translation>लॉग फ़ाइल सहेजी गई</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="162"/>
|
|
||||||
<source>Save logs to file</source>
|
<source>Save logs to file</source>
|
||||||
<translation>फ़ाइल में लॉग सहेजें</translation>
|
<translation type="vanished">फ़ाइल में लॉग सहेजें</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="184"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="68"/>
|
||||||
|
<source>Enable logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="93"/>
|
||||||
<source>Clear logs?</source>
|
<source>Clear logs?</source>
|
||||||
<translation>लॉग साफ़ करें?</translation>
|
<translation>लॉग साफ़ करें?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="185"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="94"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>जारी रखना</translation>
|
<translation>जारी रखना</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="95"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>रद्द करना</translation>
|
<translation>रद्द करना</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="192"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="101"/>
|
||||||
<source>Logs have been cleaned up</source>
|
<source>Logs have been cleaned up</source>
|
||||||
<translation>लॉग साफ़ कर दिए गए हैं</translation>
|
<translation>लॉग साफ़ कर दिए गए हैं</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="211"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="122"/>
|
||||||
|
<source>Client logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="132"/>
|
||||||
|
<source>AmneziaVPN logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="141"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="220"/>
|
||||||
|
<source>Open logs folder</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="160"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="244"/>
|
||||||
|
<source>Export logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="196"/>
|
||||||
|
<source>Service logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="208"/>
|
||||||
|
<source>AmneziaVPN-service logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="86"/>
|
||||||
<source>Clear logs</source>
|
<source>Clear logs</source>
|
||||||
<translation>लॉग साफ़ करें</translation>
|
<translation>लॉग साफ़ करें</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1954,12 +2132,11 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation> समायोजन</translation>
|
<translation> समायोजन</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="135"/>
|
|
||||||
<source>Clear %1 profile</source>
|
<source>Clear %1 profile</source>
|
||||||
<translation>%1 प्रोफ़ाइल साफ़ करें</translation>
|
<translation type="vanished">%1 प्रोफ़ाइल साफ़ करें</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="138"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="176"/>
|
||||||
<source>Clear %1 profile?</source>
|
<source>Clear %1 profile?</source>
|
||||||
<translation>%1 प्रोफ़ाइल साफ़ करें?</translation>
|
<translation>%1 प्रोफ़ाइल साफ़ करें?</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1969,39 +2146,64 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="145"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="183"/>
|
||||||
<source>Unable to clear %1 profile while there is an active connection</source>
|
<source>Unable to clear %1 profile while there is an active connection</source>
|
||||||
<translation>सक्रिय कनेक्शन होने पर %1 प्रोफ़ाइल साफ़ करने में असमर्थ</translation>
|
<translation>सक्रिय कनेक्शन होने पर %1 प्रोफ़ाइल साफ़ करने में असमर्थ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="224"/>
|
||||||
<source>Remove </source>
|
<source>Remove </source>
|
||||||
<translation>निकालना </translation>
|
<translation>निकालना </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="191"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="229"/>
|
||||||
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
|
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
|
||||||
<translation>वे सभी उपयोगकर्ता जिनके साथ आपने कनेक्शन साझा किया था, वे अब इससे कनेक्ट नहीं हो पाएंगे.</translation>
|
<translation>वे सभी उपयोगकर्ता जिनके साथ आपने कनेक्शन साझा किया था, वे अब इससे कनेक्ट नहीं हो पाएंगे.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="236"/>
|
||||||
<source>Cannot remove active container</source>
|
<source>Cannot remove active container</source>
|
||||||
<translation>सक्रिय कंटेनर को हटाया नहीं जा सकता</translation>
|
<translation>सक्रिय कंटेनर को हटाया नहीं जा सकता</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="190"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="228"/>
|
||||||
<source>Remove %1 from server?</source>
|
<source>Remove %1 from server?</source>
|
||||||
<translation>सर्वर से %1 हटाएँ?</translation>
|
<translation>सर्वर से %1 हटाएँ?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="140"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="100"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="192"/>
|
<source> connection settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="112"/>
|
||||||
|
<source>Click the "connect" button to create a connection configuration</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="132"/>
|
||||||
|
<source> server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="173"/>
|
||||||
|
<source>Clear profile</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="177"/>
|
||||||
|
<source>The connection configuration will be deleted for this device only</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="178"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="230"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>जारी रखना</translation>
|
<translation>जारी रखना</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="141"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="179"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="193"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="231"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>रद्द करना</translation>
|
<translation>रद्द करना</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2185,82 +2387,92 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation type="unfinished">कनेक्शन</translation>
|
<translation type="unfinished">कनेक्शन</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="83"/>
|
||||||
|
<source>Settings</source>
|
||||||
|
<translation type="unfinished">समायोजन</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="91"/>
|
||||||
|
<source>Enable logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="112"/>
|
||||||
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="122"/>
|
||||||
<source>Insert key</source>
|
<source>Insert key</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="123"/>
|
||||||
<source>Insert</source>
|
<source>Insert</source>
|
||||||
<translation type="unfinished">डालना</translation>
|
<translation type="unfinished">डालना</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="143"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation type="unfinished">जारी रखना</translation>
|
<translation type="unfinished">जारी रखना</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="161"/>
|
||||||
<source>Other connection options</source>
|
<source>Other connection options</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="172"/>
|
||||||
<source>VPN by Amnezia</source>
|
<source>VPN by Amnezia</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="173"/>
|
||||||
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="196"/>
|
||||||
<source>Self-hosted VPN</source>
|
<source>Self-hosted VPN</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="197"/>
|
||||||
<source>Configure Amnezia VPN on your own server</source>
|
<source>Configure Amnezia VPN on your own server</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="217"/>
|
||||||
<source>Restore from backup</source>
|
<source>Restore from backup</source>
|
||||||
<translation type="unfinished">बैकअप से बहाल करना</translation>
|
<translation type="unfinished">बैकअप से बहाल करना</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="223"/>
|
||||||
<source>Open backup file</source>
|
<source>Open backup file</source>
|
||||||
<translation type="unfinished">बैकअप फ़ाइल खोलें</translation>
|
<translation type="unfinished">बैकअप फ़ाइल खोलें</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="224"/>
|
||||||
<source>Backup files (*.backup)</source>
|
<source>Backup files (*.backup)</source>
|
||||||
<translation type="unfinished">बैकअप फ़ाइलें (*.backup)</translation>
|
<translation type="unfinished">बैकअप फ़ाइलें (*.backup)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="241"/>
|
||||||
<source>File with connection settings</source>
|
<source>File with connection settings</source>
|
||||||
<translation>कनेक्शन सेटिंग्स वाली फ़ाइल</translation>
|
<translation>कनेक्शन सेटिंग्स वाली फ़ाइल</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="206"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="249"/>
|
||||||
<source>Open config file</source>
|
<source>Open config file</source>
|
||||||
<translation>कॉन्फ़िग फ़ाइल खोलें</translation>
|
<translation>कॉन्फ़िग फ़ाइल खोलें</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="225"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="268"/>
|
||||||
<source>QR code</source>
|
<source>QR code</source>
|
||||||
<translation>क्यू आर संहिता</translation>
|
<translation>क्यू आर संहिता</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="291"/>
|
||||||
<source>I have nothing</source>
|
<source>I have nothing</source>
|
||||||
<translation type="unfinished">मेरे पास कुछ नहीं है</translation>
|
<translation type="unfinished">मेरे पास कुछ नहीं है</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2432,7 +2644,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>स्थापित करना</translation>
|
<translation>स्थापित करना</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="268"/>
|
||||||
<source>The port must be in the range of 1 to 65535</source>
|
<source>The port must be in the range of 1 to 65535</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2804,12 +3016,17 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>शेयर करना</translation>
|
<translation>शेयर करना</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="143"/>
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="147"/>
|
||||||
|
<source>Access error!</source>
|
||||||
|
<translation type="unfinished">प्रवेश त्रुटि!</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="153"/>
|
||||||
<source>Connection to </source>
|
<source>Connection to </source>
|
||||||
<translation>के लिए कनेक्शन </translation>
|
<translation>के लिए कनेक्शन </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="154"/>
|
||||||
<source>File with connection settings to </source>
|
<source>File with connection settings to </source>
|
||||||
<translation>कनेक्शन सेटिंग्स वाली फ़ाइल </translation>
|
<translation>कनेक्शन सेटिंग्स वाली फ़ाइल </translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2826,6 +3043,11 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<source>Settings restored from backup file</source>
|
<source>Settings restored from backup file</source>
|
||||||
<translation type="unfinished">बैकअप फ़ाइल से सेटिंग्स पुनर्स्थापित की गईं</translation>
|
<translation type="unfinished">बैकअप फ़ाइल से सेटिंग्स पुनर्स्थापित की गईं</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageStart.qml" line="208"/>
|
||||||
|
<source>Logging is enabled. Note that logs will be automaticallydisabled after 14 days, and all log files will be deleted.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PopupType</name>
|
<name>PopupType</name>
|
||||||
@@ -2864,12 +3086,12 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>पासवर्ड नहीं मिला</translation>
|
<translation>पासवर्ड नहीं मिला</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="175"/>
|
||||||
<source>Could not open keystore</source>
|
<source>Could not open keystore</source>
|
||||||
<translation>कीस्टोर नहीं खुल सका</translation>
|
<translation>कीस्टोर नहीं खुल सका</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="181"/>
|
||||||
<source>Could not remove private key from keystore</source>
|
<source>Could not remove private key from keystore</source>
|
||||||
<translation>कीस्टोर से निजी कुंजी नहीं हटाई जा सकी</translation>
|
<translation>कीस्टोर से निजी कुंजी नहीं हटाई जा सकी</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -3045,27 +3267,27 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>कीस्टोर नहीं खुल सका</translation>
|
<translation>कीस्टोर नहीं खुल सका</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="126"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="131"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="133"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="139"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="141"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="147"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="149"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="155"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="157"/>
|
||||||
<source>Could not encrypt data</source>
|
<source>Could not encrypt data</source>
|
||||||
<translation>डेटा एन्क्रिप्ट नहीं किया जा सका</translation>
|
<translation>डेटा एन्क्रिप्ट नहीं किया जा सका</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -3763,12 +3985,12 @@ While it offers a blend of security, stability, and speed, it's essential t
|
|||||||
<context>
|
<context>
|
||||||
<name>SettingsController</name>
|
<name>SettingsController</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/settingsController.cpp" line="138"/>
|
<location filename="../ui/controllers/settingsController.cpp" line="152"/>
|
||||||
<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="160"/>
|
<location filename="../ui/controllers/settingsController.cpp" line="174"/>
|
||||||
<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>
|
||||||
@@ -3900,7 +4122,7 @@ While it offers a blend of security, stability, and speed, it's essential t
|
|||||||
<context>
|
<context>
|
||||||
<name>VpnConnection</name>
|
<name>VpnConnection</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../vpnconnection.cpp" line="375"/>
|
<location filename="../vpnconnection.cpp" line="408"/>
|
||||||
<source>Mbps</source>
|
<source>Mbps</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,47 +4,52 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ApiServicesModel</name>
|
<name>ApiServicesModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="63"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||||
<translation>Классический VPN для комфортной работы, загрузки больших файлов и просмотра видео. Работает для любых сайтов. Скорость до %1 Мбит/с</translation>
|
<translation>Классический VPN для комфортной работы, загрузки больших файлов и просмотра видео. Работает для любых сайтов. Скорость до %1 Мбит/с</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||||
<translation>VPN для доступа к заблокированным сайтам в регионах с высоким уровнем интернет-цензуры. </translation>
|
<translation>VPN для доступа к заблокированным сайтам в регионах с высоким уровнем интернет-цензуры. </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||||
|
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||||
<translation>Amnezia Premium — классический VPN для комфортной работы, загрузки больших файлов и просмотра видео в высоком разрешении. Работает на всех сайтах, даже в странах с самым высоким уровнем интернет-цензуры.</translation>
|
<translation>Amnezia Premium — классический VPN для комфортной работы, загрузки больших файлов и просмотра видео в высоком разрешении. Работает на всех сайтах, даже в странах с самым высоким уровнем интернет-цензуры.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="75"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||||
<translation>Amnezia Free - это бесплатный VPN для обхода блокировок в странах с высоким уровнем интернет-цензуры</translation>
|
<translation>Amnezia Free - это бесплатный VPN для обхода блокировок в странах с высоким уровнем интернет-цензуры</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||||
<source>%1 MBit/s</source>
|
<source>%1 MBit/s</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||||
<source>%1 days</source>
|
<source>%1 days</source>
|
||||||
<translation>%1 дней</translation>
|
<translation>%1 дней</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||||
<translation>Через VPN будут открываться только популярные сайты, заблокированные в вашем регионе, такие как Instagram, Facebook, Twitter и другие. Остальные сайты будут открываться с вашего реального IP-адреса, <a href="%1/free" style="color: #FBB26A;">подробности на сайте.</a></translation>
|
<translation>Через VPN будут открываться только популярные сайты, заблокированные в вашем регионе, такие как Instagram, Facebook, Twitter и другие. Остальные сайты будут открываться с вашего реального IP-адреса, <a href="%1/free" style="color: #FBB26A;">подробности на сайте.</a></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||||
<source>Free</source>
|
<source>Free</source>
|
||||||
<translation>Бесплатно</translation>
|
<translation>Бесплатно</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||||
<source>%1 $/month</source>
|
<source>%1 $/month</source>
|
||||||
<translation>%1 $/месяц</translation>
|
<translation>%1 $/месяц</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -75,7 +80,7 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ConnectButton</name>
|
<name>ConnectButton</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Components/ConnectButton.qml" line="27"/>
|
<location filename="../ui/qml/Components/ConnectButton.qml" line="28"/>
|
||||||
<source>Unable to disconnect during configuration preparation</source>
|
<source>Unable to disconnect during configuration preparation</source>
|
||||||
<translation>Невозможно отключиться во время подготовки конфигурации</translation>
|
<translation>Невозможно отключиться во время подготовки конфигурации</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -187,9 +192,8 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ExportController</name>
|
<name>ExportController</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/exportController.cpp" line="30"/>
|
|
||||||
<source>Access error!</source>
|
<source>Access error!</source>
|
||||||
<translation>Ошибка доступа!</translation>
|
<translation type="vanished">Ошибка доступа!</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -259,18 +263,18 @@ Can't be disabled for current server</source>
|
|||||||
<translation>Невозможно открыть файл</translation>
|
<translation>Невозможно открыть файл</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="186"/>
|
<location filename="../ui/controllers/importController.cpp" line="187"/>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="191"/>
|
<location filename="../ui/controllers/importController.cpp" line="192"/>
|
||||||
<source>Invalid configuration file</source>
|
<source>Invalid configuration file</source>
|
||||||
<translation>Неверный файл конфигурации</translation>
|
<translation>Неверный файл конфигурации</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="606"/>
|
<location filename="../ui/controllers/importController.cpp" line="617"/>
|
||||||
<source>Scanned %1 of %2.</source>
|
<source>Scanned %1 of %2.</source>
|
||||||
<translation>Отсканировано %1 из %2.</translation>
|
<translation>Отсканировано %1 из %2.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="641"/>
|
<location filename="../ui/controllers/importController.cpp" line="652"/>
|
||||||
<source>In the imported configuration, potentially dangerous lines were found:</source>
|
<source>In the imported configuration, potentially dangerous lines were found:</source>
|
||||||
<translation>В импортированной конфигурации были обнаружены потенциально опасные строки:</translation>
|
<translation>В импортированной конфигурации были обнаружены потенциально опасные строки:</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -447,6 +451,11 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<source>Gateway endpoint</source>
|
<source>Gateway endpoint</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="101"/>
|
||||||
|
<source>Dev gateway environment</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageHome</name>
|
<name>PageHome</name>
|
||||||
@@ -481,10 +490,63 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>Невозможно изменить сервер во время активного соединения</translation>
|
<translation>Невозможно изменить сервер во время активного соединения</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>PageProtocolAwgClientSettings</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="96"/>
|
||||||
|
<source>AmneziaWG settings</source>
|
||||||
|
<translation type="unfinished">Настройки AmneziaWG</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="104"/>
|
||||||
|
<source>MTU</source>
|
||||||
|
<translation type="unfinished">MTU</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="184"/>
|
||||||
|
<source>Server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="194"/>
|
||||||
|
<source>Port</source>
|
||||||
|
<translation type="unfinished">Порт</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="284"/>
|
||||||
|
<source>Save</source>
|
||||||
|
<translation type="unfinished">Сохранить</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="290"/>
|
||||||
|
<source>Save settings?</source>
|
||||||
|
<translation type="unfinished">Сохранить настройки?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="291"/>
|
||||||
|
<source>Only the settings for this device will be changed</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="292"/>
|
||||||
|
<source>Continue</source>
|
||||||
|
<translation type="unfinished">Продолжить</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="293"/>
|
||||||
|
<source>Cancel</source>
|
||||||
|
<translation type="unfinished">Отменить</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="297"/>
|
||||||
|
<source>Unable change settings while there is an active connection</source>
|
||||||
|
<translation type="unfinished">Невозможно изменить настройки во время активного соединения</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageProtocolAwgSettings</name>
|
<name>PageProtocolAwgSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="96"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="94"/>
|
||||||
<source>AmneziaWG settings</source>
|
<source>AmneziaWG settings</source>
|
||||||
<translation>Настройки AmneziaWG</translation>
|
<translation>Настройки AmneziaWG</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -494,9 +556,8 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>Порт</translation>
|
<translation>Порт</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
|
|
||||||
<source>MTU</source>
|
<source>MTU</source>
|
||||||
<translation>MTU</translation>
|
<translation type="vanished">MTU</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Remove AmneziaWG</source>
|
<source>Remove AmneziaWG</source>
|
||||||
@@ -507,87 +568,87 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation type="vanished">Удалить AmneziaWG с сервера?</translation>
|
<translation type="vanished">Удалить AmneziaWG с сервера?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="374"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="357"/>
|
||||||
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
||||||
<translation>Все пользователи, с которыми вы поделились конфигурацией вашего VPN, больше не смогут к нему подключаться.</translation>
|
<translation>Все пользователи, с которыми вы поделились конфигурацией вашего VPN, больше не смогут к нему подключаться.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="354"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="333"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>Сохранить</translation>
|
<translation>Сохранить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="147"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
|
||||||
<source>Jc - Junk packet count</source>
|
<source>Jc - Junk packet count</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="151"/>
|
||||||
<source>Jmin - Junk packet minimum size</source>
|
<source>Jmin - Junk packet minimum size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
|
||||||
<source>Jmax - Junk packet maximum size</source>
|
<source>Jmax - Junk packet maximum size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
|
||||||
<source>S1 - Init packet junk size</source>
|
<source>S1 - Init packet junk size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
|
||||||
<source>S2 - Response packet junk size</source>
|
<source>S2 - Response packet junk size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
|
||||||
<source>H1 - Init packet magic header</source>
|
<source>H1 - Init packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
|
||||||
<source>H2 - Response packet magic header</source>
|
<source>H2 - Response packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="298"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
|
||||||
<source>H4 - Transport packet magic header</source>
|
<source>H4 - Transport packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="320"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="299"/>
|
||||||
<source>H3 - Underload packet magic header</source>
|
<source>H3 - Underload packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="345"/>
|
||||||
<source>The values of the H1-H4 fields must be unique</source>
|
<source>The values of the H1-H4 fields must be unique</source>
|
||||||
<translation>Значения в полях H1-H4 должны быть уникальными</translation>
|
<translation>Значения в полях H1-H4 должны быть уникальными</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="369"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="351"/>
|
||||||
<source>The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)</source>
|
<source>The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)</source>
|
||||||
<translation>Значение в поле S1 + размер инициации сообщения (148) не должно равняться значению в поле S2 + размер ответа на сообщение (92)</translation>
|
<translation>Значение в поле S1 + размер инициации сообщения (148) не должно равняться значению в поле S2 + размер ответа на сообщение (92)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="373"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="356"/>
|
||||||
<source>Save settings?</source>
|
<source>Save settings?</source>
|
||||||
<translation>Сохранить настройки?</translation>
|
<translation>Сохранить настройки?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="375"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="358"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>Продолжить</translation>
|
<translation>Продолжить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="376"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="359"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>Отменить</translation>
|
<translation>Отменить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="382"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>Невозможно изменить настройки во время активного соединения</translation>
|
<translation>Невозможно изменить настройки во время активного соединения</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -898,25 +959,87 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>Невозможно изменить настройки во время активного соединения</translation>
|
<translation>Невозможно изменить настройки во время активного соединения</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>PageProtocolWireGuardClientSettings</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="93"/>
|
||||||
|
<source>WG settings</source>
|
||||||
|
<translation type="unfinished">Настройки WG</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="101"/>
|
||||||
|
<source>MTU</source>
|
||||||
|
<translation type="unfinished">MTU</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="118"/>
|
||||||
|
<source>Server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="128"/>
|
||||||
|
<source>Port</source>
|
||||||
|
<translation type="unfinished">Порт</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="151"/>
|
||||||
|
<source>Save</source>
|
||||||
|
<translation type="unfinished">Сохранить</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="157"/>
|
||||||
|
<source>Save settings?</source>
|
||||||
|
<translation type="unfinished">Сохранить настройки?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="158"/>
|
||||||
|
<source>Only the settings for this device will be changed</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="159"/>
|
||||||
|
<source>Continue</source>
|
||||||
|
<translation type="unfinished">Продолжить</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="160"/>
|
||||||
|
<source>Cancel</source>
|
||||||
|
<translation type="unfinished">Отменить</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="164"/>
|
||||||
|
<source>Unable change settings while there is an active connection</source>
|
||||||
|
<translation type="unfinished">Невозможно изменить настройки во время активного соединения</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageProtocolWireGuardSettings</name>
|
<name>PageProtocolWireGuardSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="94"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="97"/>
|
||||||
<source>WG settings</source>
|
<source>WG settings</source>
|
||||||
<translation>Настройки WG</translation>
|
<translation>Настройки WG</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="102"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="107"/>
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
<translation>Порт</translation>
|
<translation>Порт</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="123"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="138"/>
|
||||||
<source>MTU</source>
|
<source>Save settings?</source>
|
||||||
<translation>MTU</translation>
|
<translation type="unfinished">Сохранить настройки?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="157"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="139"/>
|
||||||
|
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
||||||
|
<translation type="unfinished">Все пользователи, с которыми вы поделились конфигурацией вашего VPN, больше не смогут к нему подключаться.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>MTU</source>
|
||||||
|
<translation type="vanished">MTU</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="145"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>Невозможно изменить настройки во время активного соединения</translation>
|
<translation>Невозможно изменить настройки во время активного соединения</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -933,15 +1056,17 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation type="vanished">Все пользователи, с которыми вы поделились конфигурацией вашего VPN, больше не смогут к нему подключаться.</translation>
|
<translation type="vanished">Все пользователи, с которыми вы поделились конфигурацией вашего VPN, больше не смогут к нему подключаться.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="140"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation type="vanished">Продолжить</translation>
|
<translation>Продолжить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="141"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation type="vanished">Отменить</translation>
|
<translation>Отменить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="149"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="131"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>Сохранить</translation>
|
<translation>Сохранить</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1305,8 +1430,12 @@ Already installed containers were found on the server. All installed containers
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
|
||||||
|
<source>support@amnezia.org</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
<source>Mail</source>
|
<source>Mail</source>
|
||||||
<translation>Почта</translation>
|
<translation type="vanished">Почта</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
|
||||||
@@ -1314,17 +1443,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/PageSettingsAbout.qml" line="141"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="132"/>
|
||||||
|
<source>Copied</source>
|
||||||
|
<translation type="unfinished">Скопировано</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="143"/>
|
||||||
<source>GitHub</source>
|
<source>GitHub</source>
|
||||||
<translation>GitHub</translation>
|
<translation>GitHub</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="148"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="150"/>
|
||||||
<source>https://github.com/amnezia-vpn/amnezia-client</source>
|
<source>https://github.com/amnezia-vpn/amnezia-client</source>
|
||||||
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
|
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="159"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="161"/>
|
||||||
<source>Website</source>
|
<source>Website</source>
|
||||||
<translation>Веб-сайт</translation>
|
<translation>Веб-сайт</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1333,17 +1467,17 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation type="vanished">https://amnezia.org</translation>
|
<translation type="vanished">https://amnezia.org</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="179"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="181"/>
|
||||||
<source>Software version: %1</source>
|
<source>Software version: %1</source>
|
||||||
<translation>Версия ПО: %1</translation>
|
<translation>Версия ПО: %1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="208"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="210"/>
|
||||||
<source>Check for updates</source>
|
<source>Check for updates</source>
|
||||||
<translation>Проверить обновления</translation>
|
<translation>Проверить обновления</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="231"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="233"/>
|
||||||
<source>Privacy Policy</source>
|
<source>Privacy Policy</source>
|
||||||
<translation>Политика конфиденциальности</translation>
|
<translation>Политика конфиденциальности</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1816,72 +1950,108 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<context>
|
<context>
|
||||||
<name>PageSettingsLogging</name>
|
<name>PageSettingsLogging</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="24"/>
|
|
||||||
<source>Logging is enabled. Note that logs will be automatically disabled after 14 days, and all log files will be deleted.</source>
|
<source>Logging is enabled. Note that logs will be automatically disabled after 14 days, and all log files will be deleted.</source>
|
||||||
<translation>Логирование включено. Обратите внимание, что логирование будет автоматически отключено через 14 дней, и все логи будут удалены.</translation>
|
<translation type="vanished">Логирование включено. Обратите внимание, что логирование будет автоматически отключено через 14 дней, и все логи будут удалены.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="69"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="56"/>
|
||||||
<source>Logging</source>
|
<source>Logging</source>
|
||||||
<translation>Логирование</translation>
|
<translation>Логирование</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="70"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="57"/>
|
||||||
<source>Enabling this function will save application's logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
|
<source>Enabling this function will save application's logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
|
||||||
<translation>Включение этой функции позволяет сохранять логи на вашем устройстве. По умолчанию она отключена. Включите сохранение логов в случае сбоев в работе приложения.</translation>
|
<translation>Включение этой функции позволяет сохранять логи на вашем устройстве. По умолчанию она отключена. Включите сохранение логов в случае сбоев в работе приложения.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="79"/>
|
|
||||||
<source>Save logs</source>
|
<source>Save logs</source>
|
||||||
<translation>Сохранять логи</translation>
|
<translation type="vanished">Сохранять логи</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="117"/>
|
|
||||||
<source>Open folder with logs</source>
|
<source>Open folder with logs</source>
|
||||||
<translation>Открыть папку с логами</translation>
|
<translation type="vanished">Открыть папку с логами</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="143"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="171"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="255"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>Сохранить</translation>
|
<translation>Сохранить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="172"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="256"/>
|
||||||
<source>Logs files (*.log)</source>
|
<source>Logs files (*.log)</source>
|
||||||
<translation>Файлы логов (*.log)</translation>
|
<translation>Файлы логов (*.log)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="181"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="265"/>
|
||||||
<source>Logs file saved</source>
|
<source>Logs file saved</source>
|
||||||
<translation>Файл с логами сохранен</translation>
|
<translation>Файл с логами сохранен</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="162"/>
|
|
||||||
<source>Save logs to file</source>
|
<source>Save logs to file</source>
|
||||||
<translation>Сохранить логи в файл</translation>
|
<translation type="vanished">Сохранить логи в файл</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="184"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="68"/>
|
||||||
|
<source>Enable logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="93"/>
|
||||||
<source>Clear logs?</source>
|
<source>Clear logs?</source>
|
||||||
<translation>Очистить логи?</translation>
|
<translation>Очистить логи?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="185"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="94"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>Продолжить</translation>
|
<translation>Продолжить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="95"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>Отменить</translation>
|
<translation>Отменить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="192"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="101"/>
|
||||||
<source>Logs have been cleaned up</source>
|
<source>Logs have been cleaned up</source>
|
||||||
<translation>Логи очищены</translation>
|
<translation>Логи очищены</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="211"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="122"/>
|
||||||
|
<source>Client logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="132"/>
|
||||||
|
<source>AmneziaVPN logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="141"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="220"/>
|
||||||
|
<source>Open logs folder</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="160"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="244"/>
|
||||||
|
<source>Export logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="196"/>
|
||||||
|
<source>Service logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="208"/>
|
||||||
|
<source>AmneziaVPN-service logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="86"/>
|
||||||
<source>Clear logs</source>
|
<source>Clear logs</source>
|
||||||
<translation>Очистить логи</translation>
|
<translation>Очистить логи</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2069,12 +2239,11 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation> настройки</translation>
|
<translation> настройки</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="135"/>
|
|
||||||
<source>Clear %1 profile</source>
|
<source>Clear %1 profile</source>
|
||||||
<translation>Очистить профиль %1</translation>
|
<translation type="vanished">Очистить профиль %1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="138"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="176"/>
|
||||||
<source>Clear %1 profile?</source>
|
<source>Clear %1 profile?</source>
|
||||||
<translation>Очистить профиль %1?</translation>
|
<translation>Очистить профиль %1?</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2084,27 +2253,52 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="145"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="100"/>
|
||||||
|
<source> connection settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="112"/>
|
||||||
|
<source>Click the "connect" button to create a connection configuration</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="132"/>
|
||||||
|
<source> server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="173"/>
|
||||||
|
<source>Clear profile</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="177"/>
|
||||||
|
<source>The connection configuration will be deleted for this device only</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="183"/>
|
||||||
<source>Unable to clear %1 profile while there is an active connection</source>
|
<source>Unable to clear %1 profile while there is an active connection</source>
|
||||||
<translation>Невозможно очистить профиль %1 во время активного соединения</translation>
|
<translation>Невозможно очистить профиль %1 во время активного соединения</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="224"/>
|
||||||
<source>Remove </source>
|
<source>Remove </source>
|
||||||
<translation>Удалить </translation>
|
<translation>Удалить </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="190"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="228"/>
|
||||||
<source>Remove %1 from server?</source>
|
<source>Remove %1 from server?</source>
|
||||||
<translation>Удалить %1 с сервера?</translation>
|
<translation>Удалить %1 с сервера?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="191"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="229"/>
|
||||||
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
|
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
|
||||||
<translation>Все пользователи, с которыми вы поделились конфигурацией вашего VPN, больше не смогут к нему подключаться.</translation>
|
<translation>Все пользователи, с которыми вы поделились конфигурацией вашего VPN, больше не смогут к нему подключаться.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="236"/>
|
||||||
<source>Cannot remove active container</source>
|
<source>Cannot remove active container</source>
|
||||||
<translation>Невозможно удалить активный контейнер</translation>
|
<translation>Невозможно удалить активный контейнер</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2113,14 +2307,14 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation type="vanished">Все пользователи, с которыми вы поделились VPN, больше не смогут к нему подключаться.</translation>
|
<translation type="vanished">Все пользователи, с которыми вы поделились VPN, больше не смогут к нему подключаться.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="140"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="178"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="192"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="230"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>Продолжить</translation>
|
<translation>Продолжить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="141"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="179"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="193"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="231"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>Отменить</translation>
|
<translation>Отменить</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2311,7 +2505,7 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<translation type="vanished">Что у вас есть?</translation>
|
<translation type="vanished">Что у вас есть?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="241"/>
|
||||||
<source>File with connection settings</source>
|
<source>File with connection settings</source>
|
||||||
<translation>Файл с настройками подключения</translation>
|
<translation>Файл с настройками подключения</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2325,77 +2519,87 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<translation>Соединение</translation>
|
<translation>Соединение</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="83"/>
|
||||||
|
<source>Settings</source>
|
||||||
|
<translation type="unfinished">Настройки</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="91"/>
|
||||||
|
<source>Enable logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="112"/>
|
||||||
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
||||||
<translation>Вставьте ключ, добавьте файл конфигурации или отсканируйте QR-код</translation>
|
<translation>Вставьте ключ, добавьте файл конфигурации или отсканируйте QR-код</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="122"/>
|
||||||
<source>Insert key</source>
|
<source>Insert key</source>
|
||||||
<translation>Вставьте ключ</translation>
|
<translation>Вставьте ключ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="123"/>
|
||||||
<source>Insert</source>
|
<source>Insert</source>
|
||||||
<translation>Вставить</translation>
|
<translation>Вставить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="143"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>Продолжить</translation>
|
<translation>Продолжить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="161"/>
|
||||||
<source>Other connection options</source>
|
<source>Other connection options</source>
|
||||||
<translation>Другие варианты подключения</translation>
|
<translation>Другие варианты подключения</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="172"/>
|
||||||
<source>VPN by Amnezia</source>
|
<source>VPN by Amnezia</source>
|
||||||
<translation>VPN от Amnezia</translation>
|
<translation>VPN от Amnezia</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="173"/>
|
||||||
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
||||||
<translation>Подключайтесь к классическим платным и бесплатным VPN-сервисам от Amnezia</translation>
|
<translation>Подключайтесь к классическим платным и бесплатным VPN-сервисам от Amnezia</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="196"/>
|
||||||
<source>Self-hosted VPN</source>
|
<source>Self-hosted VPN</source>
|
||||||
<translation>Self-hosted VPN</translation>
|
<translation>Self-hosted VPN</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="197"/>
|
||||||
<source>Configure Amnezia VPN on your own server</source>
|
<source>Configure Amnezia VPN on your own server</source>
|
||||||
<translation>Настроить VPN на собственном сервере</translation>
|
<translation>Настроить VPN на собственном сервере</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="217"/>
|
||||||
<source>Restore from backup</source>
|
<source>Restore from backup</source>
|
||||||
<translation>Восстановить из резервной копии</translation>
|
<translation>Восстановить из резервной копии</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="223"/>
|
||||||
<source>Open backup file</source>
|
<source>Open backup file</source>
|
||||||
<translation>Открыть резервную копию</translation>
|
<translation>Открыть резервную копию</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="224"/>
|
||||||
<source>Backup files (*.backup)</source>
|
<source>Backup files (*.backup)</source>
|
||||||
<translation>Файлы резервных копий (*.backup)</translation>
|
<translation>Файлы резервных копий (*.backup)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="206"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="249"/>
|
||||||
<source>Open config file</source>
|
<source>Open config file</source>
|
||||||
<translation>Открыть файл с конфигурацией</translation>
|
<translation>Открыть файл с конфигурацией</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="225"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="268"/>
|
||||||
<source>QR code</source>
|
<source>QR code</source>
|
||||||
<translation>QR-код</translation>
|
<translation>QR-код</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="291"/>
|
||||||
<source>I have nothing</source>
|
<source>I have nothing</source>
|
||||||
<translation>У меня ничего нет</translation>
|
<translation>У меня ничего нет</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2600,7 +2804,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
|||||||
<translation>Установить</translation>
|
<translation>Установить</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="268"/>
|
||||||
<source>The port must be in the range of 1 to 65535</source>
|
<source>The port must be in the range of 1 to 65535</source>
|
||||||
<translation>Порт должен быть в диапазоне от 1 до 65535</translation>
|
<translation>Порт должен быть в диапазоне от 1 до 65535</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2996,12 +3200,17 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
|||||||
<translation>Поделиться</translation>
|
<translation>Поделиться</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="143"/>
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="147"/>
|
||||||
|
<source>Access error!</source>
|
||||||
|
<translation type="unfinished">Ошибка доступа!</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="153"/>
|
||||||
<source>Connection to </source>
|
<source>Connection to </source>
|
||||||
<translation>Подключение к </translation>
|
<translation>Подключение к </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="154"/>
|
||||||
<source>File with connection settings to </source>
|
<source>File with connection settings to </source>
|
||||||
<translation>Файл с настройками подключения к </translation>
|
<translation>Файл с настройками подключения к </translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -3018,6 +3227,11 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
|||||||
<source>Settings restored from backup file</source>
|
<source>Settings restored from backup file</source>
|
||||||
<translation>Настройки восстановлены из бэкап файла</translation>
|
<translation>Настройки восстановлены из бэкап файла</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageStart.qml" line="208"/>
|
||||||
|
<source>Logging is enabled. Note that logs will be automaticallydisabled after 14 days, and all log files will be deleted.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PopupType</name>
|
<name>PopupType</name>
|
||||||
@@ -3056,12 +3270,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
|||||||
<translation>Пароль не найден</translation>
|
<translation>Пароль не найден</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="175"/>
|
||||||
<source>Could not open keystore</source>
|
<source>Could not open keystore</source>
|
||||||
<translation>Не удалось открыть хранилище ключей</translation>
|
<translation>Не удалось открыть хранилище ключей</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="181"/>
|
||||||
<source>Could not remove private key from keystore</source>
|
<source>Could not remove private key from keystore</source>
|
||||||
<translation>Не удалось удалить закрытый ключ из хранилища ключей</translation>
|
<translation>Не удалось удалить закрытый ключ из хранилища ключей</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -3237,27 +3451,27 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
|||||||
<translation>Не удалось открыть хранилище ключей</translation>
|
<translation>Не удалось открыть хранилище ключей</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="126"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="131"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="133"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="139"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="141"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="147"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="149"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="155"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="157"/>
|
||||||
<source>Could not encrypt data</source>
|
<source>Could not encrypt data</source>
|
||||||
<translation>Не удалось зашифровать данные</translation>
|
<translation>Не удалось зашифровать данные</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -4094,7 +4308,7 @@ 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="160"/>
|
<location filename="../ui/controllers/settingsController.cpp" line="174"/>
|
||||||
<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>
|
||||||
@@ -4103,7 +4317,7 @@ This means that AmneziaWG keeps the fast performance of the original while addin
|
|||||||
<translation type="vanished">Закэшированные профили очищены</translation>
|
<translation type="vanished">Закэшированные профили очищены</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/settingsController.cpp" line="138"/>
|
<location filename="../ui/controllers/settingsController.cpp" line="152"/>
|
||||||
<source>Backup file is corrupted</source>
|
<source>Backup file is corrupted</source>
|
||||||
<translation>Файл резервной копии поврежден</translation>
|
<translation>Файл резервной копии поврежден</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -4235,7 +4449,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="375"/>
|
<location filename="../vpnconnection.cpp" line="408"/>
|
||||||
<source>Mbps</source>
|
<source>Mbps</source>
|
||||||
<translation>Мбит/с</translation>
|
<translation>Мбит/с</translation>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,47 +4,52 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ApiServicesModel</name>
|
<name>ApiServicesModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="63"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||||
|
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="75"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||||
<source>%1 MBit/s</source>
|
<source>%1 MBit/s</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||||
<source>%1 days</source>
|
<source>%1 days</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||||
<source>Free</source>
|
<source>Free</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||||
<source>%1 $/month</source>
|
<source>%1 $/month</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -75,7 +80,7 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ConnectButton</name>
|
<name>ConnectButton</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Components/ConnectButton.qml" line="27"/>
|
<location filename="../ui/qml/Components/ConnectButton.qml" line="28"/>
|
||||||
<source>Unable to disconnect during configuration preparation</source>
|
<source>Unable to disconnect during configuration preparation</source>
|
||||||
<translation>تشکیل کی تیاری کے دوران منقطع ہونا ممکن نہیں ہے</translation>
|
<translation>تشکیل کی تیاری کے دوران منقطع ہونا ممکن نہیں ہے</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -186,9 +191,8 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ExportController</name>
|
<name>ExportController</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/exportController.cpp" line="30"/>
|
|
||||||
<source>Access error!</source>
|
<source>Access error!</source>
|
||||||
<translation>رساءی ناممکن!</translation>
|
<translation type="vanished">رساءی ناممکن!</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -253,18 +257,18 @@ Can't be disabled for current server</source>
|
|||||||
<translation>فائل کو کھولنے سے قاصر ہے</translation>
|
<translation>فائل کو کھولنے سے قاصر ہے</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="186"/>
|
<location filename="../ui/controllers/importController.cpp" line="187"/>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="191"/>
|
<location filename="../ui/controllers/importController.cpp" line="192"/>
|
||||||
<source>Invalid configuration file</source>
|
<source>Invalid configuration file</source>
|
||||||
<translation>غلط کنفیگریشن فائل</translation>
|
<translation>غلط کنفیگریشن فائل</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="606"/>
|
<location filename="../ui/controllers/importController.cpp" line="617"/>
|
||||||
<source>Scanned %1 of %2.</source>
|
<source>Scanned %1 of %2.</source>
|
||||||
<translation>سکین%1 کی%2.</translation>
|
<translation>سکین%1 کی%2.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="641"/>
|
<location filename="../ui/controllers/importController.cpp" line="652"/>
|
||||||
<source>In the imported configuration, potentially dangerous lines were found:</source>
|
<source>In the imported configuration, potentially dangerous lines were found:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -443,6 +447,11 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<source>Gateway endpoint</source>
|
<source>Gateway endpoint</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="101"/>
|
||||||
|
<source>Dev gateway environment</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageHome</name>
|
<name>PageHome</name>
|
||||||
@@ -477,10 +486,63 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>فعال کنکشن موجود ہونے کی وجہ سے سرور تبدیل کرنے میں ناکام ہیں</translation>
|
<translation>فعال کنکشن موجود ہونے کی وجہ سے سرور تبدیل کرنے میں ناکام ہیں</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>PageProtocolAwgClientSettings</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="96"/>
|
||||||
|
<source>AmneziaWG settings</source>
|
||||||
|
<translation type="unfinished">امنیزیا وی جی کی ترتیبات</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="104"/>
|
||||||
|
<source>MTU</source>
|
||||||
|
<translation type="unfinished">ام ٹی یو</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="184"/>
|
||||||
|
<source>Server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="194"/>
|
||||||
|
<source>Port</source>
|
||||||
|
<translation type="unfinished">پورٹ</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="284"/>
|
||||||
|
<source>Save</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="290"/>
|
||||||
|
<source>Save settings?</source>
|
||||||
|
<translation type="unfinished">ترتیبات محفوظ کریں?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="291"/>
|
||||||
|
<source>Only the settings for this device will be changed</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="292"/>
|
||||||
|
<source>Continue</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="293"/>
|
||||||
|
<source>Cancel</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="297"/>
|
||||||
|
<source>Unable change settings while there is an active connection</source>
|
||||||
|
<translation type="unfinished">جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageProtocolAwgSettings</name>
|
<name>PageProtocolAwgSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="96"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="94"/>
|
||||||
<source>AmneziaWG settings</source>
|
<source>AmneziaWG settings</source>
|
||||||
<translation>امنیزیا وی جی کی ترتیبات</translation>
|
<translation>امنیزیا وی جی کی ترتیبات</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -490,92 +552,91 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>پورٹ</translation>
|
<translation>پورٹ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
|
|
||||||
<source>MTU</source>
|
<source>MTU</source>
|
||||||
<translation>ام ٹی یو</translation>
|
<translation type="vanished">ام ٹی یو</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="374"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="357"/>
|
||||||
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
||||||
<translation>آپ جن لوگوں کے ساتھ آپ نے اس کنکشن کا اشتراک کیا تھا، وہ اس سے مزید جڑ نہیں سکیں گے۔</translation>
|
<translation>آپ جن لوگوں کے ساتھ آپ نے اس کنکشن کا اشتراک کیا تھا، وہ اس سے مزید جڑ نہیں سکیں گے۔</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="354"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="333"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>محفوظ کریں</translation>
|
<translation>محفوظ کریں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="147"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
|
||||||
<source>Jc - Junk packet count</source>
|
<source>Jc - Junk packet count</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="151"/>
|
||||||
<source>Jmin - Junk packet minimum size</source>
|
<source>Jmin - Junk packet minimum size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
|
||||||
<source>Jmax - Junk packet maximum size</source>
|
<source>Jmax - Junk packet maximum size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
|
||||||
<source>S1 - Init packet junk size</source>
|
<source>S1 - Init packet junk size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
|
||||||
<source>S2 - Response packet junk size</source>
|
<source>S2 - Response packet junk size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
|
||||||
<source>H1 - Init packet magic header</source>
|
<source>H1 - Init packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
|
||||||
<source>H2 - Response packet magic header</source>
|
<source>H2 - Response packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="298"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
|
||||||
<source>H4 - Transport packet magic header</source>
|
<source>H4 - Transport packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="320"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="299"/>
|
||||||
<source>H3 - Underload packet magic header</source>
|
<source>H3 - Underload packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="345"/>
|
||||||
<source>The values of the H1-H4 fields must be unique</source>
|
<source>The values of the H1-H4 fields must be unique</source>
|
||||||
<translation>H1 تا H4 فیلڈز کی قیمتیں مخصوص ہونی چاہیے</translation>
|
<translation>H1 تا H4 فیلڈز کی قیمتیں مخصوص ہونی چاہیے</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="369"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="351"/>
|
||||||
<source>The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)</source>
|
<source>The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)</source>
|
||||||
<translation>S1 + پیغام شروع کار (148) کے فیلڈ کی قیمت S2 + پیغام جواب (92) کے سائز کے برابر نہیں ہونی چاہئے</translation>
|
<translation>S1 + پیغام شروع کار (148) کے فیلڈ کی قیمت S2 + پیغام جواب (92) کے سائز کے برابر نہیں ہونی چاہئے</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="373"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="356"/>
|
||||||
<source>Save settings?</source>
|
<source>Save settings?</source>
|
||||||
<translation>ترتیبات محفوظ کریں?</translation>
|
<translation>ترتیبات محفوظ کریں?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="375"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="358"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>جاری رکھیں</translation>
|
<translation>جاری رکھیں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="376"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="359"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>منسوخ کریں</translation>
|
<translation>منسوخ کریں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="382"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
|
<translation>جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -862,30 +923,102 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
|
<translation>جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>PageProtocolWireGuardClientSettings</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="93"/>
|
||||||
|
<source>WG settings</source>
|
||||||
|
<translation type="unfinished">وائر گارڈ ترتیبات</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="101"/>
|
||||||
|
<source>MTU</source>
|
||||||
|
<translation type="unfinished">ام ٹی یو</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="118"/>
|
||||||
|
<source>Server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="128"/>
|
||||||
|
<source>Port</source>
|
||||||
|
<translation type="unfinished">پورٹ</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="151"/>
|
||||||
|
<source>Save</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="157"/>
|
||||||
|
<source>Save settings?</source>
|
||||||
|
<translation type="unfinished">ترتیبات محفوظ کریں?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="158"/>
|
||||||
|
<source>Only the settings for this device will be changed</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="159"/>
|
||||||
|
<source>Continue</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="160"/>
|
||||||
|
<source>Cancel</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="164"/>
|
||||||
|
<source>Unable change settings while there is an active connection</source>
|
||||||
|
<translation type="unfinished">جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageProtocolWireGuardSettings</name>
|
<name>PageProtocolWireGuardSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="94"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="97"/>
|
||||||
<source>WG settings</source>
|
<source>WG settings</source>
|
||||||
<translation>وائر گارڈ ترتیبات</translation>
|
<translation>وائر گارڈ ترتیبات</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="102"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="107"/>
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
<translation>پورٹ</translation>
|
<translation>پورٹ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="123"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="138"/>
|
||||||
<source>MTU</source>
|
<source>Save settings?</source>
|
||||||
<translation>ام ٹی یو</translation>
|
<translation type="unfinished">ترتیبات محفوظ کریں?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="157"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="139"/>
|
||||||
|
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="140"/>
|
||||||
|
<source>Continue</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="141"/>
|
||||||
|
<source>Cancel</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>MTU</source>
|
||||||
|
<translation type="vanished">ام ٹی یو</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="145"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
|
<translation>جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="149"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="131"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>محفوظ کریں</translation>
|
<translation>محفوظ کریں</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1241,9 +1374,13 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
|
|
||||||
<source>Mail</source>
|
<source>Mail</source>
|
||||||
<translation>میل</translation>
|
<translation type="vanished">میل</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
|
||||||
|
<source>support@amnezia.org</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
|
||||||
@@ -1251,32 +1388,37 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>جائزہ اور بگ رپورٹس کے لئے</translation>
|
<translation>جائزہ اور بگ رپورٹس کے لئے</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="141"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="132"/>
|
||||||
|
<source>Copied</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="143"/>
|
||||||
<source>GitHub</source>
|
<source>GitHub</source>
|
||||||
<translation>گِٹ ہَب</translation>
|
<translation>گِٹ ہَب</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="148"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="150"/>
|
||||||
<source>https://github.com/amnezia-vpn/amnezia-client</source>
|
<source>https://github.com/amnezia-vpn/amnezia-client</source>
|
||||||
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
|
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="159"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="161"/>
|
||||||
<source>Website</source>
|
<source>Website</source>
|
||||||
<translation>ویب سائٹ</translation>
|
<translation>ویب سائٹ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="179"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="181"/>
|
||||||
<source>Software version: %1</source>
|
<source>Software version: %1</source>
|
||||||
<translation>سافٹ ویئر ورژن: %1</translation>
|
<translation>سافٹ ویئر ورژن: %1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="208"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="210"/>
|
||||||
<source>Check for updates</source>
|
<source>Check for updates</source>
|
||||||
<translation>اپ ڈیٹس چیک کریں</translation>
|
<translation>اپ ڈیٹس چیک کریں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="231"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="233"/>
|
||||||
<source>Privacy Policy</source>
|
<source>Privacy Policy</source>
|
||||||
<translation>رازداری کی پالیسی</translation>
|
<translation>رازداری کی پالیسی</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1733,72 +1875,108 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<context>
|
<context>
|
||||||
<name>PageSettingsLogging</name>
|
<name>PageSettingsLogging</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="24"/>
|
|
||||||
<source>Logging is enabled. Note that logs will be automatically disabled after 14 days, and all log files will be deleted.</source>
|
<source>Logging is enabled. Note that logs will be automatically disabled after 14 days, and all log files will be deleted.</source>
|
||||||
<translation>لاگنگ فعال ہے۔ یاد رہے کہ لاگوں کو 14 دنوں کے بعد خود بخود غیر فعال کر دیا جائے گا، اور تمام لاگ فائلیں حذف کردی جائیں گی.</translation>
|
<translation type="vanished">لاگنگ فعال ہے۔ یاد رہے کہ لاگوں کو 14 دنوں کے بعد خود بخود غیر فعال کر دیا جائے گا، اور تمام لاگ فائلیں حذف کردی جائیں گی.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="69"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="56"/>
|
||||||
<source>Logging</source>
|
<source>Logging</source>
|
||||||
<translation>لاگنگ</translation>
|
<translation>لاگنگ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="70"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="57"/>
|
||||||
<source>Enabling this function will save application's logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
|
<source>Enabling this function will save application's logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
|
||||||
<translation>اس فعل کو فعال کرنے سے، ایپلیکیشن کے لاگ خود بخود محفوظ ہوجائیں گے۔ پہلے سے، لاگنگ کی فعالیت غیر فعال ہوتی ہے۔ اگر ایپلیکیشن میں کوئی خرابی ہو، تو لاگ کو بچانا فعال کریں.</translation>
|
<translation>اس فعل کو فعال کرنے سے، ایپلیکیشن کے لاگ خود بخود محفوظ ہوجائیں گے۔ پہلے سے، لاگنگ کی فعالیت غیر فعال ہوتی ہے۔ اگر ایپلیکیشن میں کوئی خرابی ہو، تو لاگ کو بچانا فعال کریں.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="79"/>
|
|
||||||
<source>Save logs</source>
|
<source>Save logs</source>
|
||||||
<translation>لاگوں کو محفوظ کریں</translation>
|
<translation type="vanished">لاگوں کو محفوظ کریں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="117"/>
|
|
||||||
<source>Open folder with logs</source>
|
<source>Open folder with logs</source>
|
||||||
<translation>فائلوں کے فولڈر کو کھولیں</translation>
|
<translation type="vanished">فائلوں کے فولڈر کو کھولیں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="143"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="171"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="255"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>محفوظ</translation>
|
<translation>محفوظ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="172"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="256"/>
|
||||||
<source>Logs files (*.log)</source>
|
<source>Logs files (*.log)</source>
|
||||||
<translation>لاگ فائلیں (*.log)</translation>
|
<translation>لاگ فائلیں (*.log)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="181"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="265"/>
|
||||||
<source>Logs file saved</source>
|
<source>Logs file saved</source>
|
||||||
<translation>لاگ فائل محفوظ ہوگئی</translation>
|
<translation>لاگ فائل محفوظ ہوگئی</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="162"/>
|
|
||||||
<source>Save logs to file</source>
|
<source>Save logs to file</source>
|
||||||
<translation>لاگوں کو فائل میں محفوظ کریں</translation>
|
<translation type="vanished">لاگوں کو فائل میں محفوظ کریں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="184"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="68"/>
|
||||||
|
<source>Enable logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="93"/>
|
||||||
<source>Clear logs?</source>
|
<source>Clear logs?</source>
|
||||||
<translation>کیا آپ لاگوں کو صاف کرنا چاہتے ہیں؟</translation>
|
<translation>کیا آپ لاگوں کو صاف کرنا چاہتے ہیں؟</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="185"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="94"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>براہ کرم جاری رکھیں</translation>
|
<translation>براہ کرم جاری رکھیں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="95"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>منسوخ</translation>
|
<translation>منسوخ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="192"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="101"/>
|
||||||
<source>Logs have been cleaned up</source>
|
<source>Logs have been cleaned up</source>
|
||||||
<translation>تم مسح السجلاتلاگوں کو صاف کر دیا گیا ہے</translation>
|
<translation>تم مسح السجلاتلاگوں کو صاف کر دیا گیا ہے</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="211"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="122"/>
|
||||||
|
<source>Client logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="132"/>
|
||||||
|
<source>AmneziaVPN logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="141"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="220"/>
|
||||||
|
<source>Open logs folder</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="160"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="244"/>
|
||||||
|
<source>Export logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="196"/>
|
||||||
|
<source>Service logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="208"/>
|
||||||
|
<source>AmneziaVPN-service logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="86"/>
|
||||||
<source>Clear logs</source>
|
<source>Clear logs</source>
|
||||||
<translation>لاگوں کو صاف کریں</translation>
|
<translation>لاگوں کو صاف کریں</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1958,22 +2136,21 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation> ترتیبات</translation>
|
<translation> ترتیبات</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="135"/>
|
|
||||||
<source>Clear %1 profile</source>
|
<source>Clear %1 profile</source>
|
||||||
<translation>%1 پروفائل کو صاف کریں</translation>
|
<translation type="vanished">%1 پروفائل کو صاف کریں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="138"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="176"/>
|
||||||
<source>Clear %1 profile?</source>
|
<source>Clear %1 profile?</source>
|
||||||
<translation>کیا آپ واقعی %1 پروفائل کو صاف کرنا چاہتے ہیں؟</translation>
|
<translation>کیا آپ واقعی %1 پروفائل کو صاف کرنا چاہتے ہیں؟</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="145"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="183"/>
|
||||||
<source>Unable to clear %1 profile while there is an active connection</source>
|
<source>Unable to clear %1 profile while there is an active connection</source>
|
||||||
<translation>فعال کنکشن کے دوران %1 پروفائل کو صاف نہیں کیا جا سکتا</translation>
|
<translation>فعال کنکشن کے دوران %1 پروفائل کو صاف نہیں کیا جا سکتا</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="236"/>
|
||||||
<source>Cannot remove active container</source>
|
<source>Cannot remove active container</source>
|
||||||
<translation>فعال کنٹینر کو ہٹانا ممکن نہیں</translation>
|
<translation>فعال کنٹینر کو ہٹانا ممکن نہیں</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1983,29 +2160,54 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="224"/>
|
||||||
<source>Remove </source>
|
<source>Remove </source>
|
||||||
<translation>ہٹائیں </translation>
|
<translation>ہٹائیں </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="191"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="229"/>
|
||||||
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
|
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
|
||||||
<translation>آپ نے جن کے ساتھ کنکشن شئیر کیا تھا، ان تمام صارفین کو اس سے جڑنے کی اجازت نہیں ہوگی.</translation>
|
<translation>آپ نے جن کے ساتھ کنکشن شئیر کیا تھا، ان تمام صارفین کو اس سے جڑنے کی اجازت نہیں ہوگی.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="190"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="228"/>
|
||||||
<source>Remove %1 from server?</source>
|
<source>Remove %1 from server?</source>
|
||||||
<translation>کیا آپ سرور سے %1 کو ہٹانا چاہتے ہیں؟</translation>
|
<translation>کیا آپ سرور سے %1 کو ہٹانا چاہتے ہیں؟</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="140"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="100"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="192"/>
|
<source> connection settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="112"/>
|
||||||
|
<source>Click the "connect" button to create a connection configuration</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="132"/>
|
||||||
|
<source> server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="173"/>
|
||||||
|
<source>Clear profile</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="177"/>
|
||||||
|
<source>The connection configuration will be deleted for this device only</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="178"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="230"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>براہ کرم جاری رکھیں</translation>
|
<translation>براہ کرم جاری رکھیں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="141"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="179"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="193"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="231"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>منسوخ</translation>
|
<translation>منسوخ</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2189,82 +2391,92 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation type="unfinished">کنکشن</translation>
|
<translation type="unfinished">کنکشن</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="83"/>
|
||||||
|
<source>Settings</source>
|
||||||
|
<translation type="unfinished">ترتیبات</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="91"/>
|
||||||
|
<source>Enable logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="112"/>
|
||||||
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="122"/>
|
||||||
<source>Insert key</source>
|
<source>Insert key</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="123"/>
|
||||||
<source>Insert</source>
|
<source>Insert</source>
|
||||||
<translation type="unfinished">داخل کریں</translation>
|
<translation type="unfinished">داخل کریں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="143"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="161"/>
|
||||||
<source>Other connection options</source>
|
<source>Other connection options</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="172"/>
|
||||||
<source>VPN by Amnezia</source>
|
<source>VPN by Amnezia</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="173"/>
|
||||||
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="196"/>
|
||||||
<source>Self-hosted VPN</source>
|
<source>Self-hosted VPN</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="197"/>
|
||||||
<source>Configure Amnezia VPN on your own server</source>
|
<source>Configure Amnezia VPN on your own server</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="217"/>
|
||||||
<source>Restore from backup</source>
|
<source>Restore from backup</source>
|
||||||
<translation type="unfinished">بیک اپ سے بحال کریں</translation>
|
<translation type="unfinished">بیک اپ سے بحال کریں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="223"/>
|
||||||
<source>Open backup file</source>
|
<source>Open backup file</source>
|
||||||
<translation type="unfinished">بیک اپ فائل کو کھولیں</translation>
|
<translation type="unfinished">بیک اپ فائل کو کھولیں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="224"/>
|
||||||
<source>Backup files (*.backup)</source>
|
<source>Backup files (*.backup)</source>
|
||||||
<translation type="unfinished">بیک اپ فائلیں (*.backup)</translation>
|
<translation type="unfinished">بیک اپ فائلیں (*.backup)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="241"/>
|
||||||
<source>File with connection settings</source>
|
<source>File with connection settings</source>
|
||||||
<translation>کنکشن کی ترتیبات والی فائل</translation>
|
<translation>کنکشن کی ترتیبات والی فائل</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="206"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="249"/>
|
||||||
<source>Open config file</source>
|
<source>Open config file</source>
|
||||||
<translation>کنفیگ فائل کو کھولیں</translation>
|
<translation>کنفیگ فائل کو کھولیں</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="225"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="268"/>
|
||||||
<source>QR code</source>
|
<source>QR code</source>
|
||||||
<translation>QR کوڈ</translation>
|
<translation>QR کوڈ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="291"/>
|
||||||
<source>I have nothing</source>
|
<source>I have nothing</source>
|
||||||
<translation type="unfinished">میرے پاس کچھ نہیں ہے</translation>
|
<translation type="unfinished">میرے پاس کچھ نہیں ہے</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2436,7 +2648,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>انسٹال</translation>
|
<translation>انسٹال</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="268"/>
|
||||||
<source>The port must be in the range of 1 to 65535</source>
|
<source>The port must be in the range of 1 to 65535</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2808,12 +3020,17 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>شیئر</translation>
|
<translation>شیئر</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="143"/>
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="147"/>
|
||||||
|
<source>Access error!</source>
|
||||||
|
<translation type="unfinished">رساءی ناممکن!</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="153"/>
|
||||||
<source>Connection to </source>
|
<source>Connection to </source>
|
||||||
<translation>کنکشن کو </translation>
|
<translation>کنکشن کو </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="154"/>
|
||||||
<source>File with connection settings to </source>
|
<source>File with connection settings to </source>
|
||||||
<translation>کنکشن کی ترتیبات کی فائل </translation>
|
<translation>کنکشن کی ترتیبات کی فائل </translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2830,6 +3047,11 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<source>Settings restored from backup file</source>
|
<source>Settings restored from backup file</source>
|
||||||
<translation type="unfinished">ترتیبات بیک اپ فائل سے بحال کردی گئی ہیں</translation>
|
<translation type="unfinished">ترتیبات بیک اپ فائل سے بحال کردی گئی ہیں</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageStart.qml" line="208"/>
|
||||||
|
<source>Logging is enabled. Note that logs will be automaticallydisabled after 14 days, and all log files will be deleted.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PopupType</name>
|
<name>PopupType</name>
|
||||||
@@ -2868,12 +3090,12 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>پاس ورڈ نہیں ملا</translation>
|
<translation>پاس ورڈ نہیں ملا</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="175"/>
|
||||||
<source>Could not open keystore</source>
|
<source>Could not open keystore</source>
|
||||||
<translation>کی اسٹور کھولا نہیں جا سکا</translation>
|
<translation>کی اسٹور کھولا نہیں جا سکا</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="181"/>
|
||||||
<source>Could not remove private key from keystore</source>
|
<source>Could not remove private key from keystore</source>
|
||||||
<translation>خصوصی کلید کو کی اسٹور سے ہٹانا نہیں ہو سکا</translation>
|
<translation>خصوصی کلید کو کی اسٹور سے ہٹانا نہیں ہو سکا</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -3049,27 +3271,27 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>کی اسٹور کھولنے میں ناکام</translation>
|
<translation>کی اسٹور کھولنے میں ناکام</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="126"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="131"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="133"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="139"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="141"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="147"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="149"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="155"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="157"/>
|
||||||
<source>Could not encrypt data</source>
|
<source>Could not encrypt data</source>
|
||||||
<translation>ڈیٹا کو محفوظ کرنے میں ناکام</translation>
|
<translation>ڈیٹا کو محفوظ کرنے میں ناکام</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -3709,12 +3931,12 @@ While it offers a blend of security, stability, and speed, it's essential t
|
|||||||
<context>
|
<context>
|
||||||
<name>SettingsController</name>
|
<name>SettingsController</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/settingsController.cpp" line="138"/>
|
<location filename="../ui/controllers/settingsController.cpp" line="152"/>
|
||||||
<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="160"/>
|
<location filename="../ui/controllers/settingsController.cpp" line="174"/>
|
||||||
<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>
|
||||||
@@ -3846,7 +4068,7 @@ While it offers a blend of security, stability, and speed, it's essential t
|
|||||||
<context>
|
<context>
|
||||||
<name>VpnConnection</name>
|
<name>VpnConnection</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../vpnconnection.cpp" line="375"/>
|
<location filename="../vpnconnection.cpp" line="408"/>
|
||||||
<source>Mbps</source>
|
<source>Mbps</source>
|
||||||
<translation>ایم بی پی ایس</translation>
|
<translation>ایم بی پی ایس</translation>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
@@ -4,47 +4,52 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ApiServicesModel</name>
|
<name>ApiServicesModel</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="63"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
|
||||||
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
|
||||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
|
||||||
|
<source><p><a style="color: #EB5757;">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a></source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
|
||||||
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
<source>Amnezia Premium - A classic VPN for comfortable work, downloading large files, and watching videos in high resolution. It works for all websites, even in countries with the highest level of internet censorship.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="75"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
|
||||||
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
|
||||||
<source>%1 MBit/s</source>
|
<source>%1 MBit/s</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
|
||||||
<source>%1 days</source>
|
<source>%1 days</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
|
||||||
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
|
||||||
<source>Free</source>
|
<source>Free</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
|
||||||
<source>%1 $/month</source>
|
<source>%1 $/month</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -75,7 +80,7 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ConnectButton</name>
|
<name>ConnectButton</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Components/ConnectButton.qml" line="27"/>
|
<location filename="../ui/qml/Components/ConnectButton.qml" line="28"/>
|
||||||
<source>Unable to disconnect during configuration preparation</source>
|
<source>Unable to disconnect during configuration preparation</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -186,9 +191,8 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ExportController</name>
|
<name>ExportController</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/exportController.cpp" line="30"/>
|
|
||||||
<source>Access error!</source>
|
<source>Access error!</source>
|
||||||
<translation>访问错误</translation>
|
<translation type="vanished">访问错误</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -258,18 +262,18 @@ Can't be disabled for current server</source>
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="186"/>
|
<location filename="../ui/controllers/importController.cpp" line="187"/>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="191"/>
|
<location filename="../ui/controllers/importController.cpp" line="192"/>
|
||||||
<source>Invalid configuration file</source>
|
<source>Invalid configuration file</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="606"/>
|
<location filename="../ui/controllers/importController.cpp" line="617"/>
|
||||||
<source>Scanned %1 of %2.</source>
|
<source>Scanned %1 of %2.</source>
|
||||||
<translation>扫描 %1 of %2.</translation>
|
<translation>扫描 %1 of %2.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="641"/>
|
<location filename="../ui/controllers/importController.cpp" line="652"/>
|
||||||
<source>In the imported configuration, potentially dangerous lines were found:</source>
|
<source>In the imported configuration, potentially dangerous lines were found:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -469,6 +473,11 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<source>Gateway endpoint</source>
|
<source>Gateway endpoint</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="101"/>
|
||||||
|
<source>Dev gateway environment</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageHome</name>
|
<name>PageHome</name>
|
||||||
@@ -503,10 +512,63 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>已建立连接时无法更改服务器配置</translation>
|
<translation>已建立连接时无法更改服务器配置</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>PageProtocolAwgClientSettings</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="96"/>
|
||||||
|
<source>AmneziaWG settings</source>
|
||||||
|
<translation type="unfinished">AmneziaWG 配置</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="104"/>
|
||||||
|
<source>MTU</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="184"/>
|
||||||
|
<source>Server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="194"/>
|
||||||
|
<source>Port</source>
|
||||||
|
<translation type="unfinished">端口</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="284"/>
|
||||||
|
<source>Save</source>
|
||||||
|
<translation type="unfinished">保存</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="290"/>
|
||||||
|
<source>Save settings?</source>
|
||||||
|
<translation type="unfinished">保存设置?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="291"/>
|
||||||
|
<source>Only the settings for this device will be changed</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="292"/>
|
||||||
|
<source>Continue</source>
|
||||||
|
<translation type="unfinished">继续</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="293"/>
|
||||||
|
<source>Cancel</source>
|
||||||
|
<translation type="unfinished">取消</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolAwgClientSettings.qml" line="297"/>
|
||||||
|
<source>Unable change settings while there is an active connection</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageProtocolAwgSettings</name>
|
<name>PageProtocolAwgSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="96"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="94"/>
|
||||||
<source>AmneziaWG settings</source>
|
<source>AmneziaWG settings</source>
|
||||||
<translation>AmneziaWG 配置</translation>
|
<translation>AmneziaWG 配置</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -515,11 +577,6 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
<translation>端口</translation>
|
<translation>端口</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
|
|
||||||
<source>MTU</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<source>Remove AmneziaWG</source>
|
<source>Remove AmneziaWG</source>
|
||||||
<translation type="vanished">移除AmneziaWG</translation>
|
<translation type="vanished">移除AmneziaWG</translation>
|
||||||
@@ -529,87 +586,87 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation type="vanished">从服务上移除AmneziaWG?</translation>
|
<translation type="vanished">从服务上移除AmneziaWG?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="374"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="357"/>
|
||||||
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
||||||
<translation>与您共享连接的所有用户将无法再连接到该连接。</translation>
|
<translation>与您共享连接的所有用户将无法再连接到该连接。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="354"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="333"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>保存</translation>
|
<translation>保存</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="147"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
|
||||||
<source>Jc - Junk packet count</source>
|
<source>Jc - Junk packet count</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="151"/>
|
||||||
<source>Jmin - Junk packet minimum size</source>
|
<source>Jmin - Junk packet minimum size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
|
||||||
<source>Jmax - Junk packet maximum size</source>
|
<source>Jmax - Junk packet maximum size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
|
||||||
<source>S1 - Init packet junk size</source>
|
<source>S1 - Init packet junk size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
|
||||||
<source>S2 - Response packet junk size</source>
|
<source>S2 - Response packet junk size</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
|
||||||
<source>H1 - Init packet magic header</source>
|
<source>H1 - Init packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
|
||||||
<source>H2 - Response packet magic header</source>
|
<source>H2 - Response packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="298"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
|
||||||
<source>H4 - Transport packet magic header</source>
|
<source>H4 - Transport packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="320"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="299"/>
|
||||||
<source>H3 - Underload packet magic header</source>
|
<source>H3 - Underload packet magic header</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="345"/>
|
||||||
<source>The values of the H1-H4 fields must be unique</source>
|
<source>The values of the H1-H4 fields must be unique</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="369"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="351"/>
|
||||||
<source>The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)</source>
|
<source>The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="373"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="356"/>
|
||||||
<source>Save settings?</source>
|
<source>Save settings?</source>
|
||||||
<translation>保存设置?</translation>
|
<translation>保存设置?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="375"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="358"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>继续</translation>
|
<translation>继续</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="376"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="359"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>取消</translation>
|
<translation>取消</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="382"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -933,24 +990,82 @@ Already installed containers were found on the server. All installed containers
|
|||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageProtocolWireGuardSettings</name>
|
<name>PageProtocolWireGuardClientSettings</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="94"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="93"/>
|
||||||
<source>WG settings</source>
|
<source>WG settings</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="102"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="101"/>
|
||||||
<source>Port</source>
|
|
||||||
<translation type="unfinished">端口</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="123"/>
|
|
||||||
<source>MTU</source>
|
<source>MTU</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="157"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="118"/>
|
||||||
|
<source>Server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="128"/>
|
||||||
|
<source>Port</source>
|
||||||
|
<translation type="unfinished">端口</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="151"/>
|
||||||
|
<source>Save</source>
|
||||||
|
<translation type="unfinished">保存</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="157"/>
|
||||||
|
<source>Save settings?</source>
|
||||||
|
<translation type="unfinished">保存设置?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="158"/>
|
||||||
|
<source>Only the settings for this device will be changed</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="159"/>
|
||||||
|
<source>Continue</source>
|
||||||
|
<translation type="unfinished">继续</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="160"/>
|
||||||
|
<source>Cancel</source>
|
||||||
|
<translation type="unfinished">取消</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="164"/>
|
||||||
|
<source>Unable change settings while there is an active connection</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>PageProtocolWireGuardSettings</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="97"/>
|
||||||
|
<source>WG settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="107"/>
|
||||||
|
<source>Port</source>
|
||||||
|
<translation type="unfinished">端口</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="138"/>
|
||||||
|
<source>Save settings?</source>
|
||||||
|
<translation type="unfinished">保存设置?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="139"/>
|
||||||
|
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
|
||||||
|
<translation type="unfinished">与您共享连接的所有用户将无法再连接到该连接。</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="145"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -959,15 +1074,17 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation type="obsolete">与您共享连接的所有用户将无法再连接到该连接。</translation>
|
<translation type="obsolete">与您共享连接的所有用户将无法再连接到该连接。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="140"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation type="obsolete">继续</translation>
|
<translation type="unfinished">继续</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="141"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation type="obsolete">取消</translation>
|
<translation type="unfinished">取消</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="149"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="131"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>保存</translation>
|
<translation>保存</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1329,9 +1446,13 @@ And if you don'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/PageSettingsAbout.qml" line="123"/>
|
|
||||||
<source>Mail</source>
|
<source>Mail</source>
|
||||||
<translation>邮件</translation>
|
<translation type="vanished">邮件</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
|
||||||
|
<source>support@amnezia.org</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
|
||||||
@@ -1339,32 +1460,37 @@ And if you don'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/PageSettingsAbout.qml" line="141"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="132"/>
|
||||||
|
<source>Copied</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="143"/>
|
||||||
<source>GitHub</source>
|
<source>GitHub</source>
|
||||||
<translation>GitHub</translation>
|
<translation>GitHub</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="148"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="150"/>
|
||||||
<source>https://github.com/amnezia-vpn/amnezia-client</source>
|
<source>https://github.com/amnezia-vpn/amnezia-client</source>
|
||||||
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
|
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="159"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="161"/>
|
||||||
<source>Website</source>
|
<source>Website</source>
|
||||||
<translation>官网</translation>
|
<translation>官网</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="179"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="181"/>
|
||||||
<source>Software version: %1</source>
|
<source>Software version: %1</source>
|
||||||
<translation>软件版本: %1</translation>
|
<translation>软件版本: %1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="208"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="210"/>
|
||||||
<source>Check for updates</source>
|
<source>Check for updates</source>
|
||||||
<translation>检查更新</translation>
|
<translation>检查更新</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="231"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="233"/>
|
||||||
<source>Privacy Policy</source>
|
<source>Privacy Policy</source>
|
||||||
<translation>隐私政策</translation>
|
<translation>隐私政策</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -1849,72 +1975,104 @@ And if you don't like the app, all the more support it - the donation will
|
|||||||
<context>
|
<context>
|
||||||
<name>PageSettingsLogging</name>
|
<name>PageSettingsLogging</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="24"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="56"/>
|
||||||
<source>Logging is enabled. Note that logs will be automatically disabled after 14 days, and all log files will be deleted.</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="69"/>
|
|
||||||
<source>Logging</source>
|
<source>Logging</source>
|
||||||
<translation>日志</translation>
|
<translation>日志</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="70"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="57"/>
|
||||||
<source>Enabling this function will save application's logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
|
<source>Enabling this function will save application's logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
|
||||||
<translation>默认情况下,日志功能是禁用的。如果应用程序出现故障,则启用日志保存功能。</translation>
|
<translation>默认情况下,日志功能是禁用的。如果应用程序出现故障,则启用日志保存功能。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="79"/>
|
|
||||||
<source>Save logs</source>
|
<source>Save logs</source>
|
||||||
<translation>记录日志</translation>
|
<translation type="vanished">记录日志</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="117"/>
|
|
||||||
<source>Open folder with logs</source>
|
<source>Open folder with logs</source>
|
||||||
<translation>打开日志文件夹</translation>
|
<translation type="vanished">打开日志文件夹</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="143"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="171"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="255"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>保存</translation>
|
<translation>保存</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="172"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="256"/>
|
||||||
<source>Logs files (*.log)</source>
|
<source>Logs files (*.log)</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="181"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="265"/>
|
||||||
<source>Logs file saved</source>
|
<source>Logs file saved</source>
|
||||||
<translation>日志文件已保存</translation>
|
<translation>日志文件已保存</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="162"/>
|
|
||||||
<source>Save logs to file</source>
|
<source>Save logs to file</source>
|
||||||
<translation>保存日志到文件</translation>
|
<translation type="vanished">保存日志到文件</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="184"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="68"/>
|
||||||
|
<source>Enable logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="93"/>
|
||||||
<source>Clear logs?</source>
|
<source>Clear logs?</source>
|
||||||
<translation>清理日志?</translation>
|
<translation>清理日志?</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="185"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="94"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>继续</translation>
|
<translation>继续</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="95"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>取消</translation>
|
<translation>取消</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="192"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="101"/>
|
||||||
<source>Logs have been cleaned up</source>
|
<source>Logs have been cleaned up</source>
|
||||||
<translation>日志已清理</translation>
|
<translation>日志已清理</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="211"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="122"/>
|
||||||
|
<source>Client logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="132"/>
|
||||||
|
<source>AmneziaVPN logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="141"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="220"/>
|
||||||
|
<source>Open logs folder</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="160"/>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="244"/>
|
||||||
|
<source>Export logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="196"/>
|
||||||
|
<source>Service logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="208"/>
|
||||||
|
<source>AmneziaVPN-service logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="86"/>
|
||||||
<source>Clear logs</source>
|
<source>Clear logs</source>
|
||||||
<translation>清理日志</translation>
|
<translation>清理日志</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2102,12 +2260,7 @@ And if you don'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/PageSettingsServerProtocol.qml" line="135"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="176"/>
|
||||||
<source>Clear %1 profile</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="138"/>
|
|
||||||
<source>Clear %1 profile?</source>
|
<source>Clear %1 profile?</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2117,22 +2270,47 @@ And if you don'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/PageSettingsServerProtocol.qml" line="145"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="100"/>
|
||||||
|
<source> connection settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="112"/>
|
||||||
|
<source>Click the "connect" button to create a connection configuration</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="132"/>
|
||||||
|
<source> server settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="173"/>
|
||||||
|
<source>Clear profile</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="177"/>
|
||||||
|
<source>The connection configuration will be deleted for this device only</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="183"/>
|
||||||
<source>Unable to clear %1 profile while there is an active connection</source>
|
<source>Unable to clear %1 profile while there is an active connection</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="224"/>
|
||||||
<source>Remove </source>
|
<source>Remove </source>
|
||||||
<translation>移除</translation>
|
<translation>移除</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="191"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="229"/>
|
||||||
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
|
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
|
||||||
<translation>与您共享连接的所有用户将无法再连接到该连接。</translation>
|
<translation>与您共享连接的所有用户将无法再连接到该连接。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="236"/>
|
||||||
<source>Cannot remove active container</source>
|
<source>Cannot remove active container</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2145,7 +2323,7 @@ And if you don't like the app, all the more support it - the donation will
|
|||||||
<translation type="obsolete"> 从服务器</translation>
|
<translation type="obsolete"> 从服务器</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="190"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="228"/>
|
||||||
<source>Remove %1 from server?</source>
|
<source>Remove %1 from server?</source>
|
||||||
<translation>从服务器移除 %1 ?</translation>
|
<translation>从服务器移除 %1 ?</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2154,14 +2332,14 @@ And if you don't like the app, all the more support it - the donation will
|
|||||||
<translation type="obsolete">与您共享连接的所有用户将无法再连接到此链接</translation>
|
<translation type="obsolete">与您共享连接的所有用户将无法再连接到此链接</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="140"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="178"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="192"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="230"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>继续</translation>
|
<translation>继续</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="141"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="179"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="193"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="231"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>取消</translation>
|
<translation>取消</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2376,82 +2554,92 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<translation type="unfinished">连接</translation>
|
<translation type="unfinished">连接</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="83"/>
|
||||||
|
<source>Settings</source>
|
||||||
|
<translation type="unfinished">设置</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="91"/>
|
||||||
|
<source>Enable logs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="112"/>
|
||||||
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="122"/>
|
||||||
<source>Insert key</source>
|
<source>Insert key</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="123"/>
|
||||||
<source>Insert</source>
|
<source>Insert</source>
|
||||||
<translation type="unfinished">插入</translation>
|
<translation type="unfinished">插入</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="143"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation type="unfinished">继续</translation>
|
<translation type="unfinished">继续</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="161"/>
|
||||||
<source>Other connection options</source>
|
<source>Other connection options</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="172"/>
|
||||||
<source>VPN by Amnezia</source>
|
<source>VPN by Amnezia</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="173"/>
|
||||||
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="196"/>
|
||||||
<source>Self-hosted VPN</source>
|
<source>Self-hosted VPN</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="197"/>
|
||||||
<source>Configure Amnezia VPN on your own server</source>
|
<source>Configure Amnezia VPN on your own server</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="217"/>
|
||||||
<source>Restore from backup</source>
|
<source>Restore from backup</source>
|
||||||
<translation type="unfinished">从备份还原</translation>
|
<translation type="unfinished">从备份还原</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="223"/>
|
||||||
<source>Open backup file</source>
|
<source>Open backup file</source>
|
||||||
<translation type="unfinished">打开备份文件</translation>
|
<translation type="unfinished">打开备份文件</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="224"/>
|
||||||
<source>Backup files (*.backup)</source>
|
<source>Backup files (*.backup)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="241"/>
|
||||||
<source>File with connection settings</source>
|
<source>File with connection settings</source>
|
||||||
<translation>包含连接配置的文件</translation>
|
<translation>包含连接配置的文件</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="206"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="249"/>
|
||||||
<source>Open config file</source>
|
<source>Open config file</source>
|
||||||
<translation>打开配置文件</translation>
|
<translation>打开配置文件</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="225"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="268"/>
|
||||||
<source>QR code</source>
|
<source>QR code</source>
|
||||||
<translation>二维码</translation>
|
<translation>二维码</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="291"/>
|
||||||
<source>I have nothing</source>
|
<source>I have nothing</source>
|
||||||
<translation type="unfinished">我没有</translation>
|
<translation type="unfinished">我没有</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2661,7 +2849,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
|||||||
<translation>安装</translation>
|
<translation>安装</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="268"/>
|
||||||
<source>The port must be in the range of 1 to 65535</source>
|
<source>The port must be in the range of 1 to 65535</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -3077,12 +3265,17 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
|||||||
<translation>共享</translation>
|
<translation>共享</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="143"/>
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="147"/>
|
||||||
|
<source>Access error!</source>
|
||||||
|
<translation type="unfinished">访问错误</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="153"/>
|
||||||
<source>Connection to </source>
|
<source>Connection to </source>
|
||||||
<translation>连接到 </translation>
|
<translation>连接到 </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="154"/>
|
||||||
<source>File with connection settings to </source>
|
<source>File with connection settings to </source>
|
||||||
<translation>连接配置文件的内容为 </translation>
|
<translation>连接配置文件的内容为 </translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -3099,6 +3292,11 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
|||||||
<source>Settings restored from backup file</source>
|
<source>Settings restored from backup file</source>
|
||||||
<translation type="unfinished">从备份文件还原配置</translation>
|
<translation type="unfinished">从备份文件还原配置</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui/qml/Pages2/PageStart.qml" line="208"/>
|
||||||
|
<source>Logging is enabled. Note that logs will be automaticallydisabled after 14 days, and all log files will be deleted.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PopupType</name>
|
<name>PopupType</name>
|
||||||
@@ -3137,12 +3335,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
|||||||
<translation>未发现密码</translation>
|
<translation>未发现密码</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="175"/>
|
||||||
<source>Could not open keystore</source>
|
<source>Could not open keystore</source>
|
||||||
<translation>无法打开密钥库</translation>
|
<translation>无法打开密钥库</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="181"/>
|
||||||
<source>Could not remove private key from keystore</source>
|
<source>Could not remove private key from keystore</source>
|
||||||
<translation>无法从密钥库中删除私钥</translation>
|
<translation>无法从密钥库中删除私钥</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -3318,27 +3516,27 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
|
|||||||
<translation>无法打开密钥库</translation>
|
<translation>无法打开密钥库</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="126"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="131"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="133"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="139"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="141"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="147"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="149"/>
|
||||||
<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/qtkeychain/keychain_android.cpp" line="155"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="157"/>
|
||||||
<source>Could not encrypt data</source>
|
<source>Could not encrypt data</source>
|
||||||
<translation>无法加密数据</translation>
|
<translation>无法加密数据</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -4169,12 +4367,12 @@ While it offers a blend of security, stability, and speed, it's essential t
|
|||||||
<context>
|
<context>
|
||||||
<name>SettingsController</name>
|
<name>SettingsController</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/settingsController.cpp" line="138"/>
|
<location filename="../ui/controllers/settingsController.cpp" line="152"/>
|
||||||
<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="160"/>
|
<location filename="../ui/controllers/settingsController.cpp" line="174"/>
|
||||||
<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>
|
||||||
@@ -4314,7 +4512,7 @@ While it offers a blend of security, stability, and speed, it's essential t
|
|||||||
<context>
|
<context>
|
||||||
<name>VpnConnection</name>
|
<name>VpnConnection</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../vpnconnection.cpp" line="375"/>
|
<location filename="../vpnconnection.cpp" line="408"/>
|
||||||
<source>Mbps</source>
|
<source>Mbps</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
|
|||||||
@@ -10,9 +10,6 @@
|
|||||||
|
|
||||||
#include "core/controllers/vpnConfigurationController.h"
|
#include "core/controllers/vpnConfigurationController.h"
|
||||||
#include "systemController.h"
|
#include "systemController.h"
|
||||||
#ifdef Q_OS_ANDROID
|
|
||||||
#include "platforms/android/android_utils.h"
|
|
||||||
#endif
|
|
||||||
#include "qrcodegen.hpp"
|
#include "qrcodegen.hpp"
|
||||||
|
|
||||||
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
|
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
|
||||||
@@ -24,12 +21,6 @@ ExportController::ExportController(const QSharedPointer<ServersModel> &serversMo
|
|||||||
m_clientManagementModel(clientManagementModel),
|
m_clientManagementModel(clientManagementModel),
|
||||||
m_settings(settings)
|
m_settings(settings)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_ANDROID
|
|
||||||
m_authResultNotifier.reset(new AuthResultNotifier);
|
|
||||||
m_authResultReceiver.reset(new AuthResultReceiver(m_authResultNotifier));
|
|
||||||
connect(m_authResultNotifier.get(), &AuthResultNotifier::authFailed, this, [this]() { emit exportErrorOccurred(tr("Access error!")); });
|
|
||||||
connect(m_authResultNotifier.get(), &AuthResultNotifier::authSuccessful, this, &ExportController::generateFullAccessConfig);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportController::generateFullAccessConfig()
|
void ExportController::generateFullAccessConfig()
|
||||||
@@ -63,26 +54,6 @@ void ExportController::generateFullAccessConfig()
|
|||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_ANDROID)
|
|
||||||
void ExportController::generateFullAccessConfigAndroid()
|
|
||||||
{
|
|
||||||
/* We use builtin keyguard for ssh key export protection on Android */
|
|
||||||
QJniObject activity = AndroidUtils::getActivity();
|
|
||||||
auto appContext = activity.callObjectMethod("getApplicationContext", "()Landroid/content/Context;");
|
|
||||||
if (appContext.isValid()) {
|
|
||||||
auto intent = QJniObject::callStaticObjectMethod("org/amnezia/vpn/AuthHelper", "getAuthIntent",
|
|
||||||
"(Landroid/content/Context;)Landroid/content/Intent;", appContext.object());
|
|
||||||
if (intent.isValid()) {
|
|
||||||
if (intent.object<jobject>() != nullptr) {
|
|
||||||
QtAndroidPrivate::startActivity(intent.object<jobject>(), 1, m_authResultReceiver.get());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
generateFullAccessConfig();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ExportController::generateConnectionConfig(const QString &clientName)
|
void ExportController::generateConnectionConfig(const QString &clientName)
|
||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|||||||
@@ -6,9 +6,6 @@
|
|||||||
#include "ui/models/clientManagementModel.h"
|
#include "ui/models/clientManagementModel.h"
|
||||||
#include "ui/models/containers_model.h"
|
#include "ui/models/containers_model.h"
|
||||||
#include "ui/models/servers_model.h"
|
#include "ui/models/servers_model.h"
|
||||||
#ifdef Q_OS_ANDROID
|
|
||||||
#include "platforms/android/authResultReceiver.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class ExportController : public QObject
|
class ExportController : public QObject
|
||||||
{
|
{
|
||||||
@@ -25,9 +22,6 @@ public:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void generateFullAccessConfig();
|
void generateFullAccessConfig();
|
||||||
#if defined(Q_OS_ANDROID)
|
|
||||||
void generateFullAccessConfigAndroid();
|
|
||||||
#endif
|
|
||||||
void generateConnectionConfig(const QString &clientName);
|
void generateConnectionConfig(const QString &clientName);
|
||||||
void generateOpenVpnConfig(const QString &clientName);
|
void generateOpenVpnConfig(const QString &clientName);
|
||||||
void generateWireGuardConfig(const QString &clientName);
|
void generateWireGuardConfig(const QString &clientName);
|
||||||
@@ -74,11 +68,6 @@ private:
|
|||||||
QString m_config;
|
QString m_config;
|
||||||
QString m_nativeConfigString;
|
QString m_nativeConfigString;
|
||||||
QList<QString> m_qrCodes;
|
QList<QString> m_qrCodes;
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
|
||||||
QSharedPointer<AuthResultNotifier> m_authResultNotifier;
|
|
||||||
QSharedPointer<QAndroidActivityResultReceiver> m_authResultReceiver;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // EXPORTCONTROLLER_H
|
#endif // EXPORTCONTROLLER_H
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
#include <QUrlQuery>
|
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
#include "utilities.h"
|
|
||||||
#include "core/serialization/serialization.h"
|
|
||||||
#include "core/errorstrings.h"
|
#include "core/errorstrings.h"
|
||||||
|
#include "core/serialization/serialization.h"
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
#include "platforms/android/android_controller.h"
|
#include "platforms/android/android_controller.h"
|
||||||
@@ -96,36 +96,40 @@ bool ImportController::extractConfigFromData(QString data)
|
|||||||
|
|
||||||
if (config.startsWith("vless://")) {
|
if (config.startsWith("vless://")) {
|
||||||
m_configType = ConfigTypes::Xray;
|
m_configType = ConfigTypes::Xray;
|
||||||
m_config = extractXrayConfig(Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg),
|
m_config = extractXrayConfig(
|
||||||
QJsonDocument::JsonFormat::Compact), prefix);
|
Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
|
||||||
|
prefix);
|
||||||
return m_config.empty() ? false : true;
|
return m_config.empty() ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.startsWith("vmess://") && config.contains("@")) {
|
if (config.startsWith("vmess://") && config.contains("@")) {
|
||||||
m_configType = ConfigTypes::Xray;
|
m_configType = ConfigTypes::Xray;
|
||||||
m_config = extractXrayConfig(Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg),
|
m_config = extractXrayConfig(
|
||||||
QJsonDocument::JsonFormat::Compact), prefix);
|
Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
|
||||||
|
prefix);
|
||||||
return m_config.empty() ? false : true;
|
return m_config.empty() ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.startsWith("vmess://")) {
|
if (config.startsWith("vmess://")) {
|
||||||
m_configType = ConfigTypes::Xray;
|
m_configType = ConfigTypes::Xray;
|
||||||
m_config = extractXrayConfig(Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg),
|
m_config = extractXrayConfig(
|
||||||
QJsonDocument::JsonFormat::Compact), prefix);
|
Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
|
||||||
|
prefix);
|
||||||
return m_config.empty() ? false : true;
|
return m_config.empty() ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.startsWith("trojan://")) {
|
if (config.startsWith("trojan://")) {
|
||||||
m_configType = ConfigTypes::Xray;
|
m_configType = ConfigTypes::Xray;
|
||||||
m_config = extractXrayConfig(Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg),
|
m_config = extractXrayConfig(
|
||||||
QJsonDocument::JsonFormat::Compact), prefix);
|
Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
|
||||||
|
prefix);
|
||||||
return m_config.empty() ? false : true;
|
return m_config.empty() ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.startsWith("ss://") && !config.contains("plugin=")) {
|
if (config.startsWith("ss://") && !config.contains("plugin=")) {
|
||||||
m_configType = ConfigTypes::ShadowSocks;
|
m_configType = ConfigTypes::ShadowSocks;
|
||||||
m_config = extractXrayConfig(Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg),
|
m_config = extractXrayConfig(
|
||||||
QJsonDocument::JsonFormat::Compact), prefix);
|
Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), prefix);
|
||||||
return m_config.empty() ? false : true;
|
return m_config.empty() ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,6 +177,7 @@ bool ImportController::extractConfigFromData(QString data)
|
|||||||
}
|
}
|
||||||
case ConfigTypes::Amnezia: {
|
case ConfigTypes::Amnezia: {
|
||||||
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
|
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
|
||||||
|
processAmneziaConfig(m_config);
|
||||||
if (!m_config.empty()) {
|
if (!m_config.empty()) {
|
||||||
checkForMaliciousStrings(m_config);
|
checkForMaliciousStrings(m_config);
|
||||||
return true;
|
return true;
|
||||||
@@ -237,24 +242,26 @@ void ImportController::processNativeWireGuardConfig()
|
|||||||
auto containers = m_config.value(config_key::containers).toArray();
|
auto containers = m_config.value(config_key::containers).toArray();
|
||||||
if (!containers.isEmpty()) {
|
if (!containers.isEmpty()) {
|
||||||
auto container = containers.at(0).toObject();
|
auto container = containers.at(0).toObject();
|
||||||
auto containerConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::WireGuard)).toObject();
|
auto serverProtocolConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::WireGuard)).toObject();
|
||||||
auto protocolConfig = QJsonDocument::fromJson(containerConfig.value(config_key::last_config).toString().toUtf8()).object();
|
auto clientProtocolConfig = QJsonDocument::fromJson(serverProtocolConfig.value(config_key::last_config).toString().toUtf8()).object();
|
||||||
|
|
||||||
QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(2, 5));
|
QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(2, 5));
|
||||||
QString junkPacketMinSize = QString::number(10);
|
QString junkPacketMinSize = QString::number(10);
|
||||||
QString junkPacketMaxSize = QString::number(50);
|
QString junkPacketMaxSize = QString::number(50);
|
||||||
protocolConfig[config_key::junkPacketCount] = junkPacketCount;
|
clientProtocolConfig[config_key::junkPacketCount] = junkPacketCount;
|
||||||
protocolConfig[config_key::junkPacketMinSize] = junkPacketMinSize;
|
clientProtocolConfig[config_key::junkPacketMinSize] = junkPacketMinSize;
|
||||||
protocolConfig[config_key::junkPacketMaxSize] = junkPacketMaxSize;
|
clientProtocolConfig[config_key::junkPacketMaxSize] = junkPacketMaxSize;
|
||||||
protocolConfig[config_key::initPacketJunkSize] = "0";
|
clientProtocolConfig[config_key::initPacketJunkSize] = "0";
|
||||||
protocolConfig[config_key::responsePacketJunkSize] = "0";
|
clientProtocolConfig[config_key::responsePacketJunkSize] = "0";
|
||||||
protocolConfig[config_key::initPacketMagicHeader] = "1";
|
clientProtocolConfig[config_key::initPacketMagicHeader] = "1";
|
||||||
protocolConfig[config_key::responsePacketMagicHeader] = "2";
|
clientProtocolConfig[config_key::responsePacketMagicHeader] = "2";
|
||||||
protocolConfig[config_key::underloadPacketMagicHeader] = "3";
|
clientProtocolConfig[config_key::underloadPacketMagicHeader] = "3";
|
||||||
protocolConfig[config_key::transportPacketMagicHeader] = "4";
|
clientProtocolConfig[config_key::transportPacketMagicHeader] = "4";
|
||||||
|
|
||||||
containerConfig[config_key::last_config] = QString(QJsonDocument(protocolConfig).toJson());
|
clientProtocolConfig[config_key::isObfuscationEnabled] = true;
|
||||||
container["wireguard"] = containerConfig;
|
|
||||||
|
serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(clientProtocolConfig).toJson());
|
||||||
|
container["wireguard"] = serverProtocolConfig;
|
||||||
containers.replace(0, container);
|
containers.replace(0, container);
|
||||||
m_config[config_key::containers] = containers;
|
m_config[config_key::containers] = containers;
|
||||||
}
|
}
|
||||||
@@ -353,20 +360,19 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
|||||||
QJsonObject lastConfig;
|
QJsonObject lastConfig;
|
||||||
lastConfig[config_key::config] = data;
|
lastConfig[config_key::config] = data;
|
||||||
|
|
||||||
const static QRegularExpression hostNameAndPortRegExp("Endpoint = (.*):([0-9]*)");
|
auto url { QUrl::fromUserInput(configMap.value("Endpoint")) };
|
||||||
QRegularExpressionMatch hostNameAndPortMatch = hostNameAndPortRegExp.match(data);
|
|
||||||
QString hostName;
|
QString hostName;
|
||||||
QString port;
|
QString port;
|
||||||
if (hostNameAndPortMatch.hasCaptured(1)) {
|
if (!url.host().isEmpty()) {
|
||||||
hostName = hostNameAndPortMatch.captured(1);
|
hostName = url.host();
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Key parameter 'Endpoint' is missing";
|
qDebug() << "Key parameter 'Endpoint' is missing or has an invalid format";
|
||||||
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
|
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
|
||||||
return QJsonObject();
|
return QJsonObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hostNameAndPortMatch.hasCaptured(2)) {
|
if (url.port() != -1) {
|
||||||
port = hostNameAndPortMatch.captured(2);
|
port = QString::number(url.port());
|
||||||
} else {
|
} else {
|
||||||
port = protocols::wireguard::defaultPort;
|
port = protocols::wireguard::defaultPort;
|
||||||
}
|
}
|
||||||
@@ -395,7 +401,11 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
|||||||
lastConfig[config_key::mtu] = configMap.value("MTU");
|
lastConfig[config_key::mtu] = configMap.value("MTU");
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(","));
|
if (!configMap.value("PersistentKeepalive").isEmpty()) {
|
||||||
|
lastConfig[config_key::persistent_keep_alive] = configMap.value("PersistentKeepalive");
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(", "));
|
||||||
|
|
||||||
lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;
|
lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;
|
||||||
|
|
||||||
@@ -419,6 +429,12 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
|||||||
m_configType = ConfigTypes::Awg;
|
m_configType = ConfigTypes::Awg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!configMap.value("MTU").isEmpty()) {
|
||||||
|
lastConfig[config_key::mtu] = configMap.value("MTU");
|
||||||
|
} else {
|
||||||
|
lastConfig[config_key::mtu] = protocolName == "awg" ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
||||||
|
}
|
||||||
|
|
||||||
QJsonObject wireguardConfig;
|
QJsonObject wireguardConfig;
|
||||||
wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson());
|
wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson());
|
||||||
wireguardConfig[config_key::isThirdPartyConfig] = true;
|
wireguardConfig[config_key::isThirdPartyConfig] = true;
|
||||||
@@ -646,3 +662,28 @@ void ImportController::checkForMaliciousStrings(const QJsonObject &serverConfig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImportController::processAmneziaConfig(QJsonObject &config)
|
||||||
|
{
|
||||||
|
auto containers = config.value(config_key::containers).toArray();
|
||||||
|
for (auto i = 0; i < containers.size(); i++) {
|
||||||
|
auto container = containers.at(i).toObject();
|
||||||
|
auto dockerContainer = ContainerProps::containerFromString(container.value(config_key::container).toString());
|
||||||
|
if (dockerContainer == DockerContainer::Awg || dockerContainer == DockerContainer::WireGuard) {
|
||||||
|
auto containerConfig = container.value(ContainerProps::containerTypeToString(dockerContainer)).toObject();
|
||||||
|
auto protocolConfig = containerConfig.value(config_key::last_config).toString();
|
||||||
|
if (protocolConfig.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject jsonConfig = QJsonDocument::fromJson(protocolConfig.toUtf8()).object();
|
||||||
|
jsonConfig[config_key::mtu] = dockerContainer == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
||||||
|
|
||||||
|
containerConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
||||||
|
|
||||||
|
container[ContainerProps::containerTypeToString(dockerContainer)] = containerConfig;
|
||||||
|
containers.replace(i, container);
|
||||||
|
config.insert(config_key::containers, containers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ private:
|
|||||||
|
|
||||||
void checkForMaliciousStrings(const QJsonObject &protocolConfig);
|
void checkForMaliciousStrings(const QJsonObject &protocolConfig);
|
||||||
|
|
||||||
|
void processAmneziaConfig(QJsonObject &config);
|
||||||
|
|
||||||
#if defined Q_OS_ANDROID || defined Q_OS_IOS
|
#if defined Q_OS_ANDROID || defined Q_OS_IOS
|
||||||
void stopDecodingQr();
|
void stopDecodingQr();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -799,7 +799,7 @@ void InstallController::addEmptyServer()
|
|||||||
|
|
||||||
bool InstallController::fillAvailableServices()
|
bool InstallController::fillAvailableServices()
|
||||||
{
|
{
|
||||||
ApiController apiController(m_settings->getGatewayEndpoint());
|
ApiController apiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
|
||||||
|
|
||||||
QByteArray responseBody;
|
QByteArray responseBody;
|
||||||
ErrorCode errorCode = apiController.getServicesList(responseBody);
|
ErrorCode errorCode = apiController.getServicesList(responseBody);
|
||||||
@@ -821,7 +821,7 @@ bool InstallController::installServiceFromApi()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiController apiController(m_settings->getGatewayEndpoint());
|
ApiController apiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
|
||||||
QJsonObject serverConfig;
|
QJsonObject serverConfig;
|
||||||
|
|
||||||
ErrorCode errorCode = apiController.getConfigForService(m_settings->getInstallationUuid(true), m_apiServicesModel->getCountryCode(),
|
ErrorCode errorCode = apiController.getConfigForService(m_settings->getInstallationUuid(true), m_apiServicesModel->getCountryCode(),
|
||||||
@@ -849,7 +849,7 @@ bool InstallController::installServiceFromApi()
|
|||||||
bool InstallController::updateServiceFromApi(const int serverIndex, const QString &newCountryCode, const QString &newCountryName,
|
bool InstallController::updateServiceFromApi(const int serverIndex, const QString &newCountryCode, const QString &newCountryName,
|
||||||
bool reloadServiceConfig)
|
bool reloadServiceConfig)
|
||||||
{
|
{
|
||||||
ApiController apiController(m_settings->getGatewayEndpoint());
|
ApiController apiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
|
||||||
|
|
||||||
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||||
auto apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
auto apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
||||||
@@ -885,7 +885,7 @@ bool InstallController::updateServiceFromApi(const int serverIndex, const QStrin
|
|||||||
|
|
||||||
void InstallController::updateServiceFromTelegram(const int serverIndex)
|
void InstallController::updateServiceFromTelegram(const int serverIndex)
|
||||||
{
|
{
|
||||||
ApiController *apiController = new ApiController(m_settings->getGatewayEndpoint());
|
ApiController *apiController = new ApiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
|
||||||
|
|
||||||
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
#include "platforms/android/android_controller.h"
|
#include "platforms/android/android_controller.h"
|
||||||
#include "platforms/android/android_utils.h"
|
|
||||||
#include <QJniObject>
|
|
||||||
#endif
|
#endif
|
||||||
#if defined Q_OS_MAC
|
#if defined Q_OS_MAC
|
||||||
#include "ui/macos_util.h"
|
#include "ui/macos_util.h"
|
||||||
@@ -22,18 +20,8 @@ PageController::PageController(const QSharedPointer<ServersModel> &serversModel,
|
|||||||
: QObject(parent), m_serversModel(serversModel), m_settings(settings)
|
: QObject(parent), m_serversModel(serversModel), m_settings(settings)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
// Change color of navigation and status bar's
|
|
||||||
auto initialPageNavigationBarColor = getInitialPageNavigationBarColor();
|
auto initialPageNavigationBarColor = getInitialPageNavigationBarColor();
|
||||||
AndroidUtils::runOnAndroidThreadSync([&initialPageNavigationBarColor]() {
|
AndroidController::instance()->setNavigationBarColor(initialPageNavigationBarColor);
|
||||||
QJniObject activity = AndroidUtils::getActivity();
|
|
||||||
QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
|
|
||||||
if (window.isValid()) {
|
|
||||||
window.callMethod<void>("addFlags", "(I)V", 0x80000000);
|
|
||||||
window.callMethod<void>("clearFlags", "(I)V", 0x04000000);
|
|
||||||
window.callMethod<void>("setStatusBarColor", "(I)V", 0xFF0E0E11);
|
|
||||||
window.callMethod<void>("setNavigationBarColor", "(I)V", initialPageNavigationBarColor);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined Q_OS_MACX
|
#if defined Q_OS_MACX
|
||||||
@@ -115,14 +103,7 @@ unsigned int PageController::getInitialPageNavigationBarColor()
|
|||||||
void PageController::updateNavigationBarColor(const int color)
|
void PageController::updateNavigationBarColor(const int color)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
// Change color of navigation bar
|
AndroidController::instance()->setNavigationBarColor(color);
|
||||||
AndroidUtils::runOnAndroidThreadSync([&color]() {
|
|
||||||
QJniObject activity = AndroidUtils::getActivity();
|
|
||||||
QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
|
|
||||||
if (window.isValid()) {
|
|
||||||
window.callMethod<void>("setNavigationBarColor", "(I)V", color);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +112,7 @@ void PageController::showOnStartup()
|
|||||||
if (!m_settings->isStartMinimized()) {
|
if (!m_settings->isStartMinimized()) {
|
||||||
emit raiseMainWindow();
|
emit raiseMainWindow();
|
||||||
} else {
|
} else {
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX)
|
#if defined(Q_OS_WIN) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
|
||||||
emit hideMainWindow();
|
emit hideMainWindow();
|
||||||
#elif defined Q_OS_MACX
|
#elif defined Q_OS_MACX
|
||||||
setDockIconVisible(false);
|
setDockIconVisible(false);
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ namespace PageLoader
|
|||||||
PageProtocolIKev2Settings,
|
PageProtocolIKev2Settings,
|
||||||
PageProtocolRaw,
|
PageProtocolRaw,
|
||||||
|
|
||||||
|
PageProtocolWireGuardClientSettings,
|
||||||
|
PageProtocolAwgClientSettings,
|
||||||
|
|
||||||
PageShareFullAccess,
|
PageShareFullAccess,
|
||||||
|
|
||||||
PageDevMenu
|
PageDevMenu
|
||||||
|
|||||||
@@ -88,7 +88,12 @@ void SettingsController::toggleLogging(bool enable)
|
|||||||
|
|
||||||
void SettingsController::openLogsFolder()
|
void SettingsController::openLogsFolder()
|
||||||
{
|
{
|
||||||
Logger::openLogsFolder();
|
Logger::openLogsFolder(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsController::openServiceLogsFolder()
|
||||||
|
{
|
||||||
|
Logger::openLogsFolder(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsController::exportLogsFile(const QString &fileName)
|
void SettingsController::exportLogsFile(const QString &fileName)
|
||||||
@@ -100,12 +105,21 @@ void SettingsController::exportLogsFile(const QString &fileName)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsController::exportServiceLogsFile(const QString &fileName)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
AndroidController::instance()->exportLogsFile(fileName);
|
||||||
|
#else
|
||||||
|
SystemController::saveFile(fileName, Logger::getServiceLogFile());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsController::clearLogs()
|
void SettingsController::clearLogs()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
AndroidController::instance()->clearLogs();
|
AndroidController::instance()->clearLogs();
|
||||||
#else
|
#else
|
||||||
Logger::clearLogs();
|
Logger::clearLogs(false);
|
||||||
Logger::clearServiceLogs();
|
Logger::clearServiceLogs();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -283,5 +297,31 @@ void SettingsController::setGatewayEndpoint(const QString &endpoint)
|
|||||||
|
|
||||||
QString SettingsController::getGatewayEndpoint()
|
QString SettingsController::getGatewayEndpoint()
|
||||||
{
|
{
|
||||||
return m_settings->getGatewayEndpoint();
|
return m_settings->isDevGatewayEnv() ? "Dev endpoint" : m_settings->getGatewayEndpoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsController::isDevGatewayEnv()
|
||||||
|
{
|
||||||
|
return m_settings->isDevGatewayEnv();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsController::toggleDevGatewayEnv(bool enabled)
|
||||||
|
{
|
||||||
|
m_settings->toggleDevGatewayEnv(enabled);
|
||||||
|
if (enabled) {
|
||||||
|
m_settings->setDevGatewayEndpoint();
|
||||||
|
} else {
|
||||||
|
m_settings->resetGatewayEndpoint();
|
||||||
|
}
|
||||||
|
emit gatewayEndpointChanged(m_settings->getGatewayEndpoint());
|
||||||
|
emit devGatewayEnvChanged(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsController::isOnTv()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
return AndroidController::instance()->isOnTv();
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
@@ -27,6 +27,7 @@ public:
|
|||||||
|
|
||||||
Q_PROPERTY(bool isDevModeEnabled READ isDevModeEnabled NOTIFY devModeEnabled)
|
Q_PROPERTY(bool isDevModeEnabled READ isDevModeEnabled NOTIFY devModeEnabled)
|
||||||
Q_PROPERTY(QString gatewayEndpoint READ getGatewayEndpoint WRITE setGatewayEndpoint NOTIFY gatewayEndpointChanged)
|
Q_PROPERTY(QString gatewayEndpoint READ getGatewayEndpoint WRITE setGatewayEndpoint NOTIFY gatewayEndpointChanged)
|
||||||
|
Q_PROPERTY(bool isDevGatewayEnv READ isDevGatewayEnv WRITE toggleDevGatewayEnv NOTIFY devGatewayEnvChanged)
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void toggleAmneziaDns(bool enable);
|
void toggleAmneziaDns(bool enable);
|
||||||
@@ -42,7 +43,9 @@ public slots:
|
|||||||
void toggleLogging(bool enable);
|
void toggleLogging(bool enable);
|
||||||
|
|
||||||
void openLogsFolder();
|
void openLogsFolder();
|
||||||
|
void openServiceLogsFolder();
|
||||||
void exportLogsFile(const QString &fileName);
|
void exportLogsFile(const QString &fileName);
|
||||||
|
void exportServiceLogsFile(const QString &fileName);
|
||||||
void clearLogs();
|
void clearLogs();
|
||||||
|
|
||||||
void backupAppConfig(const QString &fileName);
|
void backupAppConfig(const QString &fileName);
|
||||||
@@ -81,6 +84,10 @@ public slots:
|
|||||||
void resetGatewayEndpoint();
|
void resetGatewayEndpoint();
|
||||||
void setGatewayEndpoint(const QString &endpoint);
|
void setGatewayEndpoint(const QString &endpoint);
|
||||||
QString getGatewayEndpoint();
|
QString getGatewayEndpoint();
|
||||||
|
bool isDevGatewayEnv();
|
||||||
|
void toggleDevGatewayEnv(bool enabled);
|
||||||
|
|
||||||
|
bool isOnTv();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void primaryDnsChanged();
|
void primaryDnsChanged();
|
||||||
@@ -103,6 +110,7 @@ signals:
|
|||||||
|
|
||||||
void devModeEnabled();
|
void devModeEnabled();
|
||||||
void gatewayEndpointChanged(const QString &endpoint);
|
void gatewayEndpointChanged(const QString &endpoint);
|
||||||
|
void devGatewayEnvChanged(bool enabled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
QSharedPointer<ServersModel> m_serversModel;
|
||||||
|
|||||||
@@ -125,3 +125,12 @@ void SystemController::setQmlRoot(QObject *qmlRoot)
|
|||||||
{
|
{
|
||||||
m_qmlRoot = qmlRoot;
|
m_qmlRoot = qmlRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SystemController::isAuthenticated()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
return AndroidController::instance()->requestAuthentication();
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public slots:
|
|||||||
|
|
||||||
void setQmlRoot(QObject *qmlRoot);
|
void setQmlRoot(QObject *qmlRoot);
|
||||||
|
|
||||||
|
bool isAuthenticated();
|
||||||
signals:
|
signals:
|
||||||
void fileDialogClosed(const bool isAccepted);
|
void fileDialogClosed(const bool isAccepted);
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ namespace
|
|||||||
constexpr char availableCountries[] = "available_countries";
|
constexpr char availableCountries[] = "available_countries";
|
||||||
|
|
||||||
constexpr char storeEndpoint[] = "store_endpoint";
|
constexpr char storeEndpoint[] = "store_endpoint";
|
||||||
|
|
||||||
|
constexpr char isAvailable[] = "is_available";
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace serviceType
|
namespace serviceType
|
||||||
@@ -63,8 +65,12 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
|
|||||||
return tr("Classic VPN for comfortable work, downloading large files and watching videos. "
|
return tr("Classic VPN for comfortable work, downloading large files and watching videos. "
|
||||||
"Works for any sites. Speed up to %1 MBit/s")
|
"Works for any sites. Speed up to %1 MBit/s")
|
||||||
.arg(speed);
|
.arg(speed);
|
||||||
} else {
|
} else if (serviceType == serviceType::amneziaFree){
|
||||||
return tr("VPN to access blocked sites in regions with high levels of Internet censorship. ");
|
QString description = tr("VPN to access blocked sites in regions with high levels of Internet censorship. ");
|
||||||
|
if (service.value(configKey::isAvailable).isBool() && !service.value(configKey::isAvailable).toBool()) {
|
||||||
|
description += tr("<p><a style=\"color: #EB5757;\">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a>");
|
||||||
|
}
|
||||||
|
return description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ServiceDescriptionRole: {
|
case ServiceDescriptionRole: {
|
||||||
@@ -75,6 +81,14 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
|
|||||||
return tr("Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship");
|
return tr("Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case IsServiceAvailableRole: {
|
||||||
|
if (serviceType == serviceType::amneziaFree) {
|
||||||
|
if (service.value(configKey::isAvailable).isBool() && !service.value(configKey::isAvailable).toBool()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
case SpeedRole: {
|
case SpeedRole: {
|
||||||
auto speed = serviceInfo.value(configKey::speed).toString();
|
auto speed = serviceInfo.value(configKey::speed).toString();
|
||||||
return tr("%1 MBit/s").arg(speed);
|
return tr("%1 MBit/s").arg(speed);
|
||||||
@@ -193,6 +207,7 @@ QHash<int, QByteArray> ApiServicesModel::roleNames() const
|
|||||||
roles[NameRole] = "name";
|
roles[NameRole] = "name";
|
||||||
roles[CardDescriptionRole] = "cardDescription";
|
roles[CardDescriptionRole] = "cardDescription";
|
||||||
roles[ServiceDescriptionRole] = "serviceDescription";
|
roles[ServiceDescriptionRole] = "serviceDescription";
|
||||||
|
roles[IsServiceAvailableRole] = "isServiceAvailable";
|
||||||
roles[SpeedRole] = "speed";
|
roles[SpeedRole] = "speed";
|
||||||
roles[WorkPeriodRole] = "workPeriod";
|
roles[WorkPeriodRole] = "workPeriod";
|
||||||
roles[RegionRole] = "region";
|
roles[RegionRole] = "region";
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public:
|
|||||||
NameRole = Qt::UserRole + 1,
|
NameRole = Qt::UserRole + 1,
|
||||||
CardDescriptionRole,
|
CardDescriptionRole,
|
||||||
ServiceDescriptionRole,
|
ServiceDescriptionRole,
|
||||||
|
IsServiceAvailableRole,
|
||||||
SpeedRole,
|
SpeedRole,
|
||||||
WorkPeriodRole,
|
WorkPeriodRole,
|
||||||
RegionRole,
|
RegionRole,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace
|
|||||||
constexpr char latestHandshake[] = "latestHandshake";
|
constexpr char latestHandshake[] = "latestHandshake";
|
||||||
constexpr char dataReceived[] = "dataReceived";
|
constexpr char dataReceived[] = "dataReceived";
|
||||||
constexpr char dataSent[] = "dataSent";
|
constexpr char dataSent[] = "dataSent";
|
||||||
|
constexpr char allowedIps[] = "allowedIps";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
|
|||||||
case LatestHandshakeRole: return userData.value(configKey::latestHandshake).toString();
|
case LatestHandshakeRole: return userData.value(configKey::latestHandshake).toString();
|
||||||
case DataReceivedRole: return userData.value(configKey::dataReceived).toString();
|
case DataReceivedRole: return userData.value(configKey::dataReceived).toString();
|
||||||
case DataSentRole: return userData.value(configKey::dataSent).toString();
|
case DataSentRole: return userData.value(configKey::dataSent).toString();
|
||||||
|
case AllowedIpsRole: return userData.value(configKey::allowedIps).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@@ -141,6 +143,10 @@ ErrorCode ClientManagementModel::updateModel(const DockerContainer container, co
|
|||||||
userData[configKey::dataSent] = client.dataSent;
|
userData[configKey::dataSent] = client.dataSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!client.allowedIps.isEmpty()) {
|
||||||
|
userData[configKey::allowedIps] = client.allowedIps;
|
||||||
|
}
|
||||||
|
|
||||||
obj[configKey::userData] = userData;
|
obj[configKey::userData] = userData;
|
||||||
m_clientsTable.replace(i, obj);
|
m_clientsTable.replace(i, obj);
|
||||||
break;
|
break;
|
||||||
@@ -266,8 +272,9 @@ ErrorCode ClientManagementModel::wgShow(const DockerContainer container, const S
|
|||||||
const auto peerList = parts.filter("peer:");
|
const auto peerList = parts.filter("peer:");
|
||||||
const auto latestHandshakeList = parts.filter("latest handshake:");
|
const auto latestHandshakeList = parts.filter("latest handshake:");
|
||||||
const auto transferredDataList = parts.filter("transfer:");
|
const auto transferredDataList = parts.filter("transfer:");
|
||||||
|
const auto allowedIpsList = parts.filter("allowed ips:");
|
||||||
|
|
||||||
if (latestHandshakeList.isEmpty() || transferredDataList.isEmpty() || peerList.isEmpty()) {
|
if (allowedIpsList.isEmpty() || latestHandshakeList.isEmpty() || transferredDataList.isEmpty() || peerList.isEmpty()) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,19 +288,20 @@ ErrorCode ClientManagementModel::wgShow(const DockerContainer container, const S
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < peerList.size() && i < transferredDataList.size() && i < latestHandshakeList.size(); ++i) {
|
for (int i = 0; i < peerList.size() && i < transferredDataList.size() && i < latestHandshakeList.size() && i < allowedIpsList.size(); ++i) {
|
||||||
|
|
||||||
const auto transferredData = getStrValue(transferredDataList[i]).split(",");
|
const auto transferredData = getStrValue(transferredDataList[i]).split(",");
|
||||||
auto latestHandshake = getStrValue(latestHandshakeList[i]);
|
auto latestHandshake = getStrValue(latestHandshakeList[i]);
|
||||||
auto serverBytesReceived = transferredData.front().trimmed();
|
auto serverBytesReceived = transferredData.front().trimmed();
|
||||||
auto serverBytesSent = transferredData.back().trimmed();
|
auto serverBytesSent = transferredData.back().trimmed();
|
||||||
|
auto allowedIps = getStrValue(allowedIpsList[i]);
|
||||||
|
|
||||||
changeHandshakeFormat(latestHandshake);
|
changeHandshakeFormat(latestHandshake);
|
||||||
|
|
||||||
serverBytesReceived.chop(QStringLiteral(" received").length());
|
serverBytesReceived.chop(QStringLiteral(" received").length());
|
||||||
serverBytesSent.chop(QStringLiteral(" sent").length());
|
serverBytesSent.chop(QStringLiteral(" sent").length());
|
||||||
|
|
||||||
data.push_back({ getStrValue(peerList[i]), latestHandshake, serverBytesSent, serverBytesReceived });
|
data.push_back({ getStrValue(peerList[i]), latestHandshake, serverBytesSent, serverBytesReceived, allowedIps });
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ public:
|
|||||||
CreationDateRole,
|
CreationDateRole,
|
||||||
LatestHandshakeRole,
|
LatestHandshakeRole,
|
||||||
DataReceivedRole,
|
DataReceivedRole,
|
||||||
DataSentRole
|
DataSentRole,
|
||||||
|
AllowedIpsRole
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WgShowData
|
struct WgShowData
|
||||||
@@ -26,6 +27,7 @@ public:
|
|||||||
QString latestHandshake;
|
QString latestHandshake;
|
||||||
QString dataReceived;
|
QString dataReceived;
|
||||||
QString dataSent;
|
QString dataSent;
|
||||||
|
QString allowedIps;
|
||||||
};
|
};
|
||||||
|
|
||||||
ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||||
|
|||||||
@@ -21,17 +21,30 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
|
||||||
case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break;
|
|
||||||
case Roles::JunkPacketCountRole: m_protocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
|
||||||
case Roles::JunkPacketMinSizeRole: m_protocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
case Roles::ClientJunkPacketCountRole: m_clientProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
||||||
case Roles::JunkPacketMaxSizeRole: m_protocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
case Roles::ClientJunkPacketMinSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
||||||
case Roles::InitPacketJunkSizeRole: m_protocolConfig.insert(config_key::initPacketJunkSize, value.toString()); break;
|
case Roles::ClientJunkPacketMaxSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
||||||
case Roles::ResponsePacketJunkSizeRole: m_protocolConfig.insert(config_key::responsePacketJunkSize, value.toString()); break;
|
|
||||||
case Roles::InitPacketMagicHeaderRole: m_protocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break;
|
case Roles::ServerJunkPacketCountRole: m_serverProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
||||||
case Roles::ResponsePacketMagicHeaderRole: m_protocolConfig.insert(config_key::responsePacketMagicHeader, value.toString()); break;
|
case Roles::ServerJunkPacketMinSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
||||||
case Roles::UnderloadPacketMagicHeaderRole: m_protocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString()); break;
|
case Roles::ServerJunkPacketMaxSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
||||||
case Roles::TransportPacketMagicHeaderRole: m_protocolConfig.insert(config_key::transportPacketMagicHeader, value.toString()); break;
|
case Roles::ServerInitPacketJunkSizeRole: m_serverProtocolConfig.insert(config_key::initPacketJunkSize, value.toString()); break;
|
||||||
|
case Roles::ServerResponsePacketJunkSizeRole:
|
||||||
|
m_serverProtocolConfig.insert(config_key::responsePacketJunkSize, value.toString());
|
||||||
|
break;
|
||||||
|
case Roles::ServerInitPacketMagicHeaderRole: m_serverProtocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break;
|
||||||
|
case Roles::ServerResponsePacketMagicHeaderRole:
|
||||||
|
m_serverProtocolConfig.insert(config_key::responsePacketMagicHeader, value.toString());
|
||||||
|
break;
|
||||||
|
case Roles::ServerUnderloadPacketMagicHeaderRole:
|
||||||
|
m_serverProtocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString());
|
||||||
|
break;
|
||||||
|
case Roles::ServerTransportPacketMagicHeaderRole:
|
||||||
|
m_serverProtocolConfig.insert(config_key::transportPacketMagicHeader, value.toString());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit dataChanged(index, index, QList { role });
|
emit dataChanged(index, index, QList { role });
|
||||||
@@ -45,17 +58,22 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
|
case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
|
||||||
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString();
|
|
||||||
case Roles::JunkPacketCountRole: return m_protocolConfig.value(config_key::junkPacketCount);
|
case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
|
||||||
case Roles::JunkPacketMinSizeRole: return m_protocolConfig.value(config_key::junkPacketMinSize);
|
case Roles::ClientJunkPacketCountRole: return m_clientProtocolConfig.value(config_key::junkPacketCount);
|
||||||
case Roles::JunkPacketMaxSizeRole: return m_protocolConfig.value(config_key::junkPacketMaxSize);
|
case Roles::ClientJunkPacketMinSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMinSize);
|
||||||
case Roles::InitPacketJunkSizeRole: return m_protocolConfig.value(config_key::initPacketJunkSize);
|
case Roles::ClientJunkPacketMaxSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMaxSize);
|
||||||
case Roles::ResponsePacketJunkSizeRole: return m_protocolConfig.value(config_key::responsePacketJunkSize);
|
|
||||||
case Roles::InitPacketMagicHeaderRole: return m_protocolConfig.value(config_key::initPacketMagicHeader);
|
case Roles::ServerJunkPacketCountRole: return m_serverProtocolConfig.value(config_key::junkPacketCount);
|
||||||
case Roles::ResponsePacketMagicHeaderRole: return m_protocolConfig.value(config_key::responsePacketMagicHeader);
|
case Roles::ServerJunkPacketMinSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMinSize);
|
||||||
case Roles::UnderloadPacketMagicHeaderRole: return m_protocolConfig.value(config_key::underloadPacketMagicHeader);
|
case Roles::ServerJunkPacketMaxSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMaxSize);
|
||||||
case Roles::TransportPacketMagicHeaderRole: return m_protocolConfig.value(config_key::transportPacketMagicHeader);
|
case Roles::ServerInitPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::initPacketJunkSize);
|
||||||
|
case Roles::ServerResponsePacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::responsePacketJunkSize);
|
||||||
|
case Roles::ServerInitPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::initPacketMagicHeader);
|
||||||
|
case Roles::ServerResponsePacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::responsePacketMagicHeader);
|
||||||
|
case Roles::ServerUnderloadPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::underloadPacketMagicHeader);
|
||||||
|
case Roles::ServerTransportPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::transportPacketMagicHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@@ -68,51 +86,63 @@ void AwgConfigModel::updateModel(const QJsonObject &config)
|
|||||||
|
|
||||||
m_fullConfig = config;
|
m_fullConfig = config;
|
||||||
|
|
||||||
QJsonObject protocolConfig = config.value(config_key::awg).toObject();
|
QJsonObject serverProtocolConfig = config.value(config_key::awg).toObject();
|
||||||
|
|
||||||
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Awg), Proto::Awg);
|
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Awg), Proto::Awg);
|
||||||
m_protocolConfig.insert(config_key::transport_proto, protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
m_serverProtocolConfig.insert(config_key::transport_proto,
|
||||||
m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config);
|
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
||||||
m_protocolConfig[config_key::port] = protocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
|
||||||
m_protocolConfig[config_key::mtu] = protocolConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu);
|
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||||
m_protocolConfig[config_key::junkPacketCount] =
|
m_serverProtocolConfig[config_key::junkPacketCount] =
|
||||||
protocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||||
m_protocolConfig[config_key::junkPacketMinSize] =
|
m_serverProtocolConfig[config_key::junkPacketMinSize] =
|
||||||
protocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||||
m_protocolConfig[config_key::junkPacketMaxSize] =
|
m_serverProtocolConfig[config_key::junkPacketMaxSize] =
|
||||||
protocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||||
m_protocolConfig[config_key::initPacketJunkSize] =
|
m_serverProtocolConfig[config_key::initPacketJunkSize] =
|
||||||
protocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
||||||
m_protocolConfig[config_key::responsePacketJunkSize] =
|
m_serverProtocolConfig[config_key::responsePacketJunkSize] =
|
||||||
protocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
||||||
m_protocolConfig[config_key::initPacketMagicHeader] =
|
m_serverProtocolConfig[config_key::initPacketMagicHeader] =
|
||||||
protocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||||
m_protocolConfig[config_key::responsePacketMagicHeader] =
|
m_serverProtocolConfig[config_key::responsePacketMagicHeader] =
|
||||||
protocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
|
serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
|
||||||
m_protocolConfig[config_key::underloadPacketMagicHeader] =
|
m_serverProtocolConfig[config_key::underloadPacketMagicHeader] =
|
||||||
protocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
||||||
m_protocolConfig[config_key::transportPacketMagicHeader] =
|
m_serverProtocolConfig[config_key::transportPacketMagicHeader] =
|
||||||
protocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
|
serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
|
||||||
|
|
||||||
|
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
|
||||||
|
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||||
|
m_clientProtocolConfig[config_key::mtu] = clientProtocolConfig[config_key::mtu].toString(protocols::awg::defaultMtu);
|
||||||
|
m_clientProtocolConfig[config_key::junkPacketCount] =
|
||||||
|
clientProtocolConfig.value(config_key::junkPacketCount).toString(m_serverProtocolConfig[config_key::junkPacketCount].toString());
|
||||||
|
m_clientProtocolConfig[config_key::junkPacketMinSize] =
|
||||||
|
clientProtocolConfig.value(config_key::junkPacketMinSize).toString(m_serverProtocolConfig[config_key::junkPacketMinSize].toString());
|
||||||
|
m_clientProtocolConfig[config_key::junkPacketMaxSize] =
|
||||||
|
clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(m_serverProtocolConfig[config_key::junkPacketMaxSize].toString());
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject AwgConfigModel::getConfig()
|
QJsonObject AwgConfigModel::getConfig()
|
||||||
{
|
{
|
||||||
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
|
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
|
||||||
const AwgConfig newConfig(m_protocolConfig);
|
const AwgConfig newConfig(m_serverProtocolConfig);
|
||||||
|
|
||||||
if (!oldConfig.hasEqualServerSettings(newConfig)) {
|
if (!oldConfig.hasEqualServerSettings(newConfig)) {
|
||||||
m_protocolConfig.remove(config_key::last_config);
|
m_serverProtocolConfig.remove(config_key::last_config);
|
||||||
} else {
|
} else {
|
||||||
auto lastConfig = m_protocolConfig.value(config_key::last_config).toString();
|
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
|
||||||
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||||
jsonConfig[config_key::mtu] = newConfig.mtu;
|
jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu];
|
||||||
|
jsonConfig[config_key::junkPacketCount] = m_clientProtocolConfig[config_key::junkPacketCount];
|
||||||
|
jsonConfig[config_key::junkPacketMinSize] = m_clientProtocolConfig[config_key::junkPacketMinSize];
|
||||||
|
jsonConfig[config_key::junkPacketMaxSize] = m_clientProtocolConfig[config_key::junkPacketMaxSize];
|
||||||
|
|
||||||
m_protocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_fullConfig.insert(config_key::awg, m_protocolConfig);
|
m_fullConfig.insert(config_key::awg, m_serverProtocolConfig);
|
||||||
return m_fullConfig;
|
return m_fullConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,50 +156,73 @@ bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2)
|
|||||||
return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2);
|
return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AwgConfigModel::isServerSettingsEqual()
|
||||||
|
{
|
||||||
|
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
|
||||||
|
const AwgConfig newConfig(m_serverProtocolConfig);
|
||||||
|
|
||||||
|
return oldConfig.hasEqualServerSettings(newConfig);
|
||||||
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> AwgConfigModel::roleNames() const
|
QHash<int, QByteArray> AwgConfigModel::roleNames() const
|
||||||
{
|
{
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
|
|
||||||
roles[PortRole] = "port";
|
roles[PortRole] = "port";
|
||||||
roles[MtuRole] = "mtu";
|
|
||||||
roles[JunkPacketCountRole] = "junkPacketCount";
|
roles[ClientMtuRole] = "clientMtu";
|
||||||
roles[JunkPacketMinSizeRole] = "junkPacketMinSize";
|
roles[ClientJunkPacketCountRole] = "clientJunkPacketCount";
|
||||||
roles[JunkPacketMaxSizeRole] = "junkPacketMaxSize";
|
roles[ClientJunkPacketMinSizeRole] = "clientJunkPacketMinSize";
|
||||||
roles[InitPacketJunkSizeRole] = "initPacketJunkSize";
|
roles[ClientJunkPacketMaxSizeRole] = "clientJunkPacketMaxSize";
|
||||||
roles[ResponsePacketJunkSizeRole] = "responsePacketJunkSize";
|
|
||||||
roles[InitPacketMagicHeaderRole] = "initPacketMagicHeader";
|
roles[ServerJunkPacketCountRole] = "serverJunkPacketCount";
|
||||||
roles[ResponsePacketMagicHeaderRole] = "responsePacketMagicHeader";
|
roles[ServerJunkPacketMinSizeRole] = "serverJunkPacketMinSize";
|
||||||
roles[UnderloadPacketMagicHeaderRole] = "underloadPacketMagicHeader";
|
roles[ServerJunkPacketMaxSizeRole] = "serverJunkPacketMaxSize";
|
||||||
roles[TransportPacketMagicHeaderRole] = "transportPacketMagicHeader";
|
roles[ServerInitPacketJunkSizeRole] = "serverInitPacketJunkSize";
|
||||||
|
roles[ServerResponsePacketJunkSizeRole] = "serverResponsePacketJunkSize";
|
||||||
|
roles[ServerInitPacketMagicHeaderRole] = "serverInitPacketMagicHeader";
|
||||||
|
roles[ServerResponsePacketMagicHeaderRole] = "serverResponsePacketMagicHeader";
|
||||||
|
roles[ServerUnderloadPacketMagicHeaderRole] = "serverUnderloadPacketMagicHeader";
|
||||||
|
roles[ServerTransportPacketMagicHeaderRole] = "serverTransportPacketMagicHeader";
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgConfig::AwgConfig(const QJsonObject &jsonConfig)
|
AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig)
|
||||||
{
|
{
|
||||||
port = jsonConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString();
|
||||||
mtu = jsonConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu);
|
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||||
junkPacketCount = jsonConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::awg::defaultMtu);
|
||||||
junkPacketMinSize = jsonConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
clientJunkPacketCount = clientProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||||
junkPacketMaxSize = jsonConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||||
initPacketJunkSize = jsonConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
clientJunkPacketMaxSize = clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||||
responsePacketJunkSize = jsonConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
|
||||||
initPacketMagicHeader = jsonConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||||
responsePacketMagicHeader =
|
serverJunkPacketCount = serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||||
jsonConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
|
serverJunkPacketMinSize = serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||||
underloadPacketMagicHeader =
|
serverJunkPacketMaxSize = serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||||
jsonConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
serverInitPacketJunkSize = serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
||||||
transportPacketMagicHeader =
|
serverResponsePacketJunkSize =
|
||||||
jsonConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
|
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
||||||
|
serverInitPacketMagicHeader =
|
||||||
|
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||||
|
serverResponsePacketMagicHeader =
|
||||||
|
serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
|
||||||
|
serverUnderloadPacketMagicHeader =
|
||||||
|
serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
||||||
|
serverTransportPacketMagicHeader =
|
||||||
|
serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
|
bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
|
||||||
{
|
{
|
||||||
if (port != other.port || junkPacketCount != other.junkPacketCount || junkPacketMinSize != other.junkPacketMinSize
|
if (port != other.port || serverJunkPacketCount != other.serverJunkPacketCount
|
||||||
|| junkPacketMaxSize != other.junkPacketMaxSize || initPacketJunkSize != other.initPacketJunkSize
|
|| serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize
|
||||||
|| responsePacketJunkSize != other.responsePacketJunkSize || initPacketMagicHeader != other.initPacketMagicHeader
|
|| serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize
|
||||||
|| responsePacketMagicHeader != other.responsePacketMagicHeader || underloadPacketMagicHeader != other.underloadPacketMagicHeader
|
|| serverInitPacketMagicHeader != other.serverInitPacketMagicHeader
|
||||||
|| transportPacketMagicHeader != other.transportPacketMagicHeader) {
|
|| serverResponsePacketMagicHeader != other.serverResponsePacketMagicHeader
|
||||||
|
|| serverUnderloadPacketMagicHeader != other.serverUnderloadPacketMagicHeader
|
||||||
|
|| serverTransportPacketMagicHeader != other.serverTransportPacketMagicHeader) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -177,7 +230,8 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
|
|||||||
|
|
||||||
bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const
|
bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const
|
||||||
{
|
{
|
||||||
if (mtu != other.mtu) {
|
if (clientMtu != other.clientMtu || clientJunkPacketCount != other.clientJunkPacketCount
|
||||||
|
|| clientJunkPacketMinSize != other.clientJunkPacketMinSize || clientJunkPacketMaxSize != other.clientJunkPacketMaxSize) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -16,16 +16,21 @@ struct AwgConfig
|
|||||||
AwgConfig(const QJsonObject &jsonConfig);
|
AwgConfig(const QJsonObject &jsonConfig);
|
||||||
|
|
||||||
QString port;
|
QString port;
|
||||||
QString mtu;
|
|
||||||
QString junkPacketCount;
|
QString clientMtu;
|
||||||
QString junkPacketMinSize;
|
QString clientJunkPacketCount;
|
||||||
QString junkPacketMaxSize;
|
QString clientJunkPacketMinSize;
|
||||||
QString initPacketJunkSize;
|
QString clientJunkPacketMaxSize;
|
||||||
QString responsePacketJunkSize;
|
|
||||||
QString initPacketMagicHeader;
|
QString serverJunkPacketCount;
|
||||||
QString responsePacketMagicHeader;
|
QString serverJunkPacketMinSize;
|
||||||
QString underloadPacketMagicHeader;
|
QString serverJunkPacketMaxSize;
|
||||||
QString transportPacketMagicHeader;
|
QString serverInitPacketJunkSize;
|
||||||
|
QString serverResponsePacketJunkSize;
|
||||||
|
QString serverInitPacketMagicHeader;
|
||||||
|
QString serverResponsePacketMagicHeader;
|
||||||
|
QString serverUnderloadPacketMagicHeader;
|
||||||
|
QString serverTransportPacketMagicHeader;
|
||||||
|
|
||||||
bool hasEqualServerSettings(const AwgConfig &other) const;
|
bool hasEqualServerSettings(const AwgConfig &other) const;
|
||||||
bool hasEqualClientSettings(const AwgConfig &other) const;
|
bool hasEqualClientSettings(const AwgConfig &other) const;
|
||||||
@@ -39,16 +44,21 @@ class AwgConfigModel : public QAbstractListModel
|
|||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
PortRole = Qt::UserRole + 1,
|
PortRole = Qt::UserRole + 1,
|
||||||
MtuRole,
|
|
||||||
JunkPacketCountRole,
|
ClientMtuRole,
|
||||||
JunkPacketMinSizeRole,
|
ClientJunkPacketCountRole,
|
||||||
JunkPacketMaxSizeRole,
|
ClientJunkPacketMinSizeRole,
|
||||||
InitPacketJunkSizeRole,
|
ClientJunkPacketMaxSizeRole,
|
||||||
ResponsePacketJunkSizeRole,
|
|
||||||
InitPacketMagicHeaderRole,
|
ServerJunkPacketCountRole,
|
||||||
ResponsePacketMagicHeaderRole,
|
ServerJunkPacketMinSizeRole,
|
||||||
UnderloadPacketMagicHeaderRole,
|
ServerJunkPacketMaxSizeRole,
|
||||||
TransportPacketMagicHeaderRole
|
ServerInitPacketJunkSizeRole,
|
||||||
|
ServerResponsePacketJunkSizeRole,
|
||||||
|
ServerInitPacketMagicHeaderRole,
|
||||||
|
ServerResponsePacketMagicHeaderRole,
|
||||||
|
ServerUnderloadPacketMagicHeaderRole,
|
||||||
|
ServerTransportPacketMagicHeaderRole
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit AwgConfigModel(QObject *parent = nullptr);
|
explicit AwgConfigModel(QObject *parent = nullptr);
|
||||||
@@ -65,12 +75,15 @@ public slots:
|
|||||||
bool isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4);
|
bool isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4);
|
||||||
bool isPacketSizeEqual(const int s1, const int s2);
|
bool isPacketSizeEqual(const int s1, const int s2);
|
||||||
|
|
||||||
|
bool isServerSettingsEqual();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DockerContainer m_container;
|
DockerContainer m_container;
|
||||||
QJsonObject m_protocolConfig;
|
QJsonObject m_serverProtocolConfig;
|
||||||
|
QJsonObject m_clientProtocolConfig;
|
||||||
QJsonObject m_fullConfig;
|
QJsonObject m_fullConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ bool WireGuardConfigModel::setData(const QModelIndex &index, const QVariant &val
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
|
||||||
case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break;
|
case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit dataChanged(index, index, QList { role });
|
emit dataChanged(index, index, QList { role });
|
||||||
@@ -36,8 +36,8 @@ QVariant WireGuardConfigModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
|
case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
|
||||||
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString();
|
case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@@ -49,17 +49,18 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
|
|||||||
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
|
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
|
||||||
|
|
||||||
m_fullConfig = config;
|
m_fullConfig = config;
|
||||||
QJsonObject protocolConfig = config.value(config_key::wireguard).toObject();
|
QJsonObject serverProtocolConfig = config.value(config_key::wireguard).toObject();
|
||||||
|
|
||||||
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard);
|
auto defaultTransportProto =
|
||||||
m_protocolConfig.insert(config_key::transport_proto,
|
ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard);
|
||||||
protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
m_serverProtocolConfig.insert(config_key::transport_proto,
|
||||||
m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config);
|
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
||||||
m_protocolConfig[config_key::port] =
|
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
|
||||||
protocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
||||||
|
|
||||||
m_protocolConfig[config_key::mtu] =
|
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
|
||||||
protocolConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||||
|
m_clientProtocolConfig[config_key::mtu] = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu);
|
||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
@@ -67,36 +68,47 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
|
|||||||
QJsonObject WireGuardConfigModel::getConfig()
|
QJsonObject WireGuardConfigModel::getConfig()
|
||||||
{
|
{
|
||||||
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
|
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
|
||||||
const WgConfig newConfig(m_protocolConfig);
|
const WgConfig newConfig(m_serverProtocolConfig);
|
||||||
|
|
||||||
if (!oldConfig.hasEqualServerSettings(newConfig)) {
|
if (!oldConfig.hasEqualServerSettings(newConfig)) {
|
||||||
m_protocolConfig.remove(config_key::last_config);
|
m_serverProtocolConfig.remove(config_key::last_config);
|
||||||
} else {
|
} else {
|
||||||
auto lastConfig = m_protocolConfig.value(config_key::last_config).toString();
|
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
|
||||||
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||||
jsonConfig[config_key::mtu] = newConfig.mtu;
|
jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu];
|
||||||
|
|
||||||
m_protocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_fullConfig.insert(config_key::wireguard, m_protocolConfig);
|
m_fullConfig.insert(config_key::wireguard, m_serverProtocolConfig);
|
||||||
return m_fullConfig;
|
return m_fullConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WireGuardConfigModel::isServerSettingsEqual()
|
||||||
|
{
|
||||||
|
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
|
||||||
|
const WgConfig newConfig(m_serverProtocolConfig);
|
||||||
|
|
||||||
|
return oldConfig.hasEqualServerSettings(newConfig);
|
||||||
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray> WireGuardConfigModel::roleNames() const
|
QHash<int, QByteArray> WireGuardConfigModel::roleNames() const
|
||||||
{
|
{
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
|
|
||||||
roles[PortRole] = "port";
|
roles[PortRole] = "port";
|
||||||
roles[MtuRole] = "mtu";
|
roles[ClientMtuRole] = "clientMtu";
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
WgConfig::WgConfig(const QJsonObject &jsonConfig)
|
WgConfig::WgConfig(const QJsonObject &serverProtocolConfig)
|
||||||
{
|
{
|
||||||
port = jsonConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString();
|
||||||
mtu = jsonConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||||
|
clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu);
|
||||||
|
|
||||||
|
port = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
|
bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
|
||||||
@@ -109,7 +121,7 @@ bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
|
|||||||
|
|
||||||
bool WgConfig::hasEqualClientSettings(const WgConfig &other) const
|
bool WgConfig::hasEqualClientSettings(const WgConfig &other) const
|
||||||
{
|
{
|
||||||
if (mtu != other.mtu) {
|
if (clientMtu != other.clientMtu) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ struct WgConfig
|
|||||||
WgConfig(const QJsonObject &jsonConfig);
|
WgConfig(const QJsonObject &jsonConfig);
|
||||||
|
|
||||||
QString port;
|
QString port;
|
||||||
QString mtu;
|
QString clientMtu;
|
||||||
|
|
||||||
bool hasEqualServerSettings(const WgConfig &other) const;
|
bool hasEqualServerSettings(const WgConfig &other) const;
|
||||||
bool hasEqualClientSettings(const WgConfig &other) const;
|
bool hasEqualClientSettings(const WgConfig &other) const;
|
||||||
@@ -25,7 +25,7 @@ class WireGuardConfigModel : public QAbstractListModel
|
|||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
PortRole = Qt::UserRole + 1,
|
PortRole = Qt::UserRole + 1,
|
||||||
MtuRole
|
ClientMtuRole
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit WireGuardConfigModel(QObject *parent = nullptr);
|
explicit WireGuardConfigModel(QObject *parent = nullptr);
|
||||||
@@ -39,12 +39,15 @@ public slots:
|
|||||||
void updateModel(const QJsonObject &config);
|
void updateModel(const QJsonObject &config);
|
||||||
QJsonObject getConfig();
|
QJsonObject getConfig();
|
||||||
|
|
||||||
|
bool isServerSettingsEqual();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DockerContainer m_container;
|
DockerContainer m_container;
|
||||||
QJsonObject m_protocolConfig;
|
QJsonObject m_serverProtocolConfig;
|
||||||
|
QJsonObject m_clientProtocolConfig;
|
||||||
QJsonObject m_fullConfig;
|
QJsonObject m_fullConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,11 @@ QHash<int, QByteArray> ProtocolsModel::roleNames() const
|
|||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
|
|
||||||
roles[ProtocolNameRole] = "protocolName";
|
roles[ProtocolNameRole] = "protocolName";
|
||||||
roles[ProtocolPageRole] = "protocolPage";
|
roles[ServerProtocolPageRole] = "serverProtocolPage";
|
||||||
|
roles[ClientProtocolPageRole] = "clientProtocolPage";
|
||||||
roles[ProtocolIndexRole] = "protocolIndex";
|
roles[ProtocolIndexRole] = "protocolIndex";
|
||||||
roles[RawConfigRole] = "rawConfig";
|
roles[RawConfigRole] = "rawConfig";
|
||||||
|
roles[IsClientProtocolExistsRole] = "isClientProtocolExists";
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
@@ -34,8 +36,10 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
|
|||||||
amnezia::Proto proto = ProtocolProps::protoFromString(m_content.keys().at(index.row()));
|
amnezia::Proto proto = ProtocolProps::protoFromString(m_content.keys().at(index.row()));
|
||||||
return ProtocolProps::protocolHumanNames().value(proto);
|
return ProtocolProps::protocolHumanNames().value(proto);
|
||||||
}
|
}
|
||||||
case ProtocolPageRole:
|
case ServerProtocolPageRole:
|
||||||
return static_cast<int>(protocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
|
return static_cast<int>(serverProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
|
||||||
|
case ClientProtocolPageRole:
|
||||||
|
return static_cast<int>(clientProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
|
||||||
case ProtocolIndexRole: return ProtocolProps::protoFromString(m_content.keys().at(index.row()));
|
case ProtocolIndexRole: return ProtocolProps::protoFromString(m_content.keys().at(index.row()));
|
||||||
case RawConfigRole: {
|
case RawConfigRole: {
|
||||||
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
|
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
|
||||||
@@ -50,6 +54,15 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
return rawConfig;
|
return rawConfig;
|
||||||
}
|
}
|
||||||
|
case IsClientProtocolExistsRole: {
|
||||||
|
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
|
||||||
|
auto lastConfigJsonDoc =
|
||||||
|
QJsonDocument::fromJson(protocolConfig.value(config_key::last_config).toString().toUtf8());
|
||||||
|
auto lastConfigJson = lastConfigJsonDoc.object();
|
||||||
|
|
||||||
|
auto configString = lastConfigJson.value(config_key::config).toString();
|
||||||
|
return !configString.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@@ -70,7 +83,7 @@ QJsonObject ProtocolsModel::getConfig()
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const
|
PageLoader::PageEnum ProtocolsModel::serverProtocolPage(Proto protocol) const
|
||||||
{
|
{
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case Proto::OpenVpn: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
case Proto::OpenVpn: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||||
@@ -90,3 +103,12 @@ PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const
|
|||||||
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PageLoader::PageEnum ProtocolsModel::clientProtocolPage(Proto protocol) const
|
||||||
|
{
|
||||||
|
switch (protocol) {
|
||||||
|
case Proto::WireGuard: return PageLoader::PageEnum::PageProtocolWireGuardClientSettings;
|
||||||
|
case Proto::Awg: return PageLoader::PageEnum::PageProtocolAwgClientSettings;
|
||||||
|
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,9 +13,11 @@ class ProtocolsModel : public QAbstractListModel
|
|||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
ProtocolNameRole = Qt::UserRole + 1,
|
ProtocolNameRole = Qt::UserRole + 1,
|
||||||
ProtocolPageRole,
|
ServerProtocolPageRole,
|
||||||
|
ClientProtocolPageRole,
|
||||||
ProtocolIndexRole,
|
ProtocolIndexRole,
|
||||||
RawConfigRole
|
RawConfigRole,
|
||||||
|
IsClientProtocolExistsRole
|
||||||
};
|
};
|
||||||
|
|
||||||
ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||||
@@ -33,7 +35,8 @@ protected:
|
|||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PageLoader::PageEnum protocolPage(Proto protocol) const;
|
PageLoader::PageEnum serverProtocolPage(Proto protocol) const;
|
||||||
|
PageLoader::PageEnum clientProtocolPage(Proto protocol) const;
|
||||||
|
|
||||||
std::shared_ptr<Settings> m_settings;
|
std::shared_ptr<Settings> m_settings;
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
#ifndef PROPERTY_HELPER_H
|
|
||||||
#define PROPERTY_HELPER_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
#define AUTO_PROPERTY(TYPE, NAME) \
|
|
||||||
Q_PROPERTY(TYPE NAME READ NAME WRITE set_ ## NAME NOTIFY NAME ## Changed ) \
|
|
||||||
public: \
|
|
||||||
TYPE NAME() const { return m_ ## NAME ; } \
|
|
||||||
void set_ ## NAME(TYPE value) { \
|
|
||||||
if (m_ ## NAME == value) return; \
|
|
||||||
m_ ## NAME = value; \
|
|
||||||
emit NAME ## Changed(value); \
|
|
||||||
} \
|
|
||||||
Q_SIGNAL void NAME ## Changed(TYPE value);\
|
|
||||||
private: \
|
|
||||||
TYPE m_ ## NAME{};
|
|
||||||
|
|
||||||
#define READONLY_PROPERTY(TYPE, NAME) \
|
|
||||||
Q_PROPERTY(TYPE NAME READ NAME CONSTANT ) \
|
|
||||||
public: \
|
|
||||||
TYPE NAME() const { return m_ ## NAME ; } \
|
|
||||||
private: \
|
|
||||||
void NAME(TYPE value) {m_ ## NAME = value; } \
|
|
||||||
TYPE m_ ## NAME{};
|
|
||||||
|
|
||||||
#endif // PROPERTY_HELPER_H
|
|
||||||
@@ -14,6 +14,7 @@ Button {
|
|||||||
property string defaultButtonColor: AmneziaStyle.color.paleGray
|
property string defaultButtonColor: AmneziaStyle.color.paleGray
|
||||||
property string progressButtonColor: AmneziaStyle.color.paleGray
|
property string progressButtonColor: AmneziaStyle.color.paleGray
|
||||||
property string connectedButtonColor: AmneziaStyle.color.goldenApricot
|
property string connectedButtonColor: AmneziaStyle.color.goldenApricot
|
||||||
|
property bool buttonActiveFocus: activeFocus && (Qt.platform.os !== "android" || SettingsController.isOnTv())
|
||||||
|
|
||||||
implicitWidth: 190
|
implicitWidth: 190
|
||||||
implicitHeight: 190
|
implicitHeight: 190
|
||||||
@@ -50,14 +51,14 @@ Button {
|
|||||||
verticalOffset: 0
|
verticalOffset: 0
|
||||||
radius: 10
|
radius: 10
|
||||||
samples: 25
|
samples: 25
|
||||||
color: root.activeFocus ? AmneziaStyle.color.paleGray : AmneziaStyle.color.goldenApricot
|
color: root.buttonActiveFocus ? AmneziaStyle.color.paleGray : AmneziaStyle.color.goldenApricot
|
||||||
source: backgroundCircle
|
source: backgroundCircle
|
||||||
}
|
}
|
||||||
|
|
||||||
ShapePath {
|
ShapePath {
|
||||||
fillColor: AmneziaStyle.color.transparent
|
fillColor: AmneziaStyle.color.transparent
|
||||||
strokeColor: AmneziaStyle.color.paleGray
|
strokeColor: AmneziaStyle.color.paleGray
|
||||||
strokeWidth: root.activeFocus ? 1 : 0
|
strokeWidth: root.buttonActiveFocus ? 1 : 0
|
||||||
capStyle: ShapePath.RoundCap
|
capStyle: ShapePath.RoundCap
|
||||||
|
|
||||||
PathAngleArc {
|
PathAngleArc {
|
||||||
@@ -81,14 +82,14 @@ Button {
|
|||||||
return defaultButtonColor
|
return defaultButtonColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strokeWidth: root.activeFocus ? 2 : 3
|
strokeWidth: root.buttonActiveFocus ? 2 : 3
|
||||||
capStyle: ShapePath.RoundCap
|
capStyle: ShapePath.RoundCap
|
||||||
|
|
||||||
PathAngleArc {
|
PathAngleArc {
|
||||||
centerX: backgroundCircle.width / 2
|
centerX: backgroundCircle.width / 2
|
||||||
centerY: backgroundCircle.height / 2
|
centerY: backgroundCircle.height / 2
|
||||||
radiusX: 93 - (root.activeFocus ? 2 : 0)
|
radiusX: 93 - (root.buttonActiveFocus ? 2 : 0)
|
||||||
radiusY: 93 - (root.activeFocus ? 2 : 0)
|
radiusY: 93 - (root.buttonActiveFocus ? 2 : 0)
|
||||||
startAngle: 0
|
startAngle: 0
|
||||||
sweepAngle: 360
|
sweepAngle: 360
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ Button {
|
|||||||
visible: text !== ""
|
visible: text !== ""
|
||||||
|
|
||||||
color: AmneziaStyle.color.mutedGray
|
color: AmneziaStyle.color.mutedGray
|
||||||
|
textFormat: Text.RichText
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ Item {
|
|||||||
property string buttonImageSource
|
property string buttonImageSource
|
||||||
property string rightImageSource
|
property string rightImageSource
|
||||||
property string leftImageSource
|
property string leftImageSource
|
||||||
property bool isLeftImageHoverEnabled: true //todo separete this qml file to 3
|
property bool isLeftImageHoverEnabled: true
|
||||||
|
property bool isSmallLeftImage: false
|
||||||
|
|
||||||
property alias rightButton: rightImage
|
property alias rightButton: rightImage
|
||||||
property alias eyeButton: eyeImage
|
property alias eyeButton: eyeImage
|
||||||
@@ -114,9 +115,9 @@ Item {
|
|||||||
|
|
||||||
visible: leftImageSource ? true : false
|
visible: leftImageSource ? true : false
|
||||||
|
|
||||||
Layout.preferredHeight: rightImageSource || !isLeftImageHoverEnabled ? leftImage.implicitHeight : 56
|
Layout.preferredHeight: (rightImageSource || !isLeftImageHoverEnabled || isSmallLeftImage) ? 40 : 56
|
||||||
Layout.preferredWidth: rightImageSource || !isLeftImageHoverEnabled ? leftImage.implicitWidth : 56
|
Layout.preferredWidth: (rightImageSource || !isLeftImageHoverEnabled || isSmallLeftImage)? 40 : 56
|
||||||
Layout.rightMargin: rightImageSource || !isLeftImageHoverEnabled ? 16 : 0
|
Layout.rightMargin: isSmallLeftImage ? 8 : (rightImageSource || !isLeftImageHoverEnabled) ? 16 : 0
|
||||||
|
|
||||||
radius: 12
|
radius: 12
|
||||||
color: AmneziaStyle.color.transparent
|
color: AmneziaStyle.color.transparent
|
||||||
|
|||||||
@@ -102,8 +102,7 @@ Switch {
|
|||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
id: content
|
id: content
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|
||||||
ListItemTitleType {
|
ListItemTitleType {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user