Compare commits

..

1 Commits

Author SHA1 Message Date
KsZnak bdb7795334 Update amneziavpn_fa_IR.ts
Persian language updated
2024-08-23 22:14:39 +03:00
135 changed files with 3544 additions and 5776 deletions
+8 -13
View File
@@ -16,7 +16,6 @@ jobs:
QT_VERSION: 6.6.2
QIF_VERSION: 4.7
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps:
- name: 'Install Qt'
@@ -83,7 +82,6 @@ jobs:
QIF_VERSION: 4.7
BUILD_ARCH: 64
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps:
- name: 'Get sources'
@@ -146,7 +144,6 @@ jobs:
CC: cc
CXX: c++
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps:
- name: 'Setup xcode'
@@ -181,7 +178,7 @@ jobs:
- name: 'Install go'
uses: actions/setup-go@v5
with:
go-version: '1.22.1'
go-version: '1.20'
cache: false
- name: 'Setup gomobile'
@@ -238,7 +235,6 @@ jobs:
QT_VERSION: 6.4.3
QIF_VERSION: 4.6
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps:
- name: 'Setup xcode'
@@ -301,25 +297,24 @@ jobs:
env:
ANDROID_BUILD_PLATFORM: android-34
QT_VERSION: 6.7.2
QT_VERSION: 6.6.2
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps:
- name: 'Install desktop Qt'
uses: jurplel/install-qt-action@v4
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'desktop'
arch: 'linux_gcc_64'
arch: 'gcc_64'
modules: ${{ env.QT_MODULES }}
dir: ${{ runner.temp }}
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Install android_x86_64 Qt'
uses: jurplel/install-qt-action@v4
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
@@ -330,7 +325,7 @@ jobs:
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Install android_x86 Qt'
uses: jurplel/install-qt-action@v4
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
@@ -341,7 +336,7 @@ jobs:
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Install android_armv7 Qt'
uses: jurplel/install-qt-action@v4
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
@@ -352,7 +347,7 @@ jobs:
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Install android_arm64_v8a Qt'
uses: jurplel/install-qt-action@v4
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
-1
View File
@@ -16,7 +16,6 @@ jobs:
QT_VERSION: 6.4.1
QIF_VERSION: 4.5
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
steps:
- name: 'Install desktop Qt'
+2 -2
View File
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN)
project(${PROJECT} VERSION 4.8.1.8
project(${PROJECT} VERSION 4.7.0.0
DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/"
)
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(APP_ANDROID_VERSION_CODE 63)
set(APP_ANDROID_VERSION_CODE 57)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux")
+4 -4
View File
@@ -10,10 +10,10 @@ Amnezia is an open-source VPN client, with a key feature that enables you to dep
<br>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/download/4.7.0.0/AmneziaVPN_4.7.0.0_x64.exe"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/win.png" width="150" style="max-width: 100%;"></a>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/download/4.7.0.0/AmneziaVPN_4.7.0.0.dmg"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/mac.png" width="150" style="max-width: 100%;"></a>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/download/4.7.0.0/AmneziaVPN_Linux_4.7.0.0.tar.zip"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/lin.png" width="150" style="max-width: 100%;"></a>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/tag/4.7.0.0"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/andr.png" width="150" style="max-width: 100%;"></a>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/download/4.6.0.3/AmneziaVPN_4.6.0.3_x64.exe"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/win.png" width="150" style="max-width: 100%;"></a>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/download/4.6.0.3/AmneziaVPN_4.6.0.3.dmg"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/mac.png" width="150" style="max-width: 100%;"></a>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/download/4.6.0.3/AmneziaVPN_Linux_4.6.0.3.tar.zip"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/lin.png" width="150" style="max-width: 100%;"></a>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/tag/4.6.0.3"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/andr.png" width="150" style="max-width: 100%;"></a>
<br>
+1 -7
View File
@@ -27,9 +27,6 @@ add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
add_definitions(-DPROD_AGW_PUBLIC_KEY="$ENV{PROD_AGW_PUBLIC_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)
set(PACKAGES ${PACKAGES} Multimedia)
endif()
@@ -61,7 +58,6 @@ qt_add_executable(${PROJECT} MANUAL_FINALIZATION)
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_process_interface.rep)
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_tun2socks.rep)
endif()
qt6_add_resources(QRC ${QRC} ${CMAKE_CURRENT_LIST_DIR}/resources.qrc)
@@ -114,7 +110,6 @@ include(${CMAKE_CURRENT_LIST_DIR}/cmake/3rdparty.cmake)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/../ipc
${CMAKE_CURRENT_LIST_DIR}/../common/logger
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
@@ -136,6 +131,7 @@ set(HEADERS ${HEADERS}
${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h
${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.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}/protocols/vpnprotocol.h
${CMAKE_CURRENT_BINARY_DIR}/version.h
@@ -144,7 +140,6 @@ set(HEADERS ${HEADERS}
${CMAKE_CURRENT_LIST_DIR}/core/serialization/serialization.h
${CMAKE_CURRENT_LIST_DIR}/core/serialization/transfer.h
${CMAKE_CURRENT_LIST_DIR}/core/enums/apiEnums.h
${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.h
)
# Mozilla headres
@@ -195,7 +190,6 @@ set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/core/serialization/trojan.cpp
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess.cpp
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess_new.cpp
${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.cpp
)
# Mozilla sources
+1 -1
View File
@@ -164,7 +164,7 @@ void AmneziaApplication::init()
bool enabled = m_settings->isSaveLogs();
#ifndef Q_OS_ANDROID
if (enabled) {
if (!Logger::init(false)) {
if (!Logger::init()) {
qWarning() << "Initialization of debug subsystem failed";
}
}
+5 -8
View File
@@ -3,6 +3,7 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.amnezia.vpn"
android:versionName="-- %%INSERT_VERSION_NAME%% --"
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
android:installLocation="auto">
@@ -45,7 +46,7 @@
android:configChanges="uiMode|screenSize|smallestScreenSize|screenLayout|orientation|density
|fontScale|layoutDirection|locale|keyboard|keyboardHidden|navigation|mcc|mnc"
android:launchMode="singleInstance"
android:windowSoftInputMode="stateUnchanged|adjustResize"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
@@ -67,6 +68,9 @@
android:name="android.app.lib_name"
android:value="-- %%INSERT_APP_LIB_NAME%% --" />
<meta-data
android:name="android.app.extract_android_style"
android:value="minimal" />
</activity>
<activity
@@ -84,13 +88,6 @@
android:exported="false"
android:theme="@style/Translucent" />
<activity android:name=".AuthActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity=""
android:exported="false"
android:theme="@style/Translucent" />
<activity
android:name=".ImportConfigActivity"
android:excludeFromRecents="true"
+67 -7
View File
@@ -1,21 +1,81 @@
package org.amnezia.vpn.protocol.awg
import org.amnezia.vpn.protocol.wireguard.Wireguard
import org.amnezia.vpn.protocol.wireguard.WireguardConfig
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() {
override val ifName: String = "awg0"
override fun parseConfig(config: JSONObject): WireguardConfig {
val configData = config.getJSONObject("awg_config_data")
return WireguardConfig.build {
setUseProtocolExtension(true)
configExtensionParameters(configData)
configWireguard(config, configData)
override fun parseConfig(config: JSONObject): AwgConfig {
val configDataJson = config.getJSONObject("awg_config_data")
val configData = parseConfigData(configDataJson.getString("config"))
return AwgConfig.build {
configWireguard(configData, configDataJson)
configSplitTunneling(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()) }
}
}
}
@@ -0,0 +1,108 @@
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
View File
@@ -3,6 +3,3 @@
// android.bundle.enableUncompressedNativeLibs is deprecated
// disable adding gradle property android.bundle.enableUncompressedNativeLibs by androiddeployqt
useLegacyPackaging
// package name for androiddeployqt
namespace = "org.amnezia.vpn"
-2
View File
@@ -115,11 +115,9 @@ dependencies {
implementation(project(":xray"))
implementation(libs.androidx.core)
implementation(libs.androidx.activity)
implementation(libs.androidx.fragment)
implementation(libs.kotlinx.coroutines)
implementation(libs.kotlinx.serialization.protobuf)
implementation(libs.bundles.androidx.camera)
implementation(libs.google.mlkit)
implementation(libs.androidx.datastore)
implementation(libs.androidx.biometric)
}
+30 -6
View File
@@ -3,15 +3,39 @@ package org.amnezia.vpn.protocol.cloak
import android.util.Base64
import net.openvpn.ovpn3.ClientAPI_Config
import org.amnezia.vpn.protocol.openvpn.OpenVpn
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
import org.json.JSONObject
class Cloak : OpenVpn() {
/**
* 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="
* }
* }
*/
override fun internalInit() {
super.internalInit()
if (!isInitialized) loadSharedLibrary(context, "ck-ovpn-plugin")
}
class Cloak : OpenVpn() {
override fun parseConfig(config: JSONObject): ClientAPI_Config {
val openVpnConfig = ClientAPI_Config()
+9 -13
View File
@@ -1,28 +1,24 @@
[versions]
agp = "8.5.2"
kotlin = "1.9.24"
androidx-core = "1.13.1"
androidx-activity = "1.9.1"
androidx-annotation = "1.8.2"
androidx-biometric = "1.2.0-alpha05"
androidx-camera = "1.3.4"
androidx-fragment = "1.8.2"
agp = "8.2.0"
kotlin = "1.9.20"
androidx-core = "1.12.0"
androidx-activity = "1.8.1"
androidx-annotation = "1.7.0"
androidx-camera = "1.3.0"
androidx-security-crypto = "1.1.0-alpha06"
androidx-datastore = "1.1.1"
kotlinx-coroutines = "1.8.1"
androidx-datastore = "1.1.0-beta01"
kotlinx-coroutines = "1.7.3"
kotlinx-serialization = "1.6.3"
google-mlkit = "17.3.0"
google-mlkit = "17.2.0"
[libraries]
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" }
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-camera2 = { module = "androidx.camera:camera-camera2", 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-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-datastore = { module = "androidx.datastore:datastore-preferences", version.ref = "androidx-datastore" }
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
Binary file not shown.
+3 -1
View File
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+2 -5
View File
@@ -15,8 +15,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@@ -57,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -86,8 +84,7 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
+10 -12
View File
@@ -13,8 +13,6 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@@ -45,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
@@ -59,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
@@ -11,12 +11,28 @@ import org.amnezia.vpn.protocol.Protocol
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
import org.amnezia.vpn.protocol.Statistics
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.getLocalNetworks
import org.amnezia.vpn.util.net.parseInetAddress
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() {
private var openVpnClient: OpenVpnClient? = null
@@ -35,17 +51,14 @@ open class OpenVpn : Protocol() {
}
override fun internalInit() {
if (!isInitialized) {
loadSharedLibrary(context, "ovpn3")
loadSharedLibrary(context, "ovpnutil")
}
if (!isInitialized) loadSharedLibrary(context, "ovpn3")
if (this::scope.isInitialized) {
scope.cancel()
}
scope = CoroutineScope(Dispatchers.IO)
}
override suspend fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
override fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
val configBuilder = OpenVpnConfig.Builder()
openVpnClient = OpenVpnClient(
@@ -2,6 +2,7 @@ package org.amnezia.vpn.protocol
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 VpnStartException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
@@ -42,7 +42,7 @@ abstract class Protocol {
protected abstract fun internalInit()
abstract suspend fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean)
abstract fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean)
abstract fun stopVpn()
@@ -158,6 +158,60 @@ abstract class Protocol {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
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)
+1 -1
View File
@@ -21,5 +21,5 @@ android {
}
dependencies {
api(fileTree(mapOf("dir" to "../libs", "include" to listOf("*.jar"))))
implementation(fileTree(mapOf("dir" to "../libs", "include" to listOf("*.jar"))))
}
+1
View File
@@ -3,6 +3,7 @@
<!-- DO NOT EDIT THIS: This file is populated automatically by the deployment tool. -->
<array name="bundled_libs">
<!-- %%INSERT_EXTRA_LIBS%% -->
</array>
<array name="qt_libs">
-3
View File
@@ -1,9 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF0E0E11</color>
<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:windowNoTitle">true</item>
</style>
+1 -1
View File
@@ -22,7 +22,7 @@ dependencyResolutionManagement {
includeBuild("./gradle/plugins")
plugins {
id("com.android.settings") version "8.5.2"
id("com.android.settings") version "8.2.0"
id("settings-property-delegate")
}
@@ -43,7 +43,6 @@ import kotlinx.coroutines.withContext
import org.amnezia.vpn.protocol.getStatistics
import org.amnezia.vpn.protocol.getStatus
import org.amnezia.vpn.qt.QtAndroidController
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
import org.amnezia.vpn.util.Log
import org.amnezia.vpn.util.Prefs
import org.json.JSONException
@@ -159,11 +158,6 @@ class AmneziaActivity : QtActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
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)
val proto = mainScope.async(Dispatchers.IO) {
VpnStateStore.getVpnState().vpnProto
@@ -181,17 +175,6 @@ class AmneziaActivity : QtActivity() {
runBlocking { vpnProto = proto.await() }
}
private fun loadLibs() {
listOf(
"rsapss",
"crypto_3",
"ssl_3",
"ssh"
).forEach {
loadSharedLibrary(this.applicationContext, it)
}
}
private fun registerBroadcastReceivers() {
notificationStateReceiver = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
registerBroadcastReceiver(
@@ -627,14 +610,6 @@ 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")
fun minimizeApp() {
Log.v(TAG, "Minimize application")
@@ -709,17 +684,6 @@ class AmneziaActivity : QtActivity() {
.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
*/
@@ -31,7 +31,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.cancel
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.drop
@@ -40,6 +39,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
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.CONNECTING
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
@@ -49,7 +49,6 @@ import org.amnezia.vpn.protocol.ProtocolState.UNKNOWN
import org.amnezia.vpn.protocol.VpnException
import org.amnezia.vpn.protocol.VpnStartException
import org.amnezia.vpn.protocol.putStatus
import org.amnezia.vpn.util.LoadLibraryException
import org.amnezia.vpn.util.Log
import org.amnezia.vpn.util.Prefs
import org.amnezia.vpn.util.net.NetworkState
@@ -112,10 +111,6 @@ open class AmneziaVpnService : VpnService() {
get() = clientMessengers.any { it.value.name == ACTIVITY_MESSENGER_NAME }
private val connectionExceptionHandler = CoroutineExceptionHandler { _, e ->
connectionJob?.cancel()
connectionJob = null
disconnectionJob?.cancel()
disconnectionJob = null
protocolState.value = DISCONNECTED
when (e) {
is IllegalArgumentException,
@@ -536,7 +531,7 @@ open class AmneziaVpnService : VpnService() {
protocolState.value = DISCONNECTING
disconnectionJob = connectionScope.launch {
connectionJob?.cancelAndJoin()
connectionJob?.join()
connectionJob = null
vpnProto?.protocol?.stopVpn()
@@ -1,97 +0,0 @@
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)
}
}
@@ -0,0 +1,24 @@
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)
}
override fun onNewIntent(intent: Intent) {
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
Log.d(TAG, "onNewIntent: $intent")
intent.let(::readConfig)
intent?.let(::readConfig)
}
private fun readConfig(intent: Intent) {
@@ -25,7 +25,5 @@ object QtAndroidController {
external fun onConfigImported(data: String)
external fun onAuthResult(result: Boolean)
external fun decodeQrCode(data: String): Boolean
}
@@ -1,9 +0,0 @@
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 }
@@ -1,66 +0,0 @@
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) {
connectivityManager.registerBestMatchingNetworkCallback(networkRequest, networkCallback, handler)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val numberAttempts = 300
val numberAttempts = 3
var attemptCount = 0
while(true) {
try {
@@ -35,7 +35,7 @@ fun getLocalNetworks(context: Context, ipv6: Boolean): List<InetNetwork> {
return emptyList()
}
fun parseInetAddress(address: String): InetAddress = InetAddress.getByName(address)
fun parseInetAddress(address: String): InetAddress = parseNumericAddressCompat(address)
private val parseNumericAddressCompat: (String) -> InetAddress =
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
.replace("((?:(?:^|:)0+\\b){2,}):?(?!\\S*\\b\\1:0+\\b)(\\S*)".toRegex(), "::$2")
val InetAddress.ip: String
internal val InetAddress.ip: String
get() = if (this is Inet4Address) {
hostAddress!!
} else {
@@ -1,26 +1,54 @@
package org.amnezia.vpn.protocol.wireguard
import android.net.VpnService.Builder
import java.io.IOException
import java.util.Locale
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import java.util.TreeMap
import org.amnezia.awg.GoBackend
import org.amnezia.vpn.protocol.Protocol
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
import org.amnezia.vpn.protocol.Statistics
import org.amnezia.vpn.protocol.VpnStartException
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
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.InetNetwork
import org.amnezia.vpn.util.net.parseInetAddress
import org.amnezia.vpn.util.optStringOrNull
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"
open class Wireguard : Protocol() {
@@ -51,105 +79,67 @@ open class Wireguard : Protocol() {
if (!isInitialized) loadSharedLibrary(context, "wg-go")
}
override suspend fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
override fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
val wireguardConfig = parseConfig(config)
val startTime = System.currentTimeMillis()
start(wireguardConfig, vpnBuilder, protect)
waitForConnection(startTime)
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 {
val configData = config.getJSONObject("wireguard_config_data")
val configDataJson = config.getJSONObject("wireguard_config_data")
val configData = parseConfigData(configDataJson.getString("config"))
return WireguardConfig.build {
configWireguard(config, configData)
configWireguard(configData, configDataJson)
configSplitTunneling(config)
configAppSplitTunneling(config)
}
}
protected fun WireguardConfig.Builder.configWireguard(config: JSONObject, configData: JSONObject) {
configData.getString("client_ip").split(",").map { address ->
protected fun WireguardConfig.Builder.configWireguard(configData: Map<String, String>, configDataJson: JSONObject) {
configData["Address"]?.split(",")?.map { address ->
InetNetwork.parse(address.trim())
}.forEach(::addAddress)
}?.forEach(::addAddress)
config.optStringOrNull("dns1")?.let { dns ->
addDnsServer(parseInetAddress(dns.trim()))
}
config.optStringOrNull("dns2")?.let { dns ->
addDnsServer(parseInetAddress(dns.trim()))
}
configData["DNS"]?.split(",")?.map { dns ->
parseInetAddress(dns.trim())
}?.forEach(::addDnsServer)
val defRoutes = hashSetOf(
InetNetwork("0.0.0.0", 0),
InetNetwork("::", 0)
)
val routes = hashSetOf<InetNetwork>()
configData.getJSONArray("allowed_ips").asSequence<String>().map { route ->
configData["AllowedIPs"]?.split(",")?.map { route ->
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 (routes.any { it !in defRoutes }) disableSplitTunneling()
addRoutes(routes)
configData.optStringOrNull("mtu")?.let { setMtu(it.toInt()) }
val host = configData.getString("hostName").let { parseInetAddress(it.trim()) }
val port = configData.getInt("port")
setEndpoint(InetEndpoint(host, port))
if (configData.optBoolean("isObfuscationEnabled")) {
setUseProtocolExtension(true)
configExtensionParameters(configData)
configDataJson.optString("mtu").let { mtu ->
if (mtu.isNotEmpty()) {
setMtu(mtu.toInt())
} else {
configData["MTU"]?.let { setMtu(it.toInt()) }
}
}
configData.optStringOrNull("persistent_keep_alive")?.let { setPersistentKeepalive(it.toInt()) }
configData.getString("client_priv_key").let { setPrivateKeyHex(it.base64ToHex()) }
configData.getString("server_pub_key").let { setPublicKeyHex(it.base64ToHex()) }
configData.optStringOrNull("psk_key")?.let { setPreSharedKeyHex(it.base64ToHex()) }
configData["Endpoint"]?.let { setEndpoint(InetEndpoint.parse(it)) }
configData["PersistentKeepalive"]?.let { setPersistentKeepalive(it.toInt()) }
configData["PrivateKey"]?.let { setPrivateKeyHex(it.base64ToHex()) }
configData["PublicKey"]?.let { setPublicKeyHex(it.base64ToHex()) }
configData["PresharedKey"]?.let { setPreSharedKeyHex(it.base64ToHex()) }
}
protected fun WireguardConfig.Builder.configExtensionParameters(configData: JSONObject) {
configData.optStringOrNull("Jc")?.let { setJc(it.toInt()) }
configData.optStringOrNull("Jmin")?.let { setJmin(it.toInt()) }
configData.optStringOrNull("Jmax")?.let { setJmax(it.toInt()) }
configData.optStringOrNull("S1")?.let { setS1(it.toInt()) }
configData.optStringOrNull("S2")?.let { setS2(it.toInt()) }
configData.optStringOrNull("H1")?.let { setH1(it.toLong()) }
configData.optStringOrNull("H2")?.let { setH2(it.toLong()) }
configData.optStringOrNull("H3")?.let { setH3(it.toLong()) }
configData.optStringOrNull("H4")?.let { setH4(it.toLong()) }
protected fun parseConfigData(data: String): Map<String, String> {
val parsedData = TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER)
data.lineSequence()
.filter { it.isNotEmpty() && !it.startsWith('[') }
.forEach { line ->
val attr = line.split("=", limit = 2)
parsedData[attr.first().trim()] = attr.last().trim()
}
return parsedData
}
private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) {
@@ -1,7 +1,6 @@
package org.amnezia.vpn.protocol.wireguard
import android.util.Base64
import org.amnezia.vpn.protocol.BadConfigException
import org.amnezia.vpn.protocol.ProtocolConfig
import org.amnezia.vpn.util.net.InetEndpoint
@@ -13,17 +12,7 @@ open class WireguardConfig protected constructor(
val persistentKeepalive: Int,
val publicKeyHex: String,
val preSharedKeyHex: 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?
val privateKeyHex: String
) : ProtocolConfig(protocolConfigBuilder) {
protected constructor(builder: Builder) : this(
@@ -32,17 +21,7 @@ open class WireguardConfig protected constructor(
builder.persistentKeepalive,
builder.publicKeyHex,
builder.preSharedKeyHex,
builder.privateKeyHex,
builder.useProtocolExtension,
builder.jc,
builder.jmin,
builder.jmax,
builder.s1,
builder.s2,
builder.h1,
builder.h2,
builder.h3,
builder.h4
builder.privateKeyHex
)
fun toWgUserspaceString(): String = with(StringBuilder()) {
@@ -54,30 +33,6 @@ open class WireguardConfig protected constructor(
open fun appendDeviceLine(sb: StringBuilder) = with(sb) {
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) {
@@ -110,18 +65,6 @@ open class WireguardConfig protected constructor(
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 setPersistentKeepalive(persistentKeepalive: Int) = apply { this.persistentKeepalive = persistentKeepalive }
@@ -132,18 +75,6 @@ open class WireguardConfig protected constructor(
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) }
}
+65 -11
View File
@@ -17,10 +17,72 @@ import org.amnezia.vpn.protocol.xray.libXray.Logger
import org.amnezia.vpn.protocol.xray.libXray.Tun2SocksConfig
import org.amnezia.vpn.util.Log
import org.amnezia.vpn.util.net.InetNetwork
import org.amnezia.vpn.util.net.ip
import org.amnezia.vpn.util.net.parseInetAddress
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 LIBXRAY_TAG = "libXray"
@@ -47,7 +109,7 @@ class Xray : Protocol() {
}
}
override suspend fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
override fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
if (isRunning) {
Log.w(TAG, "XRay already running")
return
@@ -62,15 +124,7 @@ class Xray : Protocol() {
.put("loglevel", "warning")
.put("access", "none") // disable access log
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)
start(xrayConfig, xrayJsonConfig.toString(), vpnBuilder, protect)
state.value = CONNECTED
isRunning = true
}
+2
View File
@@ -27,6 +27,7 @@ link_directories(${CMAKE_CURRENT_SOURCE_DIR}/platforms/android)
set(HEADERS ${HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_controller.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}/core/installedAppsImageProvider.h
)
@@ -34,6 +35,7 @@ set(HEADERS ${HEADERS}
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_controller.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}/core/installedAppsImageProvider.cpp
)
@@ -95,18 +95,6 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
stdOut.replace("/32", "");
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
if (ips.isEmpty()) {
nextIpNumber = "2";
@@ -199,10 +187,6 @@ QString WireguardConfigurator::createConfig(const ServerCredentials &credentials
jConfig[config_key::server_pub_key] = connData.serverPubKey;
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;
return QJsonDocument(jConfig).toJson();
+10 -13
View File
@@ -9,8 +9,8 @@
#include "QRsa.h"
#include "amnezia_application.h"
#include "configurators/wireguard_configurator.h"
#include "core/enums/apiEnums.h"
#include "configurators/wireguard_configurator.h"
#include "version.h"
namespace
@@ -42,7 +42,7 @@ namespace
constexpr char keyPayload[] = "key_payload";
}
const QStringList proxyStorageUrl = { "" };
const QStringList proxyStorageUrl = {""};
ErrorCode checkErrors(const QList<QSslError> &sslErrors, QNetworkReply *reply)
{
@@ -65,8 +65,7 @@ namespace
}
}
ApiController::ApiController(const QString &gatewayEndpoint, bool isDevEnvironment, QObject *parent)
: QObject(parent), m_gatewayEndpoint(gatewayEndpoint), m_isDevEnvironment(isDevEnvironment)
ApiController::ApiController(const QString &gatewayEndpoint, QObject *parent) : QObject(parent), m_gatewayEndpoint(gatewayEndpoint)
{
}
@@ -144,7 +143,7 @@ QStringList ApiController::getProxyUrls()
QEventLoop wait;
QList<QSslError> sslErrors;
QNetworkReply *reply;
QNetworkReply* reply;
for (const auto &proxyStorageUrl : proxyStorageUrl) {
request.setUrl(proxyStorageUrl);
@@ -282,7 +281,7 @@ ErrorCode ApiController::getServicesList(QByteArray &responseBody)
request.setUrl(QString("%1v1/services").arg(m_gatewayEndpoint));
QNetworkReply *reply;
QNetworkReply* reply;
reply = amnApp->manager()->get(request);
QEventLoop wait;
@@ -301,8 +300,7 @@ ErrorCode ApiController::getServicesList(QByteArray &responseBody)
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
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;
}
reply->deleteLater();
@@ -357,9 +355,9 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co
EVP_PKEY *publicKey = nullptr;
try {
QByteArray rsaKey = m_isDevEnvironment ? DEV_AGW_PUBLIC_KEY : PROD_AGW_PUBLIC_KEY;
QByteArray key = PROD_AGW_PUBLIC_KEY;
QSimpleCrypto::QRsa rsa;
publicKey = rsa.getPublicKeyFromByteArray(rsaKey);
publicKey = rsa.getPublicKeyFromByteArray(key);
} catch (...) {
qCritical() << "error loading public key from environment variables";
return ErrorCode::ApiMissingAgwPublicKey;
@@ -377,7 +375,7 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co
requestBody[configKey::keyPayload] = QString(encryptedKeyPayload.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;
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
@@ -397,8 +395,7 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
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;
}
reply->deleteLater();
+1 -2
View File
@@ -14,7 +14,7 @@ class ApiController : public QObject
Q_OBJECT
public:
explicit ApiController(const QString &gatewayEndpoint, bool isDevEnvironment, QObject *parent = nullptr);
explicit ApiController(const QString &gatewayEndpoint, QObject *parent = nullptr);
public slots:
void updateServerConfigFromApi(const QString &installationUuid, const int serverIndex, QJsonObject serverConfig);
@@ -44,7 +44,6 @@ private:
QString m_gatewayEndpoint;
QStringList m_proxyUrls;
bool m_isDevEnvironment = false;
};
#endif // APICONTROLLER_H
+12 -15
View File
@@ -83,6 +83,7 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
}
qDebug().noquote() << lineToExec;
Logger::appendSshLog("Run command:" + lineToExec);
error = m_sshClient.executeCommand(lineToExec, cbReadStdOut, cbReadStdErr);
if (error != ErrorCode::NoError) {
@@ -99,13 +100,13 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
{
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);
if (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);
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
@@ -425,7 +426,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
if (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)
return errorCode;
@@ -436,10 +437,9 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
return ErrorCode::NoError;
};
errorCode =
runScript(credentials,
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
cbReadStdOut);
errorCode = runScript(credentials,
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
cbReadStdOut);
if (errorCode)
return errorCode;
@@ -621,15 +621,13 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
// Socks5 proxy vars
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();
QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : "";
vars.append({ { "$SOCKS5_USER", socks5user } });
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
vars.append({ { "$SOCKS5_USER", socks5user } });
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
QString serverIp = (container != DockerContainer::Awg && container != DockerContainer::WireGuard && container != DockerContainer::Xray)
? NetworkUtilities::getIPAddress(credentials.hostName)
: credentials.hostName;
QString serverIp = NetworkUtilities::getIPAddress(credentials.hostName);
if (!serverIp.isEmpty()) {
vars.append({ { "$SERVER_IP_ADDRESS", serverIp } });
} else {
@@ -715,8 +713,7 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential
udpProtoScript.append("' | grep -i udp");
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) {
return errorCode;
}
@@ -100,13 +100,7 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair<QStr
protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString);
QJsonObject 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;
}
}
vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData);
}
+2 -14
View File
@@ -29,12 +29,6 @@ QSharedPointer<IpcInterfaceReplica> IpcClient::Interface()
return Instance()->m_ipcClient;
}
QSharedPointer<IpcProcessTun2SocksReplica> IpcClient::InterfaceTun2Socks()
{
if (!Instance()) return nullptr;
return Instance()->m_Tun2SocksClient;
}
bool IpcClient::init(IpcClient *instance)
{
m_instance = instance;
@@ -50,12 +44,6 @@ bool IpcClient::init(IpcClient *instance)
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](){
@@ -63,16 +51,16 @@ bool IpcClient::init(IpcClient *instance)
});
Instance()->m_localSocket->connectToServer(amnezia::getIpcServiceUrl());
Instance()->m_localSocket->waitForConnected();
if (!Instance()->m_ipcClient) {
qDebug() << "IpcClient::init failed";
return false;
}
qDebug() << "IpcClient::init succeed";
return (Instance()->m_ipcClient->isReplicaValid() && Instance()->m_Tun2SocksClient->isReplicaValid());
return Instance()->m_ipcClient->isReplicaValid();
}
QSharedPointer<PrivilegedProcess> IpcClient::CreatePrivilegedProcess()
-5
View File
@@ -6,7 +6,6 @@
#include "ipc.h"
#include "rep_ipc_interface_replica.h"
#include "rep_ipc_process_tun2socks_replica.h"
#include "privileged_process.h"
@@ -19,7 +18,6 @@ public:
static IpcClient *Instance();
static bool init(IpcClient *instance);
static QSharedPointer<IpcInterfaceReplica> Interface();
static QSharedPointer<IpcProcessTun2SocksReplica> InterfaceTun2Socks();
static QSharedPointer<PrivilegedProcess> CreatePrivilegedProcess();
bool isSocketConnected() const;
@@ -30,11 +28,8 @@ private:
~IpcClient() override;
QRemoteObjectNode m_ClientNode;
QRemoteObjectNode m_Tun2SocksNode;
QSharedPointer<IpcInterfaceReplica> m_ipcClient;
QPointer<QLocalSocket> m_localSocket;
QPointer<QLocalSocket> m_tun2socksSocket;
QSharedPointer<IpcProcessTun2SocksReplica> m_Tun2SocksClient;
struct ProcessDescriptor {
ProcessDescriptor () {
+1 -4
View File
@@ -109,10 +109,7 @@ QStringList NetworkUtilities::summarizeRoutes(const QStringList &ips, const QStr
QString NetworkUtilities::getIPAddress(const QString &host)
{
QHostAddress address(host);
if (QAbstractSocket::IPv4Protocol == address.protocol()) {
return host;
} else if (QAbstractSocket::IPv6Protocol == address.protocol()) {
if (ipAddressRegExp().match(host).hasMatch()) {
return host;
}
+81 -107
View File
@@ -4,18 +4,18 @@
#include <QDebug>
#include <QDesktopServices>
#include <QDir>
#include <QJsonDocument>
#include <QMetaEnum>
#include <QJsonDocument>
#include <QStandardPaths>
#include <QUrl>
#include <iostream>
#include "utilities.h"
#include "version.h"
#include "utilities.h"
#ifdef AMNEZIA_DESKTOP
#include <core/ipcclient.h>
#include <core/ipcclient.h>
#endif
#ifdef Q_OS_IOS
@@ -25,9 +25,8 @@
QFile Logger::m_file;
QTextStream Logger::m_textStream;
QString Logger::m_logFileName = QString("%1.log").arg(APPLICATION_NAME);
QString Logger::m_serviceLogFileName = QString("%1.log").arg(SERVICE_NAME);
void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
if (msg.simplified().isEmpty()) {
return;
@@ -38,12 +37,12 @@ void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, cons
return;
}
if (msg.startsWith("Unknown property") || msg.startsWith("Could not create pixmap") || msg.startsWith("Populating font")
|| msg.startsWith("stale focus object")) {
if (msg.startsWith("Unknown property") || msg.startsWith("Could not create pixmap") || msg.startsWith("Populating font") || msg.startsWith("stale focus object")) {
return;
}
Logger::m_textStream << qFormatLogMessage(type, context, msg) << Qt::endl << Qt::flush;
Logger::appendAllLog(qFormatLogMessage(type, context, msg));
std::cout << qFormatLogMessage(type, context, msg).toStdString() << std::endl << std::flush;
}
@@ -54,24 +53,36 @@ Logger &Logger::Instance()
return s;
}
bool Logger::init(bool isServiceLogger)
void Logger::appendSshLog(const QString &log)
{
QString path = isServiceLogger ? systemLogDir() : userLogsDir();
QString logFileName = isServiceLogger ? m_serviceLogFileName : m_logFileName ;
QString dt = QDateTime::currentDateTime().toString();
Instance().m_sshLog.append(dt + ": " + log + "\n");
emit Instance().sshLogChanged(Instance().sshLog());
}
void Logger::appendAllLog(const QString &log)
{
Instance().m_allLog.append(log + "\n");
emit Instance().allLogChanged(Instance().allLog());
}
bool Logger::init()
{
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}");
QString path = userLogsDir();
QDir appDir(path);
if (!appDir.mkpath(path)) {
return false;
}
m_file.setFileName(appDir.filePath(logFileName));
m_file.setFileName(appDir.filePath(m_logFileName));
if (!m_file.open(QIODevice::Append)) {
qWarning() << "Cannot open log file:" << logFileName;
qWarning() << "Cannot open log file:" << m_logFileName;
return false;
}
m_file.setTextModeEnabled(true);
m_textStream.setDevice(&m_file);
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}");
#if !defined(QT_DEBUG) || defined(Q_OS_IOS)
qInstallMessageHandler(debugMessageHandler);
@@ -88,8 +99,7 @@ void Logger::deInit()
m_file.close();
}
bool Logger::setServiceLogsEnabled(bool enabled)
{
bool Logger::setServiceLogsEnabled(bool enabled) {
#ifdef AMNEZIA_DESKTOP
IpcClient *m_IpcClient = new IpcClient;
@@ -102,7 +112,8 @@ bool Logger::setServiceLogsEnabled(bool enabled)
if (m_IpcClient->Interface()) {
m_IpcClient->Interface()->setLogsEnabled(enabled);
} else {
}
else {
qWarning() << "Error occurred setting up service logs";
return false;
}
@@ -116,32 +127,11 @@ QString Logger::userLogsDir()
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/log";
}
QString Logger::systemLogDir()
{
#ifdef Q_OS_WIN
QStringList locationList = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
QString primaryLocation = "ProgramData";
foreach (const QString &location, locationList) {
if (location.contains(primaryLocation)) {
return QString("%1/%2/log").arg(location).arg(APPLICATION_NAME);
}
}
return QString();
#else
return QString("/var/log/%1").arg(APPLICATION_NAME);
#endif
}
QString Logger::userLogsFilePath()
{
return userLogsDir() + QDir::separator() + m_logFileName;
}
QString Logger::serviceLogsFilePath()
{
return systemLogDir() + QDir::separator() + m_serviceLogFileName;
}
QString Logger::getLogFile()
{
m_file.flush();
@@ -149,32 +139,18 @@ QString Logger::getLogFile()
file.open(QIODevice::ReadOnly);
QString qtLog = file.readAll();
#ifdef Q_OS_IOS
return QString().fromStdString(AmneziaVPN::swiftUpdateLogData(qtLog.toStdString()));
#else
return qtLog;
#endif
}
QString Logger::getServiceLogFile()
bool Logger::openLogsFolder()
{
m_file.flush();
QFile file(serviceLogsFilePath());
file.open(QIODevice::ReadOnly);
QString qtLog = file.readAll();
#ifdef Q_OS_IOS
return QString().fromStdString(AmneziaVPN::swiftUpdateLogData(qtLog.toStdString()));
#else
return qtLog;
#endif
}
bool Logger::openLogsFolder(bool isServiceLogger)
{
QString path = isServiceLogger ? systemLogDir() : userLogsDir();
QString path = userLogsDir();
#ifdef Q_OS_WIN
path = "file:///" + path;
#endif
@@ -185,23 +161,38 @@ bool Logger::openLogsFolder(bool isServiceLogger)
return true;
}
void Logger::clearLogs(bool isServiceLogger)
bool Logger::openServiceLogsFolder()
{
QString path = Utils::systemLogPath();
#ifdef Q_OS_WIN
path = "file:///" + path;
#endif
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
return true;
}
QString Logger::appLogFileNamePath()
{
return m_file.fileName();
}
void Logger::clearLogs()
{
bool isLogActive = m_file.isOpen();
m_file.close();
QFile file(isServiceLogger ? serviceLogsFilePath() : userLogsFilePath());
QFile file(userLogsFilePath());
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
file.resize(0);
file.close();
#ifdef Q_OS_IOS
AmneziaVPN::swiftDeleteLog();
#endif
if (isLogActive) {
init(isServiceLogger);
init();
}
}
@@ -219,7 +210,8 @@ void Logger::clearServiceLogs()
if (m_IpcClient->Interface()) {
m_IpcClient->Interface()->clearLogs();
} else {
}
else {
qWarning() << "Error occurred cleaning up service logs";
}
#endif
@@ -227,41 +219,26 @@ void Logger::clearServiceLogs()
void Logger::cleanUp()
{
clearLogs(false);
clearLogs();
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
dir.removeRecursively();
clearLogs(true);
clearServiceLogs();
}
Logger::Log::Log(Logger *logger, LogLevel logLevel) : m_logger(logger), m_logLevel(logLevel), m_data(new Data())
{
}
Logger::Log::Log(Logger* logger, LogLevel logLevel)
: m_logger(logger), m_logLevel(logLevel), m_data(new Data()) {}
Logger::Log::~Log()
{
Logger::Log::~Log() {
qDebug() << "Amnezia" << m_logger->className() << m_data->m_buffer.trimmed();
delete m_data;
}
Logger::Log Logger::error()
{
return Log(this, LogLevel::Error);
}
Logger::Log Logger::warning()
{
return Log(this, LogLevel::Warning);
}
Logger::Log Logger::info()
{
return Log(this, LogLevel::Info);
}
Logger::Log Logger::debug()
{
return Log(this, LogLevel::Debug);
}
QString Logger::sensitive(const QString &input)
{
Logger::Log Logger::error() { return Log(this, LogLevel::Error); }
Logger::Log Logger::warning() { return Log(this, LogLevel::Warning); }
Logger::Log Logger::info() { return Log(this, LogLevel::Info); }
Logger::Log Logger::debug() { return Log(this, LogLevel::Debug); }
QString Logger::sensitive(const QString& input) {
#ifdef Q_DEBUG
return input;
#else
@@ -270,51 +247,48 @@ QString Logger::sensitive(const QString &input)
#endif
}
#define CREATE_LOG_OP_REF(x) \
Logger::Log &Logger::Log::operator<<(x t) \
{ \
m_data->m_ts << t << ' '; \
return *this; \
}
#define CREATE_LOG_OP_REF(x) \
Logger::Log& Logger::Log::operator<<(x t) { \
m_data->m_ts << t << ' '; \
return *this; \
}
CREATE_LOG_OP_REF(uint64_t);
CREATE_LOG_OP_REF(const char *);
CREATE_LOG_OP_REF(const QString &);
CREATE_LOG_OP_REF(const QByteArray &);
CREATE_LOG_OP_REF(const void *);
CREATE_LOG_OP_REF(const char*);
CREATE_LOG_OP_REF(const QString&);
CREATE_LOG_OP_REF(const QByteArray&);
CREATE_LOG_OP_REF(const void*);
#undef CREATE_LOG_OP_REF
Logger::Log &Logger::Log::operator<<(const QStringList &t)
{
Logger::Log& Logger::Log::operator<<(const QStringList& t) {
m_data->m_ts << '[' << t.join(",") << ']' << ' ';
return *this;
}
Logger::Log &Logger::Log::operator<<(const QJsonObject &t)
{
Logger::Log& Logger::Log::operator<<(const QJsonObject& t) {
m_data->m_ts << QJsonDocument(t).toJson(QJsonDocument::Indented) << ' ';
return *this;
}
Logger::Log &Logger::Log::operator<<(QTextStreamFunction t)
{
Logger::Log& Logger::Log::operator<<(QTextStreamFunction t) {
m_data->m_ts << t;
return *this;
}
void Logger::Log::addMetaEnum(quint64 value, const QMetaObject *meta, const char *name)
{
void Logger::Log::addMetaEnum(quint64 value, const QMetaObject* meta,
const char* name) {
QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
QString out;
QTextStream ts(&out);
if (const char *scope = me.scope()) {
if (const char* scope = me.scope()) {
ts << scope << "::";
}
const char *key = me.valueToKey(static_cast<int>(value));
const char* key = me.valueToKey(static_cast<int>(value));
const bool scoped = me.isScoped();
if (scoped || !key) {
ts << me.enumName() << (!key ? "(" : "::");
+107
View File
@@ -0,0 +1,107 @@
#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
+1 -1
View File
@@ -149,7 +149,7 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
QJsonArray jsAllowedIPAddesses;
QJsonArray plainAllowedIP = wgConfig.value(amnezia::config_key::allowed_ips).toArray();
QJsonArray defaultAllowedIP = { "0.0.0.0/0", "::/0" };
QJsonArray defaultAllowedIP = QJsonArray::fromStringList(QString("0.0.0.0/0, ::/0").split(","));
if (plainAllowedIP != defaultAllowedIP && !plainAllowedIP.isEmpty()) {
// Use AllowedIP list from WG config because of higher priority
@@ -98,7 +98,6 @@ bool AndroidController::initialize()
{"onStatisticsUpdate", "(JJ)V", reinterpret_cast<void *>(onStatisticsUpdate)},
{"onFileOpened", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onFileOpened)},
{"onConfigImported", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onConfigImported)},
{"onAuthResult", "(Z)V", reinterpret_cast<void *>(onAuthResult)},
{"decodeQrCode", "(Ljava/lang/String;)Z", reinterpret_cast<bool *>(decodeQrCode)}
};
@@ -211,11 +210,6 @@ void AndroidController::setScreenshotsEnabled(bool enabled)
callActivityMethod("setScreenshotsEnabled", "(Z)V", enabled);
}
void AndroidController::setNavigationBarColor(unsigned int color)
{
callActivityMethod("setNavigationBarColor", "(I)V", color);
}
void AndroidController::minimizeApp()
{
callActivityMethod("minimizeApp", "()V");
@@ -271,22 +265,6 @@ void AndroidController::requestNotificationPermission()
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
jclass AndroidController::log;
jmethodID AndroidController::logDebug;
@@ -484,14 +462,6 @@ void AndroidController::onConfigImported(JNIEnv *env, jobject thiz, jstring 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
bool AndroidController::decodeQrCode(JNIEnv *env, jobject thiz, jstring data)
{
@@ -41,13 +41,11 @@ public:
void exportLogsFile(const QString &fileName);
void clearLogs();
void setScreenshotsEnabled(bool enabled);
void setNavigationBarColor(unsigned int color);
void minimizeApp();
QJsonArray getAppList();
QPixmap getAppIcon(const QString &package, QSize *size, const QSize &requestedSize);
bool isNotificationPermissionGranted();
void requestNotificationPermission();
bool requestAuthentication();
static bool initLogging();
static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message);
@@ -65,7 +63,6 @@ signals:
void configImported(QString config);
void importConfigFromOutside(QString config);
void initConnectionState(Vpn::ConnectionState state);
void authenticationResult(bool result);
private:
bool isWaitingStatus = true;
@@ -92,7 +89,6 @@ private:
static void onStatisticsUpdate(JNIEnv *env, jobject thiz, jlong rxBytes, jlong txBytes);
static void onConfigImported(JNIEnv *env, jobject thiz, jstring data);
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);
template <typename Ret, typename ...Args>
@@ -0,0 +1,16 @@
#include "authResultReceiver.h"
AuthResultReceiver::AuthResultReceiver(QSharedPointer<AuthResultNotifier> &notifier) : 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();
}
}
@@ -0,0 +1,32 @@
#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> &notifier);
void handleActivityResult(int receiverRequestCode, int resultCode, const QJniObject &data) override;
private:
QSharedPointer<AuthResultNotifier> m_notifier;
};
#endif // AUTHRESULTRECEIVER_H
+4 -15
View File
@@ -351,6 +351,8 @@ void IosController::vpnStatusDidChange(void *pNotification)
}
}
}
} else {
qDebug() << "Disconnect error is absent";
}
}];
} else {
@@ -499,20 +501,6 @@ bool IosController::setupWireGuard()
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);
QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact));
@@ -847,7 +835,7 @@ QString IosController::openFile() {
void IosController::requestInetAccess() {
NSURL *url = [NSURL URLWithString:@"http://captive.apple.com/generate_204"];
if (!url) {
if (url) {
qDebug() << "IosController::requestInetAccess URL error";
return;
}
@@ -859,6 +847,7 @@ void IosController::requestInetAccess() {
} else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
QString responseBody = QString::fromUtf8((const char*)data.bytes, data.length);
qDebug() << "IosController::requestInetAccess server response:" << httpResponse.statusCode << "\n\n" <<responseBody;
}
}];
[task resume];
@@ -12,7 +12,7 @@
#include "Winsvc.h"
/**
* @brief The WindowsServiceManager provides control over the MozillaVPNBroker
* @brief The WindowsServiceManager provides controll over the MozillaVPNBroker
* service via SCM
*/
class WindowsServiceManager : public QObject {
+3 -5
View File
@@ -6,7 +6,6 @@
#include <QTcpSocket>
#include <QNetworkInterface>
#include "core/networkUtilities.h"
#include "logger.h"
#include "openvpnprotocol.h"
#include "utilities.h"
@@ -128,6 +127,7 @@ void OpenVpnProtocol::sendManagementCommand(const QString &command)
uint OpenVpnProtocol::selectMgmtPort()
{
for (int i = 0; i < 100; ++i) {
quint32 port = QRandomGenerator::global()->generate();
port = (double)(65000 - 15001) * port / UINT32_MAX + 15001;
@@ -137,6 +137,7 @@ uint OpenVpnProtocol::selectMgmtPort()
if (ok)
return port;
}
return m_managementPort;
}
@@ -342,8 +343,7 @@ void OpenVpnProtocol::updateVpnGateway(const QString &line)
}
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
m_configData.insert("vpnGateway", m_vpnGateway);
m_configData.insert("vpnServer",
NetworkUtilities::getIPAddress(m_configData.value(amnezia::config_key::hostName).toString()));
m_configData.insert("vpnServer", m_configData.value(amnezia::config_key::hostName).toString());
IpcClient::Interface()->enablePeerTraffic(m_configData);
}
}
@@ -352,8 +352,6 @@ void OpenVpnProtocol::updateVpnGateway(const QString &line)
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
// killSwitch toggle
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
m_configData.insert("vpnServer",
NetworkUtilities::getIPAddress(m_configData.value(amnezia::config_key::hostName).toString()));
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
}
#endif
-1
View File
@@ -65,7 +65,6 @@ namespace amnezia
constexpr char last_config[] = "last_config";
constexpr char isThirdPartyConfig[] = "isThirdPartyConfig";
constexpr char isObfuscationEnabled[] = "isObfuscationEnabled";
constexpr char junkPacketCount[] = "Jc";
constexpr char junkPacketMinSize[] = "Jmin";
+2 -7
View File
@@ -4,8 +4,9 @@
#include <QTcpSocket>
#include <QThread>
#include "logger.h"
#include "utilities.h"
#include "wireguardprotocol.h"
#include "core/networkUtilities.h"
#include "mozilla/localsocketcontroller.h"
@@ -36,12 +37,6 @@ void WireguardProtocol::stop()
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);
return ErrorCode::NoError;
}
+100 -68
View File
@@ -17,7 +17,6 @@ XrayProtocol::XrayProtocol(const QJsonObject &configuration, QObject *parent):
m_routeGateway = NetworkUtilities::getGatewayAndIface();
m_vpnGateway = amnezia::protocols::xray::defaultLocalAddr;
m_vpnLocalAddress = amnezia::protocols::xray::defaultLocalAddr;
m_t2sProcess = IpcClient::InterfaceTun2Socks();
}
XrayProtocol::~XrayProtocol()
@@ -44,9 +43,7 @@ ErrorCode XrayProtocol::start()
m_xrayCfgFile.setAutoRemove(false);
#endif
m_xrayCfgFile.open();
QString config = QJsonDocument(m_xrayConfig).toJson();
config.replace(m_remoteHost, m_remoteAddress);
m_xrayCfgFile.write(config.toUtf8());
m_xrayCfgFile.write(QJsonDocument(m_xrayConfig).toJson());
m_xrayCfgFile.close();
QStringList args = QStringList() << "-c" << m_xrayCfgFile.fileName() << "-format=json";
@@ -66,7 +63,7 @@ ErrorCode XrayProtocol::start()
});
connect(&m_xrayProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug().noquote() << "XrayProtocol finished, exitCode, exitStatus" << exitCode << exitStatus;
qDebug().noquote() << "XrayProtocol finished, exitCode, exiStatus" << exitCode << exitStatus;
setConnectionState(Vpn::ConnectionState::Disconnected);
if (exitStatus != QProcess::NormalExit) {
emit protocolError(amnezia::ErrorCode::XrayExecutableCrashed);
@@ -92,80 +89,116 @@ ErrorCode XrayProtocol::start()
ErrorCode XrayProtocol::startTun2Sock()
{
m_t2sProcess->start();
if (!QFileInfo::exists(Utils::tun2socksPath())) {
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
m_configData.insert("inetAdapterIndex", NetworkUtilities::AdapterIndexTo(QHostAddress(m_remoteAddress)));
#endif
connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::stateChanged, this,
[&](QProcess::ProcessState newState) { qDebug() << "PrivilegedProcess stateChanged" << newState; });
connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::setConnectionState, this,
[&](int vpnState) {
qDebug() << "PrivilegedProcess setConnectionState " << vpnState;
if (vpnState == Vpn::ConnectionState::Connected)
{
setConnectionState(Vpn::ConnectionState::Connecting);
QList<QHostAddress> dnsAddr;
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns1).toString()));
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns2).toString()));
#ifdef Q_OS_WIN
QThread::msleep(8000);
#endif
#ifdef Q_OS_MACOS
QThread::msleep(5000);
IpcClient::Interface()->createTun("utun22", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("utun22", dnsAddr);
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
#ifdef Q_OS_LINUX
QThread::msleep(1000);
IpcClient::Interface()->createTun("tun2", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
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(), &PrivilegedProcess::errorOccurred,
[&](QProcess::ProcessError error) { qDebug() << "PrivilegedProcess errorOccurred" << error; });
connect(m_t2sProcess.data(), &PrivilegedProcess::stateChanged,
[&](QProcess::ProcessState newState) {
qDebug() << "PrivilegedProcess stateChanged" << newState;
if (newState == QProcess::Running)
{
setConnectionState(Vpn::ConnectionState::Connecting);
QList<QHostAddress> dnsAddr;
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns1).toString()));
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns2).toString()));
#ifdef Q_OS_MACOS
QThread::msleep(5000);
IpcClient::Interface()->createTun("utun22", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("utun22", dnsAddr);
#endif
#ifdef Q_OS_WINDOWS
QThread::msleep(15000);
#endif
#ifdef Q_OS_LINUX
QThread::msleep(1000);
IpcClient::Interface()->createTun("tun2", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
#endif
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
// killSwitch toggle
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
m_configData.insert("vpnServer", m_remoteAddress);
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
}
// killSwitch toggle
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
}
#endif
if (m_routeMode == 0) {
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "0.0.0.0/1");
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "128.0.0.0/1");
IpcClient::Interface()->routeAddList(m_routeGateway, QStringList() << m_remoteAddress);
}
IpcClient::Interface()->StopRoutingIpv6();
if (m_routeMode == 0) {
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "0.0.0.0/1");
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "128.0.0.0/1");
IpcClient::Interface()->routeAddList(m_routeGateway, QStringList() << m_remoteAddress);
}
IpcClient::Interface()->StopRoutingIpv6();
#ifdef Q_OS_WIN
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
QList<QNetworkInterface> netInterfaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < netInterfaces.size(); i++) {
for (int j = 0; j < netInterfaces.at(i).addressEntries().size(); j++)
{
// killSwitch toggle
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
}
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
m_configData.insert("vpnGateway", m_vpnGateway);
m_configData.insert("vpnServer", m_remoteAddress);
IpcClient::Interface()->enablePeerTraffic(m_configData);
}
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
QList<QNetworkInterface> netInterfaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < netInterfaces.size(); i++) {
for (int j=0; j < netInterfaces.at(i).addressEntries().size(); j++)
{
// killSwitch toggle
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
}
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
m_configData.insert("vpnGateway", m_vpnGateway);
m_configData.insert("vpnServer", m_remoteAddress);
IpcClient::Interface()->enablePeerTraffic(m_configData);
}
#endif
setConnectionState(Vpn::ConnectionState::Connected);
}
}
#endif
setConnectionState(Vpn::ConnectionState::Connected);
}
});
#if !defined(Q_OS_MACOS)
if (vpnState == Vpn::ConnectionState::Disconnected) {
setConnectionState(Vpn::ConnectionState::Disconnected);
IpcClient::Interface()->deleteTun("tun2");
IpcClient::Interface()->StartRoutingIpv6();
IpcClient::Interface()->clearSavedRoutes();
}
connect(m_t2sProcess.data(), &PrivilegedProcess::finished, this,
[&]() {
setConnectionState(Vpn::ConnectionState::Disconnected);
IpcClient::Interface()->deleteTun("tun2");
IpcClient::Interface()->StartRoutingIpv6();
IpcClient::Interface()->clearSavedRoutes();
});
#endif
});
m_t2sProcess->start();
return ErrorCode::NoError;
}
@@ -179,7 +212,7 @@ void XrayProtocol::stop()
qDebug() << "XrayProtocol::stop()";
m_xrayProcess.terminate();
if (m_t2sProcess) {
m_t2sProcess->stop();
m_t2sProcess->close();
}
#ifdef Q_OS_WIN
@@ -205,8 +238,7 @@ void XrayProtocol::readXrayConfiguration(const QJsonObject &configuration)
}
m_xrayConfig = xrayConfiguration;
m_localPort = QString(amnezia::protocols::xray::defaultLocalProxyPort).toInt();
m_remoteHost = configuration.value(amnezia::config_key::hostName).toString();
m_remoteAddress = NetworkUtilities::getIPAddress(m_remoteHost);
m_remoteAddress = configuration.value(amnezia::config_key::hostName).toString();
m_routeMode = configuration.value(amnezia::config_key::splitTunnelType).toInt();
m_primaryDNS = configuration.value(amnezia::config_key::dns1).toString();
m_secondaryDNS = configuration.value(amnezia::config_key::dns2).toString();
+1 -3
View File
@@ -26,7 +26,6 @@ private:
static QString tun2SocksExecPath();
private:
int m_localPort;
QString m_remoteHost;
QString m_remoteAddress;
int m_routeMode;
QJsonObject m_configData;
@@ -34,10 +33,9 @@ private:
QString m_secondaryDNS;
#ifndef Q_OS_IOS
QProcess m_xrayProcess;
QSharedPointer<IpcProcessTun2SocksReplica> m_t2sProcess;
QSharedPointer<PrivilegedProcess> m_t2sProcess;
#endif
QTemporaryFile m_xrayCfgFile;
};
#endif // XRAYPROTOCOL_H
-2
View File
@@ -199,8 +199,6 @@
<file>server_scripts/socks5_proxy/Dockerfile</file>
<file>server_scripts/socks5_proxy/configure_container.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/PageSetupWizardApiServiceInfo.qml</file>
<file>ui/qml/Controls2/CardWithIconsType.qml</file>
+2 -14
View File
@@ -174,25 +174,13 @@ bool SecureQSettings::restoreAppConfig(const QByteArray &json)
QByteArray SecureQSettings::encryptText(const QByteArray &value) const
{
QSimpleCrypto::QBlockCipher cipher;
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;
return cipher.encryptAesBlockCipher(value, getEncKey(), getEncIv());
}
QByteArray SecureQSettings::decryptText(const QByteArray &ba) const
{
QSimpleCrypto::QBlockCipher cipher;
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;
return cipher.decryptAesBlockCipher(ba, getEncKey(), getEncIv());
}
bool SecureQSettings::encryptionRequired() const
+1 -1
View File
@@ -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'
# 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"
+1 -1
View File
@@ -3,7 +3,7 @@
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
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 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
+1 -16
View File
@@ -227,7 +227,7 @@ void Settings::setSaveLogs(bool enabled)
if (!isSaveLogs()) {
Logger::deInit();
} else {
if (!Logger::init(false)) {
if (!Logger::init()) {
qWarning() << "Initialization of debug subsystem failed";
}
}
@@ -519,22 +519,7 @@ void Settings::setGatewayEndpoint(const QString &endpoint)
m_gatewayEndpoint = endpoint;
}
void Settings::setDevGatewayEndpoint()
{
m_gatewayEndpoint = DEV_AGW_ENDPOINT;
}
QString Settings::getGatewayEndpoint()
{
return m_gatewayEndpoint;
}
bool Settings::isDevGatewayEnv()
{
return m_isDevGatewayEnv;
}
void Settings::toggleDevGatewayEnv(bool enabled)
{
m_isDevGatewayEnv = enabled;
}
+1 -5
View File
@@ -183,7 +183,7 @@ public:
bool isScreenshotsEnabled() const
{
return value("Conf/screenshotsEnabled", true).toBool();
return value("Conf/screenshotsEnabled", false).toBool();
}
void setScreenshotsEnabled(bool enabled)
{
@@ -217,10 +217,7 @@ public:
void resetGatewayEndpoint();
void setGatewayEndpoint(const QString &endpoint);
void setDevGatewayEndpoint();
QString getGatewayEndpoint();
bool isDevGatewayEnv();
void toggleDevGatewayEnv(bool enabled);
signals:
void saveLogsChanged(bool enabled);
@@ -237,7 +234,6 @@ private:
mutable SecureQSettings m_settings;
QString m_gatewayEndpoint;
bool m_isDevGatewayEnv = false;
};
#endif // SETTINGS_H
File diff suppressed because it is too large Load Diff
+122 -331
View File
@@ -4,52 +4,48 @@
<context>
<name>ApiServicesModel</name>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
<location filename="../ui/models/apiServicesModel.cpp" line="63"/>
<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 کلاسیک استفاده کنید. این VPN برای هر سایتی کار میکند و سرعت آن تا %1 مگابیت بر ثانیه است.</translation>
<translation>Для перевода на персидский:
وی پی ان کلاسیک برای کار راحت، دانلود فایلهای بزرگ و تماشای ویدیو. قابل استفاده برای هر سایتی. سرعت تا %1 مگابیت بر ثانیه.</translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
<translation>وی پی ان برای دسترسی به سایتهای مسدود شده در مناطق با سانسور شدید اینترنت.</translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
<source>&lt;p&gt;&lt;a style=&quot;color: #EB5757;&quot;&gt;Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.&lt;/a&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
<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>امنزیا پریمیوم - یک وی پی ان کلاسیک برای کار راحت، دانلود فایلهای بزرگ و تماشای ویدیو با کیفیت بالا. قابل استفاده برای تمامی سایتها، حتی در کشورهایی با بالاترین سطح سانسور اینترنت.</translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
<location filename="../ui/models/apiServicesModel.cpp" line="75"/>
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
<translation>امنزیا رایگان یک وی پی ان رایگان برای دور زدن مسدودیتها در کشورهایی با سطح بالای سانسور اینترنت است.</translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
<source>%1 MBit/s</source>
<translation>%1 MBit/s</translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
<source>%1 days</source>
<translation>%1 روز</translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
<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, &lt;a href=&quot;%1/free&quot; style=&quot;color: #FBB26A;&quot;&gt;more details on the website.&lt;/a&gt;</source>
<translation>وی پی ان فقط سایتهای محبوبی را که در منطقه شما مسدود شدهاند، مانند اینستاگرام، فیسبوک، توییتر و غیره باز میکند. سایر سایتها با آدرس آیپی واقعی شما باز خواهند شد. &lt;a href=&quot;%1/free&quot; style=&quot;color: #FBB26A;&quot;&gt;more details on the website.&lt;/a&gt;</translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
<source>Free</source>
<translation>رایگان</translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
<source>%1 $/month</source>
<translation>%1 $/ماه</translation>
</message>
@@ -80,7 +76,7 @@
<context>
<name>ConnectButton</name>
<message>
<location filename="../ui/qml/Components/ConnectButton.qml" line="28"/>
<location filename="../ui/qml/Components/ConnectButton.qml" line="27"/>
<source>Unable to disconnect during configuration preparation</source>
<translation>در هنگام آمادهسازی پیکربندی، نمیتوان از اتصال خارج شد.</translation>
</message>
@@ -123,7 +119,7 @@
<message>
<location filename="../ui/controllers/connectionController.cpp" line="209"/>
<source>The selected protocol is not supported on the current platform</source>
<translation>پروتکل انتخابشده در پلتفرم فعلی پشتیبانی نمیشود.</translation>
<translation>پروتکل انتخاب شده بر روی این پلتفرم پشتیبانی نمیشودپروتکل انتخاب شده در پلتفرم فعلی پشتیبانی نمیشود.</translation>
</message>
<message>
<location filename="../ui/controllers/connectionController.cpp" line="233"/>
@@ -193,8 +189,9 @@
<context>
<name>ExportController</name>
<message>
<location filename="../ui/controllers/exportController.cpp" line="30"/>
<source>Access error!</source>
<translation type="vanished">خطای دسترسی!</translation>
<translation>خطای دسترسی!</translation>
</message>
</context>
<context>
@@ -263,18 +260,18 @@ Can&apos;t be disabled for current server</source>
<translation>نمیتوان فایل را باز کرد.</translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="187"/>
<location filename="../ui/controllers/importController.cpp" line="192"/>
<location filename="../ui/controllers/importController.cpp" line="186"/>
<location filename="../ui/controllers/importController.cpp" line="191"/>
<source>Invalid configuration file</source>
<translation>فایل پیکربندی نامعتبر است.</translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="617"/>
<location filename="../ui/controllers/importController.cpp" line="606"/>
<source>Scanned %1 of %2.</source>
<translation>ارزیابی %1 از %2.</translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="652"/>
<location filename="../ui/controllers/importController.cpp" line="641"/>
<source>In the imported configuration, potentially dangerous lines were found:</source>
<translation>در پیکربندی وارد شده، خطوطی که ممکن است خطرناک باشند، یافت شدند:</translation>
</message>
@@ -451,11 +448,6 @@ Already installed containers were found on the server. All installed containers
<source>Gateway endpoint</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="101"/>
<source>Dev gateway environment</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PageHome</name>
@@ -490,63 +482,10 @@ Already installed containers were found on the server. All installed containers
<translation>امکان تغییر سرور در هنگام متصل بودن وجود ندارد</translation>
</message>
</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>
<name>PageProtocolAwgSettings</name>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="94"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="96"/>
<source>AmneziaWG settings</source>
<translation>تنظیمات AmneziaWG</translation>
</message>
@@ -555,6 +494,11 @@ Already installed containers were found on the server. All installed containers
<source>Port</source>
<translation>پورت</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
<source>MTU</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove AmneziaWG</source>
<translation type="vanished">حذف AmneziaWG</translation>
@@ -564,87 +508,87 @@ Already installed containers were found on the server. All installed containers
<translation type="vanished">آیا میخواهید AmneziaWG از سرور حذف شود؟</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="357"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="374"/>
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
<translation>همه کاربرانی که با آنها ارتباطی به اشتراک گذاشتهاید دیگر قادر به اتصال به آن نخواهند بود.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="333"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="354"/>
<source>Save</source>
<translation>ذخیره</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="147"/>
<source>Jc - Junk packet count</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="151"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
<source>Jmin - Junk packet minimum size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
<source>Jmax - Junk packet maximum size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
<source>S1 - Init packet junk size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
<source>S2 - Response packet junk size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
<source>H1 - Init packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
<source>H2 - Response packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="298"/>
<source>H4 - Transport packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="299"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="320"/>
<source>H3 - Underload packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="345"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
<source>The values of the H1-H4 fields must be unique</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="351"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="369"/>
<source>The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="356"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="373"/>
<source>Save settings?</source>
<translation>تنظیمات را ذخیره کن?</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="358"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="375"/>
<source>Continue</source>
<translation>ادامه</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="359"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="376"/>
<source>Cancel</source>
<translation>کنسل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="382"/>
<source>Unable change settings while there is an active connection</source>
<translation>نمیتوان تنظیمات را تغییر داد در حالی که اتصال فعال است.</translation>
</message>
@@ -955,88 +899,25 @@ Already installed containers were found on the server. All installed containers
<translation>نمیتوان تنظیمات را تغییر داد در حالی که اتصال فعال است.</translation>
</message>
</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"></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>
<name>PageProtocolWireGuardSettings</name>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="97"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="94"/>
<source>WG settings</source>
<translation>تنظیمات WG</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="107"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="102"/>
<source>Port</source>
<translation>پورت</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="138"/>
<source>Save settings?</source>
<translation type="unfinished">تنظیمات را ذخیره کن?</translation>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="123"/>
<source>MTU</source>
<translation></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="145"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="157"/>
<source>Unable change settings while there is an active connection</source>
<translation>نمیتوان تنظیمات را تغییر داد در حالی که اتصال فعال است.</translation>
</message>
@@ -1045,12 +926,11 @@ Already installed containers were found on the server. All installed containers
<translation type="obsolete">تمام کاربرانی که این ارتباط را با آنها به اشتراک گذاشتهاید دیگر نمیتوانند به آن متصل شوند.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="141"/>
<source>Cancel</source>
<translation type="unfinished">کنسل</translation>
<translation type="obsolete">کنسل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="131"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="149"/>
<source>Save</source>
<translation>ذخیره</translation>
</message>
@@ -1233,13 +1113,13 @@ Already installed containers were found on the server. All installed containers
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="162"/>
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="189"/>
<source>Copied</source>
<translation>کپی شد</translation>
<translation>کپی شدکپی شد</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="125"/>
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="260"/>
<source>Port</source>
<translation>پورت</translation>
<translation>پورتپورت</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="149"/>
@@ -1410,12 +1290,8 @@ Already installed containers were found on the server. All installed containers
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
<source>support@amnezia.org</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mail</source>
<translation type="vanished">ایمیل</translation>
<translation>ایمیل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
@@ -1423,22 +1299,17 @@ Already installed containers were found on the server. All installed containers
<translation>برای ارائه نظرات و گزارشات باگ</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="141"/>
<source>GitHub</source>
<translation>GitHub</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="150"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="148"/>
<source>https://github.com/amnezia-vpn/amnezia-client</source>
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="161"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="159"/>
<source>Website</source>
<translation>وب سایت</translation>
</message>
@@ -1447,17 +1318,17 @@ Already installed containers were found on the server. All installed containers
<translation type="vanished">https://amnezia.org</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="181"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="179"/>
<source>Software version: %1</source>
<translation>%1 :نسخه نرمافزار</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="210"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="208"/>
<source>Check for updates</source>
<translation>بررسی بروزرسانی</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="233"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="231"/>
<source>Privacy Policy</source>
<translation></translation>
</message>
@@ -1514,7 +1385,7 @@ Already installed containers were found on the server. All installed containers
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
<source>Cancel</source>
<translation>لغو</translation>
<translation>کنسللغو کنید</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
@@ -1562,7 +1433,7 @@ Already installed containers were found on the server. All installed containers
<message>
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="129"/>
<source>Mode</source>
<translation>حالت</translation>
<translation>حالتمدل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="221"/>
@@ -1587,7 +1458,7 @@ Already installed containers were found on the server. All installed containers
<message>
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="278"/>
<source>Open executable file</source>
<translation>فایل اجرایی را باز کنید</translation>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="279"/>
@@ -1615,7 +1486,7 @@ Already installed containers were found on the server. All installed containers
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="95"/>
<source>Enable notifications to show the VPN state in the status bar</source>
<translation>اعلان ها را فعال کنید تا وضعیت VPN را در نوار وضعیت ببینید</translation>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="117"/>
@@ -1906,108 +1777,72 @@ Already installed containers were found on the server. All installed containers
<context>
<name>PageSettingsLogging</name>
<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>
<translation type="vanished">ثبت وقایع فعال است. توجه داشته باشید که ثبت وقایع بهطور خودکار پس از ۱۴ روز غیرفعال شده و تمام فایلهای ثبت وقایع حذف خواهند شد.</translation>
<translation>ثبت وقایع فعال است. توجه داشته باشید که ثبت وقایع بهطور خودکار پس از ۱۴ روز غیرفعال شده و تمام فایلهای ثبت وقایع حذف خواهند شد.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="56"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="69"/>
<source>Logging</source>
<translation>گزارشات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="57"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="70"/>
<source>Enabling this function will save application&apos;s logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
<translation>فعال کردن این عملکرد باعث ذخیره خودکار لاگهای برنامه میشود. به طور پیشفرض، قابلیت ثبت لاگ غیرفعال است. در صورت بروز خطا در برنامه، ذخیره لاگ را فعال کنید.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="79"/>
<source>Save logs</source>
<translation type="vanished">ذخیره گزارشات</translation>
<translation>ذخیره گزارشات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="117"/>
<source>Open folder with logs</source>
<translation type="vanished">باز کردن پوشه گزارشات</translation>
<translation>باز کردن پوشه گزارشات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="171"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="255"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="143"/>
<source>Save</source>
<translation>ذخیره</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="256"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="144"/>
<source>Logs files (*.log)</source>
<translation>Logs files (*.log)</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="181"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="265"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="153"/>
<source>Logs file saved</source>
<translation>فایل گزارشات ذخیره شد</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="162"/>
<source>Save logs to file</source>
<translation type="vanished">ذخیره گزارشات در فایل</translation>
<translation>ذخیره گزارشات در فایل</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="184"/>
<source>Clear logs?</source>
<translation>پاک کردن گزارشات؟</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="94"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="185"/>
<source>Continue</source>
<translation>ادامه</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="95"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="186"/>
<source>Cancel</source>
<translation>کنسل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="101"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="192"/>
<source>Logs have been cleaned up</source>
<translation>گزارشات پاک شدند</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="211"/>
<source>Clear logs</source>
<translation>پاک کردن گزارشات</translation>
</message>
@@ -2179,11 +2014,12 @@ Already installed containers were found on the server. All installed containers
<translation> تنظیمات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="135"/>
<source>Clear %1 profile</source>
<translation type="vanished">پاک کردن پروفایل %1</translation>
<translation>پاک کردن پروفایل %1</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="176"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="138"/>
<source>Clear %1 profile?</source>
<translation>آیا میخواهید پروفایل %1 را پاک کنید؟</translation>
</message>
@@ -2193,64 +2029,39 @@ Already installed containers were found on the server. All installed containers
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="183"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="145"/>
<source>Unable to clear %1 profile while there is an active connection</source>
<translation>نمیتوان پروفایل %1 را در حین اتصال فعال پاک کرد.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="224"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="186"/>
<source>Remove </source>
<translation>حذف </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="228"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="190"/>
<source>Remove %1 from server?</source>
<translation>حذف %1 از سرور؟</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="229"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="191"/>
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
<translation>تمام کاربرانی که این ارتباط را با آنها به اشتراک گذاشتهاید دیگر نمیتوانند به آن متصل شوند.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="236"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="198"/>
<source>Cannot remove active container</source>
<translation>نمیتوان کانتینر فعال را حذف کرد.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="178"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="230"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="140"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="192"/>
<source>Continue</source>
<translation>ادامه</translation>
</message>
<message>
<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 &quot;connect&quot; 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="179"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="231"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="141"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="193"/>
<source>Cancel</source>
<translation>کنسل</translation>
</message>
@@ -2433,7 +2244,7 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<translation type="vanished">چی داری؟</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="241"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="198"/>
<source>File with connection settings</source>
<translation>فایل شامل تنظیمات اتصال</translation>
</message>
@@ -2447,87 +2258,77 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<translation>ارتباط</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
<source>Insert the key, add a configuration file or scan the QR-code</source>
<translation>کلید را وارد کنید، فایل پیکربندی را اضافه کنید یا کد QR را اسکن کنید</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="122"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
<source>Insert key</source>
<translation>کلید را وارد کنید</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="123"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
<source>Insert</source>
<translation>وارد کردن</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="143"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
<source>Continue</source>
<translation>ادامه دهید</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="161"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
<source>Other connection options</source>
<translation>گزینههای اتصال دیگر</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
<source>VPN by Amnezia</source>
<translation>VPN توسط Amnezia</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="173"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
<source>Connect to classic paid and free VPN services from Amnezia</source>
<translation>اتصال به سرویسهای VPN کلاسیک پولی و رایگان از Amnezia</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="196"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
<source>Self-hosted VPN</source>
<translation>Self-hosted VPN</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="197"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
<source>Configure Amnezia VPN on your own server</source>
<translation>پیکربندی VPN Amnezia بر روی سرور خودتان</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="217"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
<source>Restore from backup</source>
<translation>بازیابی از پشتیبان</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="223"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
<source>Open backup file</source>
<translation>باز کردن فایل پشتیبان</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="224"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
<source>Backup files (*.backup)</source>
<translation>Backup files (*.backup)</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="249"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="206"/>
<source>Open config file</source>
<translation>باز کردن فایل تنظیمات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="268"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="225"/>
<source>QR code</source>
<translation>QR-Code</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="291"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
<source>I have nothing</source>
<translation>من هیچی ندارم</translation>
</message>
@@ -2699,7 +2500,7 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<translation>نصب</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="268"/>
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
<source>The port must be in the range of 1 to 65535</source>
<translation>پورت باید در محدوده ۱ تا ۶۵۵۳۵ باشد</translation>
</message>
@@ -3067,17 +2868,12 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<translation>اشتراکگذاری</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="143"/>
<source>Connection to </source>
<translation>ارتباط با </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="154"/>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="144"/>
<source>File with connection settings to </source>
<translation>فایل شامل تنظیمات ارتباط با </translation>
</message>
@@ -3094,11 +2890,6 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<source>Settings restored from backup file</source>
<translation>تنظیمات از فایل پشتیبان بازیابی شد</translation>
</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>
<name>PopupType</name>
@@ -3137,12 +2928,12 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<translation>Password not found</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="175"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
<source>Could not open keystore</source>
<translation>Could not open keystore</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="181"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
<source>Could not remove private key from keystore</source>
<translation>Could not remove private key from keystore</translation>
</message>
@@ -3318,27 +3109,27 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<translation>Could not open keystore</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="126"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
<source>Could not create private key generator</source>
<translation>Could not create private key generator</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="133"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="131"/>
<source>Could not generate new private key</source>
<translation>Could not generate new private key</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="141"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="139"/>
<source>Could not retrieve private key from keystore</source>
<translation>Could not retrieve private key from keystore</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="149"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="147"/>
<source>Could not create encryption cipher</source>
<translation>Could not create encryption cipher</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="157"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="155"/>
<source>Could not encrypt data</source>
<translation>Could not encrypt data</translation>
</message>
@@ -4093,7 +3884,7 @@ For more detailed information, you can
<context>
<name>SettingsController</name>
<message>
<location filename="../ui/controllers/settingsController.cpp" line="174"/>
<location filename="../ui/controllers/settingsController.cpp" line="160"/>
<source>All settings have been reset to default values</source>
<translation>تمام تنظیمات به مقادیر پیش فرض ریست شد</translation>
</message>
@@ -4102,7 +3893,7 @@ For more detailed information, you can
<translation type="vanished">پروفایل ذخیره شده پاک شد</translation>
</message>
<message>
<location filename="../ui/controllers/settingsController.cpp" line="152"/>
<location filename="../ui/controllers/settingsController.cpp" line="138"/>
<source>Backup file is corrupted</source>
<translation>فایل بکآپ خراب شده است</translation>
</message>
@@ -4234,7 +4025,7 @@ For more detailed information, you can
<context>
<name>VpnConnection</name>
<message>
<location filename="../vpnconnection.cpp" line="408"/>
<location filename="../vpnconnection.cpp" line="375"/>
<source>Mbps</source>
<translation>Mbps</translation>
</message>
+109 -331
View File
@@ -4,52 +4,47 @@
<context>
<name>ApiServicesModel</name>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
<location filename="../ui/models/apiServicesModel.cpp" line="63"/>
<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>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
<source>&lt;p&gt;&lt;a style=&quot;color: #EB5757;&quot;&gt;Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.&lt;/a&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
<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>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
<location filename="../ui/models/apiServicesModel.cpp" line="75"/>
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
<source>%1 MBit/s</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
<source>%1 days</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
<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, &lt;a href=&quot;%1/free&quot; style=&quot;color: #FBB26A;&quot;&gt;more details on the website.&lt;/a&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
<source>Free</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
<source>%1 $/month</source>
<translation type="unfinished"></translation>
</message>
@@ -80,7 +75,7 @@
<context>
<name>ConnectButton</name>
<message>
<location filename="../ui/qml/Components/ConnectButton.qml" line="28"/>
<location filename="../ui/qml/Components/ConnectButton.qml" line="27"/>
<source>Unable to disconnect during configuration preparation</source>
<translation>ि ि </translation>
</message>
@@ -192,8 +187,9 @@
<context>
<name>ExportController</name>
<message>
<location filename="../ui/controllers/exportController.cpp" line="30"/>
<source>Access error!</source>
<translation type="vanished"> ि!</translation>
<translation> ि!</translation>
</message>
</context>
<context>
@@ -259,18 +255,18 @@ Can&apos;t be disabled for current server</source>
<translation> </translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="187"/>
<location filename="../ui/controllers/importController.cpp" line="192"/>
<location filename="../ui/controllers/importController.cpp" line="186"/>
<location filename="../ui/controllers/importController.cpp" line="191"/>
<source>Invalid configuration file</source>
<translation> ि </translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="617"/>
<location filename="../ui/controllers/importController.cpp" line="606"/>
<source>Scanned %1 of %2.</source>
<translation>%2 %1 ि .</translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="652"/>
<location filename="../ui/controllers/importController.cpp" line="641"/>
<source>In the imported configuration, potentially dangerous lines were found:</source>
<translation type="unfinished"></translation>
</message>
@@ -447,11 +443,6 @@ Already installed containers were found on the server. All installed containers
<source>Gateway endpoint</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="101"/>
<source>Dev gateway environment</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PageHome</name>
@@ -486,63 +477,10 @@ Already installed containers were found on the server. All installed containers
<translation>ि </translation>
</message>
</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>
<name>PageProtocolAwgSettings</name>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="94"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="96"/>
<source>AmneziaWG settings</source>
<translation>Amneziaडब्ल्यूज ि</translation>
</message>
@@ -552,91 +490,92 @@ Already installed containers were found on the server. All installed containers
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
<source>MTU</source>
<translation type="vanished"></translation>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="147"/>
<source>Jc - Junk packet count</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="151"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
<source>Jmin - Junk packet minimum size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
<source>Jmax - Junk packet maximum size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
<source>S1 - Init packet junk size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
<source>S2 - Response packet junk size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
<source>H1 - Init packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
<source>H2 - Response packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="298"/>
<source>H4 - Transport packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="299"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="320"/>
<source>H3 - Underload packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="333"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="354"/>
<source>Save</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="345"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
<source>The values of the H1-H4 fields must be unique</source>
<translation>H1-H4 ि ि</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="351"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="369"/>
<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>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="356"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="373"/>
<source>Save settings?</source>
<translation>ि ?</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="357"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="374"/>
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
<translation> ि ि , .</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="382"/>
<source>Unable change settings while there is an active connection</source>
<translation>ि ि </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="358"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="375"/>
<source>Continue</source>
<translation> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="359"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="376"/>
<source>Cancel</source>
<translation> </translation>
</message>
@@ -923,102 +862,30 @@ Already installed containers were found on the server. All installed containers
<translation>ि ि </translation>
</message>
</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>
<name>PageProtocolWireGuardSettings</name>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="97"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="94"/>
<source>WG settings</source>
<translation> ि</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="107"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="102"/>
<source>Port</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="123"/>
<source>MTU</source>
<translation type="vanished"></translation>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="131"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="149"/>
<source>Save</source>
<translation></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="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"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="157"/>
<source>Unable change settings while there is an active connection</source>
<translation>ि ि </translation>
</message>
@@ -1369,14 +1236,10 @@ Already installed containers were found on the server. All installed containers
<source>https://t.me/amnezia_vpn_en</source>
<translation></translation>
</message>
<message>
<source>Mail</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
<source>support@amnezia.org</source>
<translation type="unfinished"></translation>
<source>Mail</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
@@ -1384,37 +1247,32 @@ Already installed containers were found on the server. All installed containers
<translation> ि ि</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="141"/>
<source>GitHub</source>
<translation>GitHub</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="150"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="148"/>
<source>https://github.com/amnezia-vpn/amnezia-client</source>
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="161"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="159"/>
<source>Website</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="181"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="179"/>
<source>Software version: %1</source>
<translation> : %1</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="210"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="208"/>
<source>Check for updates</source>
<translation> ि </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="233"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="231"/>
<source>Privacy Policy</source>
<translation> ि</translation>
</message>
@@ -1871,108 +1729,72 @@ Already installed containers were found on the server. All installed containers
<context>
<name>PageSettingsLogging</name>
<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>
<translation type="vanished">ि . ि 14 ि ि , .</translation>
<translation>ि . ि 14 ि ि , .</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="56"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="69"/>
<source>Logging</source>
<translation>ि</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="57"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="70"/>
<source>Enabling this function will save application&apos;s logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
<translation> ि ि , ि , ि ि िि ि .</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="79"/>
<source>Save logs</source>
<translation type="vanished"> </translation>
<translation> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="117"/>
<source>Open folder with logs</source>
<translation type="vanished"> </translation>
<translation> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="171"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="255"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="143"/>
<source>Save</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="256"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="144"/>
<source>Logs files (*.log)</source>
<translation> (*.log)</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="181"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="265"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="153"/>
<source>Logs file saved</source>
<translation> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="162"/>
<source>Save logs to file</source>
<translation type="vanished"> </translation>
<translation> </translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="184"/>
<source>Clear logs?</source>
<translation> ?</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="94"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="185"/>
<source>Continue</source>
<translation> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="95"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="186"/>
<source>Cancel</source>
<translation> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="101"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="192"/>
<source>Logs have been cleaned up</source>
<translation> ि </translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="211"/>
<source>Clear logs</source>
<translation> </translation>
</message>
@@ -2132,11 +1954,12 @@ Already installed containers were found on the server. All installed containers
<translation> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="135"/>
<source>Clear %1 profile</source>
<translation type="vanished">%1 </translation>
<translation>%1 </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="176"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="138"/>
<source>Clear %1 profile?</source>
<translation>%1 ?</translation>
</message>
@@ -2146,64 +1969,39 @@ Already installed containers were found on the server. All installed containers
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="183"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="145"/>
<source>Unable to clear %1 profile while there is an active connection</source>
<translation>ि %1 </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="224"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="186"/>
<source>Remove </source>
<translation>ि </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="229"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="191"/>
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
<translation> ि ि , .</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="236"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="198"/>
<source>Cannot remove active container</source>
<translation>ि </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="228"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="190"/>
<source>Remove %1 from server?</source>
<translation> %1 ?</translation>
</message>
<message>
<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 &quot;connect&quot; 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"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="140"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="192"/>
<source>Continue</source>
<translation> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="179"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="231"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="141"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="193"/>
<source>Cancel</source>
<translation> </translation>
</message>
@@ -2387,92 +2185,82 @@ Already installed containers were found on the server. All installed containers
<translation type="unfinished"></translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
<source>Insert the key, add a configuration file or scan the QR-code</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="122"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
<source>Insert key</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="123"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
<source>Insert</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="143"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
<source>Continue</source>
<translation type="unfinished"> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="161"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
<source>Other connection options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
<source>VPN by Amnezia</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="173"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
<source>Connect to classic paid and free VPN services from Amnezia</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="196"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
<source>Self-hosted VPN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="197"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
<source>Configure Amnezia VPN on your own server</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="217"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
<source>Restore from backup</source>
<translation type="unfinished"> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="223"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
<source>Open backup file</source>
<translation type="unfinished"> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="224"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
<source>Backup files (*.backup)</source>
<translation type="unfinished"> (*.backup)</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="241"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="198"/>
<source>File with connection settings</source>
<translation> ि </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="249"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="206"/>
<source>Open config file</source>
<translation>ि </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="268"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="225"/>
<source>QR code</source>
<translation> ि</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="291"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
<source>I have nothing</source>
<translation type="unfinished"> </translation>
</message>
@@ -2644,7 +2432,7 @@ Already installed containers were found on the server. All installed containers
<translation>ि </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="268"/>
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
<source>The port must be in the range of 1 to 65535</source>
<translation type="unfinished"></translation>
</message>
@@ -3016,17 +2804,12 @@ Already installed containers were found on the server. All installed containers
<translation> </translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="143"/>
<source>Connection to </source>
<translation> ि </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="154"/>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="144"/>
<source>File with connection settings to </source>
<translation> ि </translation>
</message>
@@ -3043,11 +2826,6 @@ Already installed containers were found on the server. All installed containers
<source>Settings restored from backup file</source>
<translation type="unfinished"> ि ि </translation>
</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>
<name>PopupType</name>
@@ -3086,12 +2864,12 @@ Already installed containers were found on the server. All installed containers
<translation> ि</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="175"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
<source>Could not open keystore</source>
<translation> </translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="181"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
<source>Could not remove private key from keystore</source>
<translation> ि </translation>
</message>
@@ -3267,27 +3045,27 @@ Already installed containers were found on the server. All installed containers
<translation> </translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="126"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
<source>Could not create private key generator</source>
<translation>ि </translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="133"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="131"/>
<source>Could not generate new private key</source>
<translation> ि </translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="141"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="139"/>
<source>Could not retrieve private key from keystore</source>
<translation> ि </translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="149"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="147"/>
<source>Could not create encryption cipher</source>
<translation>ि ि </translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="157"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="155"/>
<source>Could not encrypt data</source>
<translation> ि ि </translation>
</message>
@@ -3985,12 +3763,12 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<context>
<name>SettingsController</name>
<message>
<location filename="../ui/controllers/settingsController.cpp" line="152"/>
<location filename="../ui/controllers/settingsController.cpp" line="138"/>
<source>Backup file is corrupted</source>
<translation> ि </translation>
</message>
<message>
<location filename="../ui/controllers/settingsController.cpp" line="174"/>
<location filename="../ui/controllers/settingsController.cpp" line="160"/>
<source>All settings have been reset to default values</source>
<translation> ि ि ि </translation>
</message>
@@ -4122,7 +3900,7 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<context>
<name>VpnConnection</name>
<message>
<location filename="../vpnconnection.cpp" line="408"/>
<location filename="../vpnconnection.cpp" line="375"/>
<source>Mbps</source>
<translation></translation>
</message>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+109 -331
View File
@@ -4,52 +4,47 @@
<context>
<name>ApiServicesModel</name>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
<location filename="../ui/models/apiServicesModel.cpp" line="63"/>
<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>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
<source>&lt;p&gt;&lt;a style=&quot;color: #EB5757;&quot;&gt;Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.&lt;/a&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
<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>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
<location filename="../ui/models/apiServicesModel.cpp" line="75"/>
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
<source>%1 MBit/s</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
<source>%1 days</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
<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, &lt;a href=&quot;%1/free&quot; style=&quot;color: #FBB26A;&quot;&gt;more details on the website.&lt;/a&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
<source>Free</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
<source>%1 $/month</source>
<translation type="unfinished"></translation>
</message>
@@ -80,7 +75,7 @@
<context>
<name>ConnectButton</name>
<message>
<location filename="../ui/qml/Components/ConnectButton.qml" line="28"/>
<location filename="../ui/qml/Components/ConnectButton.qml" line="27"/>
<source>Unable to disconnect during configuration preparation</source>
<translation>تشکیل کی تیاری کے دوران منقطع ہونا ممکن نہیں ہے</translation>
</message>
@@ -191,8 +186,9 @@
<context>
<name>ExportController</name>
<message>
<location filename="../ui/controllers/exportController.cpp" line="30"/>
<source>Access error!</source>
<translation type="vanished">رساءی ناممکن!</translation>
<translation>رساءی ناممکن!</translation>
</message>
</context>
<context>
@@ -257,18 +253,18 @@ Can&apos;t be disabled for current server</source>
<translation>فائل کو کھولنے سے قاصر ہے</translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="187"/>
<location filename="../ui/controllers/importController.cpp" line="192"/>
<location filename="../ui/controllers/importController.cpp" line="186"/>
<location filename="../ui/controllers/importController.cpp" line="191"/>
<source>Invalid configuration file</source>
<translation>غلط کنفیگریشن فائل</translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="617"/>
<location filename="../ui/controllers/importController.cpp" line="606"/>
<source>Scanned %1 of %2.</source>
<translation>سکین%1 کی%2.</translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="652"/>
<location filename="../ui/controllers/importController.cpp" line="641"/>
<source>In the imported configuration, potentially dangerous lines were found:</source>
<translation type="unfinished"></translation>
</message>
@@ -447,11 +443,6 @@ Already installed containers were found on the server. All installed containers
<source>Gateway endpoint</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="101"/>
<source>Dev gateway environment</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PageHome</name>
@@ -486,63 +477,10 @@ Already installed containers were found on the server. All installed containers
<translation>فعال کنکشن موجود ہونے کی وجہ سے سرور تبدیل کرنے میں ناکام ہیں</translation>
</message>
</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>
<name>PageProtocolAwgSettings</name>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="94"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="96"/>
<source>AmneziaWG settings</source>
<translation>امنیزیا وی جی کی ترتیبات</translation>
</message>
@@ -552,91 +490,92 @@ Already installed containers were found on the server. All installed containers
<translation>پورٹ</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
<source>MTU</source>
<translation type="vanished">ام ٹی یو</translation>
<translation>ام ٹی یو</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="357"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="374"/>
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
<translation>آپ جن لوگوں کے ساتھ آپ نے اس کنکشن کا اشتراک کیا تھا، وہ اس سے مزید جڑ نہیں سکیں گے۔</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="333"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="354"/>
<source>Save</source>
<translation>محفوظ کریں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="147"/>
<source>Jc - Junk packet count</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="151"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
<source>Jmin - Junk packet minimum size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
<source>Jmax - Junk packet maximum size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
<source>S1 - Init packet junk size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
<source>S2 - Response packet junk size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
<source>H1 - Init packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
<source>H2 - Response packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="298"/>
<source>H4 - Transport packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="299"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="320"/>
<source>H3 - Underload packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="345"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
<source>The values of the H1-H4 fields must be unique</source>
<translation>H1 تا H4 فیلڈز کی قیمتیں مخصوص ہونی چاہیے</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="351"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="369"/>
<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>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="356"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="373"/>
<source>Save settings?</source>
<translation>ترتیبات محفوظ کریں?</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="358"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="375"/>
<source>Continue</source>
<translation>جاری رکھیں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="359"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="376"/>
<source>Cancel</source>
<translation>منسوخ کریں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="382"/>
<source>Unable change settings while there is an active connection</source>
<translation>جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
</message>
@@ -923,102 +862,30 @@ Already installed containers were found on the server. All installed containers
<translation>جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
</message>
</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>
<name>PageProtocolWireGuardSettings</name>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="97"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="94"/>
<source>WG settings</source>
<translation>وائر گارڈ ترتیبات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="107"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="102"/>
<source>Port</source>
<translation>پورٹ</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="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="123"/>
<source>MTU</source>
<translation type="vanished">ام ٹی یو</translation>
<translation>ام ٹی یو</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="145"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="157"/>
<source>Unable change settings while there is an active connection</source>
<translation>جب ایک فعال کنکشن موجود ہو تو ترتیبات کو تبدیل نہیں کیا جا سکتا</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="131"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="149"/>
<source>Save</source>
<translation>محفوظ کریں</translation>
</message>
@@ -1373,14 +1240,10 @@ Already installed containers were found on the server. All installed containers
<source>https://t.me/amnezia_vpn_en</source>
<translation></translation>
</message>
<message>
<source>Mail</source>
<translation type="vanished">میل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
<source>support@amnezia.org</source>
<translation type="unfinished"></translation>
<source>Mail</source>
<translation>میل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
@@ -1388,37 +1251,32 @@ Already installed containers were found on the server. All installed containers
<translation>جائزہ اور بگ رپورٹس کے لئے</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="141"/>
<source>GitHub</source>
<translation>گِٹ ہَب</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="150"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="148"/>
<source>https://github.com/amnezia-vpn/amnezia-client</source>
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="161"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="159"/>
<source>Website</source>
<translation>ویب سائٹ</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="181"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="179"/>
<source>Software version: %1</source>
<translation>سافٹ ویئر ورژن: %1</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="210"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="208"/>
<source>Check for updates</source>
<translation>اپ ڈیٹس چیک کریں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="233"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="231"/>
<source>Privacy Policy</source>
<translation>رازداری کی پالیسی</translation>
</message>
@@ -1875,108 +1733,72 @@ Already installed containers were found on the server. All installed containers
<context>
<name>PageSettingsLogging</name>
<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>
<translation type="vanished">لاگنگ فعال ہے۔ یاد رہے کہ لاگوں کو 14 دنوں کے بعد خود بخود غیر فعال کر دیا جائے گا، اور تمام لاگ فائلیں حذف کردی جائیں گی.</translation>
<translation>لاگنگ فعال ہے۔ یاد رہے کہ لاگوں کو 14 دنوں کے بعد خود بخود غیر فعال کر دیا جائے گا، اور تمام لاگ فائلیں حذف کردی جائیں گی.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="56"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="69"/>
<source>Logging</source>
<translation>لاگنگ</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="57"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="70"/>
<source>Enabling this function will save application&apos;s logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
<translation>اس فعل کو فعال کرنے سے، ایپلیکیشن کے لاگ خود بخود محفوظ ہوجائیں گے۔ پہلے سے، لاگنگ کی فعالیت غیر فعال ہوتی ہے۔ اگر ایپلیکیشن میں کوئی خرابی ہو، تو لاگ کو بچانا فعال کریں.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="79"/>
<source>Save logs</source>
<translation type="vanished">لاگوں کو محفوظ کریں</translation>
<translation>لاگوں کو محفوظ کریں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="117"/>
<source>Open folder with logs</source>
<translation type="vanished">فائلوں کے فولڈر کو کھولیں</translation>
<translation>فائلوں کے فولڈر کو کھولیں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="171"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="255"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="143"/>
<source>Save</source>
<translation>محفوظ</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="256"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="144"/>
<source>Logs files (*.log)</source>
<translation>لاگ فائلیں (*.log)</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="181"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="265"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="153"/>
<source>Logs file saved</source>
<translation>لاگ فائل محفوظ ہوگئی</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="162"/>
<source>Save logs to file</source>
<translation type="vanished">لاگوں کو فائل میں محفوظ کریں</translation>
<translation>لاگوں کو فائل میں محفوظ کریں</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="184"/>
<source>Clear logs?</source>
<translation>کیا آپ لاگوں کو صاف کرنا چاہتے ہیں؟</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="94"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="185"/>
<source>Continue</source>
<translation>براہ کرم جاری رکھیں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="95"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="186"/>
<source>Cancel</source>
<translation>منسوخ</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="101"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="192"/>
<source>Logs have been cleaned up</source>
<translation>تم مسح السجلاتلاگوں کو صاف کر دیا گیا ہے</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="211"/>
<source>Clear logs</source>
<translation>لاگوں کو صاف کریں</translation>
</message>
@@ -2136,21 +1958,22 @@ Already installed containers were found on the server. All installed containers
<translation> ترتیبات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="135"/>
<source>Clear %1 profile</source>
<translation type="vanished">%1 پروفائل کو صاف کریں</translation>
<translation>%1 پروفائل کو صاف کریں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="176"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="138"/>
<source>Clear %1 profile?</source>
<translation>کیا آپ واقعی %1 پروفائل کو صاف کرنا چاہتے ہیں؟</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="183"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="145"/>
<source>Unable to clear %1 profile while there is an active connection</source>
<translation>فعال کنکشن کے دوران %1 پروفائل کو صاف نہیں کیا جا سکتا</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="236"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="198"/>
<source>Cannot remove active container</source>
<translation>فعال کنٹینر کو ہٹانا ممکن نہیں</translation>
</message>
@@ -2160,54 +1983,29 @@ Already installed containers were found on the server. All installed containers
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="224"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="186"/>
<source>Remove </source>
<translation>ہٹائیں </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="229"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="191"/>
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
<translation>آپ نے جن کے ساتھ کنکشن شئیر کیا تھا، ان تمام صارفین کو اس سے جڑنے کی اجازت نہیں ہوگی.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="228"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="190"/>
<source>Remove %1 from server?</source>
<translation>کیا آپ سرور سے %1 کو ہٹانا چاہتے ہیں؟</translation>
</message>
<message>
<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 &quot;connect&quot; 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"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="140"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="192"/>
<source>Continue</source>
<translation>براہ کرم جاری رکھیں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="179"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="231"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="141"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="193"/>
<source>Cancel</source>
<translation>منسوخ</translation>
</message>
@@ -2391,92 +2189,82 @@ Already installed containers were found on the server. All installed containers
<translation type="unfinished">کنکشن</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
<source>Insert the key, add a configuration file or scan the QR-code</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="122"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
<source>Insert key</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="123"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
<source>Insert</source>
<translation type="unfinished">داخل کریں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="143"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
<source>Continue</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="161"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
<source>Other connection options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
<source>VPN by Amnezia</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="173"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
<source>Connect to classic paid and free VPN services from Amnezia</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="196"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
<source>Self-hosted VPN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="197"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
<source>Configure Amnezia VPN on your own server</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="217"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
<source>Restore from backup</source>
<translation type="unfinished">بیک اپ سے بحال کریں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="223"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
<source>Open backup file</source>
<translation type="unfinished">بیک اپ فائل کو کھولیں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="224"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
<source>Backup files (*.backup)</source>
<translation type="unfinished">بیک اپ فائلیں (*.backup)</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="241"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="198"/>
<source>File with connection settings</source>
<translation>کنکشن کی ترتیبات والی فائل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="249"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="206"/>
<source>Open config file</source>
<translation>کنفیگ فائل کو کھولیں</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="268"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="225"/>
<source>QR code</source>
<translation>QR کوڈ</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="291"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
<source>I have nothing</source>
<translation type="unfinished">میرے پاس کچھ نہیں ہے</translation>
</message>
@@ -2648,7 +2436,7 @@ Already installed containers were found on the server. All installed containers
<translation>انسٹال</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="268"/>
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
<source>The port must be in the range of 1 to 65535</source>
<translation type="unfinished"></translation>
</message>
@@ -3020,17 +2808,12 @@ Already installed containers were found on the server. All installed containers
<translation>شیئر</translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="143"/>
<source>Connection to </source>
<translation>کنکشن کو </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="154"/>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="144"/>
<source>File with connection settings to </source>
<translation>کنکشن کی ترتیبات کی فائل </translation>
</message>
@@ -3047,11 +2830,6 @@ Already installed containers were found on the server. All installed containers
<source>Settings restored from backup file</source>
<translation type="unfinished">ترتیبات بیک اپ فائل سے بحال کردی گئی ہیں</translation>
</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>
<name>PopupType</name>
@@ -3090,12 +2868,12 @@ Already installed containers were found on the server. All installed containers
<translation>پاس ورڈ نہیں ملا</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="175"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
<source>Could not open keystore</source>
<translation>کی اسٹور کھولا نہیں جا سکا</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="181"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
<source>Could not remove private key from keystore</source>
<translation>خصوصی کلید کو کی اسٹور سے ہٹانا نہیں ہو سکا</translation>
</message>
@@ -3271,27 +3049,27 @@ Already installed containers were found on the server. All installed containers
<translation>کی اسٹور کھولنے میں ناکام</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="126"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
<source>Could not create private key generator</source>
<translation>پرائیویٹ کلید جنریٹر تخلیق نہیں کیا</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="133"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="131"/>
<source>Could not generate new private key</source>
<translation>نیا نجی کلید تخلیق نہیں کیا جا سکا</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="141"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="139"/>
<source>Could not retrieve private key from keystore</source>
<translation>کی اسٹور سے نجی کلید حاصل نہیں کیا</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="149"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="147"/>
<source>Could not create encryption cipher</source>
<translation>تشکیل تشکیل نہیں کر سکا</translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="157"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="155"/>
<source>Could not encrypt data</source>
<translation>ڈیٹا کو محفوظ کرنے میں ناکام</translation>
</message>
@@ -3931,12 +3709,12 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<context>
<name>SettingsController</name>
<message>
<location filename="../ui/controllers/settingsController.cpp" line="152"/>
<location filename="../ui/controllers/settingsController.cpp" line="138"/>
<source>Backup file is corrupted</source>
<translation>بیک اپ فائل خراب ہو گئی ہے</translation>
</message>
<message>
<location filename="../ui/controllers/settingsController.cpp" line="174"/>
<location filename="../ui/controllers/settingsController.cpp" line="160"/>
<source>All settings have been reset to default values</source>
<translation>تمام ترتیبات کو ڈیفالٹ اقدار پر دوبارہ ترتیب دیا گیا ہے</translation>
</message>
@@ -4068,7 +3846,7 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<context>
<name>VpnConnection</name>
<message>
<location filename="../vpnconnection.cpp" line="408"/>
<location filename="../vpnconnection.cpp" line="375"/>
<source>Mbps</source>
<translation>ایم بی پی ایس</translation>
</message>
+124 -322
View File
@@ -4,52 +4,47 @@
<context>
<name>ApiServicesModel</name>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="65"/>
<location filename="../ui/models/apiServicesModel.cpp" line="63"/>
<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>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="69"/>
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="71"/>
<source>&lt;p&gt;&lt;a style=&quot;color: #EB5757;&quot;&gt;Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.&lt;/a&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="78"/>
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
<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>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="81"/>
<location filename="../ui/models/apiServicesModel.cpp" line="75"/>
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="94"/>
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
<source>%1 MBit/s</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="101"/>
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
<source>%1 days</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="110"/>
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
<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, &lt;a href=&quot;%1/free&quot; style=&quot;color: #FBB26A;&quot;&gt;more details on the website.&lt;/a&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="118"/>
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
<source>Free</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/models/apiServicesModel.cpp" line="120"/>
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
<source>%1 $/month</source>
<translation type="unfinished"></translation>
</message>
@@ -80,7 +75,7 @@
<context>
<name>ConnectButton</name>
<message>
<location filename="../ui/qml/Components/ConnectButton.qml" line="28"/>
<location filename="../ui/qml/Components/ConnectButton.qml" line="27"/>
<source>Unable to disconnect during configuration preparation</source>
<translation type="unfinished"></translation>
</message>
@@ -191,8 +186,9 @@
<context>
<name>ExportController</name>
<message>
<location filename="../ui/controllers/exportController.cpp" line="30"/>
<source>Access error!</source>
<translation type="vanished">访</translation>
<translation>访</translation>
</message>
</context>
<context>
@@ -262,18 +258,18 @@ Can&apos;t be disabled for current server</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="187"/>
<location filename="../ui/controllers/importController.cpp" line="192"/>
<location filename="../ui/controllers/importController.cpp" line="186"/>
<location filename="../ui/controllers/importController.cpp" line="191"/>
<source>Invalid configuration file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="617"/>
<location filename="../ui/controllers/importController.cpp" line="606"/>
<source>Scanned %1 of %2.</source>
<translation> %1 of %2.</translation>
</message>
<message>
<location filename="../ui/controllers/importController.cpp" line="652"/>
<location filename="../ui/controllers/importController.cpp" line="641"/>
<source>In the imported configuration, potentially dangerous lines were found:</source>
<translation type="unfinished"></translation>
</message>
@@ -473,11 +469,6 @@ Already installed containers were found on the server. All installed containers
<source>Gateway endpoint</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="101"/>
<source>Dev gateway environment</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PageHome</name>
@@ -512,63 +503,10 @@ Already installed containers were found on the server. All installed containers
<translation></translation>
</message>
</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>
<name>PageProtocolAwgSettings</name>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="94"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="96"/>
<source>AmneziaWG settings</source>
<translation>AmneziaWG </translation>
</message>
@@ -577,6 +515,11 @@ Already installed containers were found on the server. All installed containers
<source>Port</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
<source>MTU</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove AmneziaWG</source>
<translation type="vanished">AmneziaWG</translation>
@@ -586,87 +529,87 @@ Already installed containers were found on the server. All installed containers
<translation type="vanished">AmneziaWG</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="357"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="374"/>
<source>All users with whom you shared a connection with will no longer be able to connect to it.</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="333"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="354"/>
<source>Save</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="126"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="147"/>
<source>Jc - Junk packet count</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="151"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
<source>Jmin - Junk packet minimum size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
<source>Jmax - Junk packet maximum size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
<source>S1 - Init packet junk size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
<source>S2 - Response packet junk size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
<source>H1 - Init packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
<source>H2 - Response packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="298"/>
<source>H4 - Transport packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="299"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="320"/>
<source>H3 - Underload packet magic header</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="345"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
<source>The values of the H1-H4 fields must be unique</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="351"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="369"/>
<source>The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="356"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="373"/>
<source>Save settings?</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="358"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="375"/>
<source>Continue</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="359"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="376"/>
<source>Cancel</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="382"/>
<source>Unable change settings while there is an active connection</source>
<translation type="unfinished"></translation>
</message>
@@ -990,82 +933,24 @@ Already installed containers were found on the server. All installed containers
</message>
</context>
<context>
<name>PageProtocolWireGuardClientSettings</name>
<name>PageProtocolWireGuardSettings</name>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="93"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="94"/>
<source>WG settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml" line="101"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="102"/>
<source>Port</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="123"/>
<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>
<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"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="157"/>
<source>Unable change settings while there is an active connection</source>
<translation type="unfinished"></translation>
</message>
@@ -1074,17 +959,15 @@ Already installed containers were found on the server. All installed containers
<translation type="obsolete"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="140"/>
<source>Continue</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="141"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="131"/>
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="149"/>
<source>Save</source>
<translation></translation>
</message>
@@ -1445,14 +1328,10 @@ And if you don&apos;t like the app, all the more support it - the donation will
<source>https://t.me/amnezia_vpn_en</source>
<translation></translation>
</message>
<message>
<source>Mail</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
<source>support@amnezia.org</source>
<translation type="unfinished"></translation>
<source>Mail</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="124"/>
@@ -1460,37 +1339,32 @@ And if you don&apos;t like the app, all the more support it - the donation will
<translation></translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="141"/>
<source>GitHub</source>
<translation>GitHub</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="150"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="148"/>
<source>https://github.com/amnezia-vpn/amnezia-client</source>
<translation>https://github.com/amnezia-vpn/amnezia-client</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="161"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="159"/>
<source>Website</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="181"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="179"/>
<source>Software version: %1</source>
<translation>: %1</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="210"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="208"/>
<source>Check for updates</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="233"/>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="231"/>
<source>Privacy Policy</source>
<translation></translation>
</message>
@@ -1975,104 +1849,72 @@ And if you don&apos;t like the app, all the more support it - the donation will
<context>
<name>PageSettingsLogging</name>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="56"/>
<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>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="69"/>
<source>Logging</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="57"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="70"/>
<source>Enabling this function will save application&apos;s logs automatically. By default, logging functionality is disabled. Enable log saving in case of application malfunction.</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="79"/>
<source>Save logs</source>
<translation type="vanished"></translation>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="117"/>
<source>Open folder with logs</source>
<translation type="vanished"></translation>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="171"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="255"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="143"/>
<source>Save</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="256"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="144"/>
<source>Logs files (*.log)</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="181"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="265"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="153"/>
<source>Logs file saved</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="162"/>
<source>Save logs to file</source>
<translation type="vanished"></translation>
<translation></translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="184"/>
<source>Clear logs?</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="94"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="185"/>
<source>Continue</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="95"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="186"/>
<source>Cancel</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="101"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="192"/>
<source>Logs have been cleaned up</source>
<translation></translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="211"/>
<source>Clear logs</source>
<translation></translation>
</message>
@@ -2260,7 +2102,12 @@ And if you don&apos;t like the app, all the more support it - the donation will
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="176"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="135"/>
<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>
<translation type="unfinished"></translation>
</message>
@@ -2270,47 +2117,22 @@ And if you don&apos;t like the app, all the more support it - the donation will
<translation></translation>
</message>
<message>
<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 &quot;connect&quot; 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"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="145"/>
<source>Unable to clear %1 profile while there is an active connection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="224"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="186"/>
<source>Remove </source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="229"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="191"/>
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="236"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="198"/>
<source>Cannot remove active container</source>
<translation type="unfinished"></translation>
</message>
@@ -2323,7 +2145,7 @@ And if you don&apos;t like the app, all the more support it - the donation will
<translation type="obsolete"> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="228"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="190"/>
<source>Remove %1 from server?</source>
<translation> %1 ?</translation>
</message>
@@ -2332,14 +2154,14 @@ And if you don&apos;t like the app, all the more support it - the donation will
<translation type="obsolete"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="178"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="230"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="140"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="192"/>
<source>Continue</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="179"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="231"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="141"/>
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="193"/>
<source>Cancel</source>
<translation></translation>
</message>
@@ -2554,92 +2376,82 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<translation type="unfinished"></translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
<source>Insert the key, add a configuration file or scan the QR-code</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="122"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
<source>Insert key</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="123"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
<source>Insert</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="143"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
<source>Continue</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="161"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
<source>Other connection options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="172"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
<source>VPN by Amnezia</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="173"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
<source>Connect to classic paid and free VPN services from Amnezia</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="196"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
<source>Self-hosted VPN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="197"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
<source>Configure Amnezia VPN on your own server</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="217"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
<source>Restore from backup</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="223"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
<source>Open backup file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="224"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
<source>Backup files (*.backup)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="241"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="198"/>
<source>File with connection settings</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="249"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="206"/>
<source>Open config file</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="268"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="225"/>
<source>QR code</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="291"/>
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
<source>I have nothing</source>
<translation type="unfinished"></translation>
</message>
@@ -2849,7 +2661,7 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="268"/>
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
<source>The port must be in the range of 1 to 65535</source>
<translation type="unfinished"></translation>
</message>
@@ -3265,17 +3077,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation></translation>
</message>
<message>
<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"/>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="143"/>
<source>Connection to </source>
<translation> </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="154"/>
<location filename="../ui/qml/Pages2/PageShareFullAccess.qml" line="144"/>
<source>File with connection settings to </source>
<translation> </translation>
</message>
@@ -3292,11 +3099,6 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<source>Settings restored from backup file</source>
<translation type="unfinished"></translation>
</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>
<name>PopupType</name>
@@ -3335,12 +3137,12 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation></translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="175"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="173"/>
<source>Could not open keystore</source>
<translation></translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="181"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="179"/>
<source>Could not remove private key from keystore</source>
<translation></translation>
</message>
@@ -3516,27 +3318,27 @@ and will not be shared or disclosed to the Amnezia or any third parties</source>
<translation></translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="126"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="124"/>
<source>Could not create private key generator</source>
<translation></translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="133"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="131"/>
<source>Could not generate new private key</source>
<translation></translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="141"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="139"/>
<source>Could not retrieve private key from keystore</source>
<translation></translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="149"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="147"/>
<source>Could not create encryption cipher</source>
<translation></translation>
</message>
<message>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="157"/>
<location filename="../3rd/qtkeychain/qtkeychain/keychain_android.cpp" line="155"/>
<source>Could not encrypt data</source>
<translation></translation>
</message>
@@ -4367,12 +4169,12 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<context>
<name>SettingsController</name>
<message>
<location filename="../ui/controllers/settingsController.cpp" line="152"/>
<location filename="../ui/controllers/settingsController.cpp" line="138"/>
<source>Backup file is corrupted</source>
<translation></translation>
</message>
<message>
<location filename="../ui/controllers/settingsController.cpp" line="174"/>
<location filename="../ui/controllers/settingsController.cpp" line="160"/>
<source>All settings have been reset to default values</source>
<translation></translation>
</message>
@@ -4512,7 +4314,7 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<context>
<name>VpnConnection</name>
<message>
<location filename="../vpnconnection.cpp" line="408"/>
<location filename="../vpnconnection.cpp" line="375"/>
<source>Mbps</source>
<translation></translation>
</message>
@@ -10,6 +10,9 @@
#include "core/controllers/vpnConfigurationController.h"
#include "systemController.h"
#ifdef Q_OS_ANDROID
#include "platforms/android/android_utils.h"
#endif
#include "qrcodegen.hpp"
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
@@ -21,6 +24,12 @@ ExportController::ExportController(const QSharedPointer<ServersModel> &serversMo
m_clientManagementModel(clientManagementModel),
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()
@@ -54,6 +63,26 @@ void ExportController::generateFullAccessConfig()
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)
{
clearPreviousConfig();
+11
View File
@@ -6,6 +6,9 @@
#include "ui/models/clientManagementModel.h"
#include "ui/models/containers_model.h"
#include "ui/models/servers_model.h"
#ifdef Q_OS_ANDROID
#include "platforms/android/authResultReceiver.h"
#endif
class ExportController : public QObject
{
@@ -22,6 +25,9 @@ public:
public slots:
void generateFullAccessConfig();
#if defined(Q_OS_ANDROID)
void generateFullAccessConfigAndroid();
#endif
void generateConnectionConfig(const QString &clientName);
void generateOpenVpnConfig(const QString &clientName);
void generateWireGuardConfig(const QString &clientName);
@@ -68,6 +74,11 @@ private:
QString m_config;
QString m_nativeConfigString;
QList<QString> m_qrCodes;
#ifdef Q_OS_ANDROID
QSharedPointer<AuthResultNotifier> m_authResultNotifier;
QSharedPointer<QAndroidActivityResultReceiver> m_authResultReceiver;
#endif
};
#endif // EXPORTCONTROLLER_H
+35 -76
View File
@@ -4,12 +4,12 @@
#include <QFileInfo>
#include <QQuickItem>
#include <QRandomGenerator>
#include <QStandardPaths>
#include <QUrlQuery>
#include <QStandardPaths>
#include "core/errorstrings.h"
#include "core/serialization/serialization.h"
#include "utilities.h"
#include "core/serialization/serialization.h"
#include "core/errorstrings.h"
#ifdef Q_OS_ANDROID
#include "platforms/android/android_controller.h"
@@ -96,40 +96,36 @@ bool ImportController::extractConfigFromData(QString data)
if (config.startsWith("vless://")) {
m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(
Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
m_config = extractXrayConfig(Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg),
QJsonDocument::JsonFormat::Compact), prefix);
return m_config.empty() ? false : true;
}
if (config.startsWith("vmess://") && config.contains("@")) {
m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(
Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
m_config = extractXrayConfig(Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg),
QJsonDocument::JsonFormat::Compact), prefix);
return m_config.empty() ? false : true;
}
if (config.startsWith("vmess://")) {
m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(
Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
m_config = extractXrayConfig(Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg),
QJsonDocument::JsonFormat::Compact), prefix);
return m_config.empty() ? false : true;
}
if (config.startsWith("trojan://")) {
m_configType = ConfigTypes::Xray;
m_config = extractXrayConfig(
Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
prefix);
m_config = extractXrayConfig(Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg),
QJsonDocument::JsonFormat::Compact), prefix);
return m_config.empty() ? false : true;
}
if (config.startsWith("ss://") && !config.contains("plugin=")) {
m_configType = ConfigTypes::ShadowSocks;
m_config = extractXrayConfig(
Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), prefix);
m_config = extractXrayConfig(Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg),
QJsonDocument::JsonFormat::Compact), prefix);
return m_config.empty() ? false : true;
}
@@ -177,7 +173,6 @@ bool ImportController::extractConfigFromData(QString data)
}
case ConfigTypes::Amnezia: {
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
processAmneziaConfig(m_config);
if (!m_config.empty()) {
checkForMaliciousStrings(m_config);
return true;
@@ -242,26 +237,24 @@ void ImportController::processNativeWireGuardConfig()
auto containers = m_config.value(config_key::containers).toArray();
if (!containers.isEmpty()) {
auto container = containers.at(0).toObject();
auto serverProtocolConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::WireGuard)).toObject();
auto clientProtocolConfig = QJsonDocument::fromJson(serverProtocolConfig.value(config_key::last_config).toString().toUtf8()).object();
auto containerConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::WireGuard)).toObject();
auto protocolConfig = QJsonDocument::fromJson(containerConfig.value(config_key::last_config).toString().toUtf8()).object();
QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(2, 5));
QString junkPacketMinSize = QString::number(10);
QString junkPacketMaxSize = QString::number(50);
clientProtocolConfig[config_key::junkPacketCount] = junkPacketCount;
clientProtocolConfig[config_key::junkPacketMinSize] = junkPacketMinSize;
clientProtocolConfig[config_key::junkPacketMaxSize] = junkPacketMaxSize;
clientProtocolConfig[config_key::initPacketJunkSize] = "0";
clientProtocolConfig[config_key::responsePacketJunkSize] = "0";
clientProtocolConfig[config_key::initPacketMagicHeader] = "1";
clientProtocolConfig[config_key::responsePacketMagicHeader] = "2";
clientProtocolConfig[config_key::underloadPacketMagicHeader] = "3";
clientProtocolConfig[config_key::transportPacketMagicHeader] = "4";
protocolConfig[config_key::junkPacketCount] = junkPacketCount;
protocolConfig[config_key::junkPacketMinSize] = junkPacketMinSize;
protocolConfig[config_key::junkPacketMaxSize] = junkPacketMaxSize;
protocolConfig[config_key::initPacketJunkSize] = "0";
protocolConfig[config_key::responsePacketJunkSize] = "0";
protocolConfig[config_key::initPacketMagicHeader] = "1";
protocolConfig[config_key::responsePacketMagicHeader] = "2";
protocolConfig[config_key::underloadPacketMagicHeader] = "3";
protocolConfig[config_key::transportPacketMagicHeader] = "4";
clientProtocolConfig[config_key::isObfuscationEnabled] = true;
serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(clientProtocolConfig).toJson());
container["wireguard"] = serverProtocolConfig;
containerConfig[config_key::last_config] = QString(QJsonDocument(protocolConfig).toJson());
container["wireguard"] = containerConfig;
containers.replace(0, container);
m_config[config_key::containers] = containers;
}
@@ -360,19 +353,20 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
QJsonObject lastConfig;
lastConfig[config_key::config] = data;
auto url { QUrl::fromUserInput(configMap.value("Endpoint")) };
const static QRegularExpression hostNameAndPortRegExp("Endpoint = (.*):([0-9]*)");
QRegularExpressionMatch hostNameAndPortMatch = hostNameAndPortRegExp.match(data);
QString hostName;
QString port;
if (!url.host().isEmpty()) {
hostName = url.host();
if (hostNameAndPortMatch.hasCaptured(1)) {
hostName = hostNameAndPortMatch.captured(1);
} else {
qDebug() << "Key parameter 'Endpoint' is missing or has an invalid format";
qDebug() << "Key parameter 'Endpoint' is missing";
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
return QJsonObject();
}
if (url.port() != -1) {
port = QString::number(url.port());
if (hostNameAndPortMatch.hasCaptured(2)) {
port = hostNameAndPortMatch.captured(2);
} else {
port = protocols::wireguard::defaultPort;
}
@@ -401,11 +395,7 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
lastConfig[config_key::mtu] = configMap.value("MTU");
}
if (!configMap.value("PersistentKeepalive").isEmpty()) {
lastConfig[config_key::persistent_keep_alive] = configMap.value("PersistentKeepalive");
}
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(", "));
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(","));
lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;
@@ -429,12 +419,6 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
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;
wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson());
wireguardConfig[config_key::isThirdPartyConfig] = true;
@@ -504,7 +488,7 @@ QJsonObject ImportController::extractXrayConfig(const QString &data, const QStri
if (m_configType == ConfigTypes::ShadowSocks) {
config[config_key::defaultContainer] = "amnezia-ssxray";
} else {
config[config_key::defaultContainer] = "amnezia-xray";
config[config_key::defaultContainer] = "amnezia-xray";
}
if (description.isEmpty()) {
config[config_key::description] = m_settings->nextAvailableServerName();
@@ -662,28 +646,3 @@ 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);
}
}
}
-2
View File
@@ -68,8 +68,6 @@ private:
void checkForMaliciousStrings(const QJsonObject &protocolConfig);
void processAmneziaConfig(QJsonObject &config);
#if defined Q_OS_ANDROID || defined Q_OS_IOS
void stopDecodingQr();
#endif
+4 -4
View File
@@ -799,7 +799,7 @@ void InstallController::addEmptyServer()
bool InstallController::fillAvailableServices()
{
ApiController apiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
ApiController apiController(m_settings->getGatewayEndpoint());
QByteArray responseBody;
ErrorCode errorCode = apiController.getServicesList(responseBody);
@@ -821,7 +821,7 @@ bool InstallController::installServiceFromApi()
return false;
}
ApiController apiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
ApiController apiController(m_settings->getGatewayEndpoint());
QJsonObject serverConfig;
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 reloadServiceConfig)
{
ApiController apiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
ApiController apiController(m_settings->getGatewayEndpoint());
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
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)
{
ApiController *apiController = new ApiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
ApiController *apiController = new ApiController(m_settings->getGatewayEndpoint());
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
+22 -3
View File
@@ -10,6 +10,8 @@
#ifdef Q_OS_ANDROID
#include "platforms/android/android_controller.h"
#include "platforms/android/android_utils.h"
#include <QJniObject>
#endif
#if defined Q_OS_MAC
#include "ui/macos_util.h"
@@ -20,8 +22,18 @@ PageController::PageController(const QSharedPointer<ServersModel> &serversModel,
: QObject(parent), m_serversModel(serversModel), m_settings(settings)
{
#ifdef Q_OS_ANDROID
// Change color of navigation and status bar's
auto initialPageNavigationBarColor = getInitialPageNavigationBarColor();
AndroidController::instance()->setNavigationBarColor(initialPageNavigationBarColor);
AndroidUtils::runOnAndroidThreadSync([&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
#if defined Q_OS_MACX
@@ -103,7 +115,14 @@ unsigned int PageController::getInitialPageNavigationBarColor()
void PageController::updateNavigationBarColor(const int color)
{
#ifdef Q_OS_ANDROID
AndroidController::instance()->setNavigationBarColor(color);
// Change color of navigation bar
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
}
@@ -112,7 +131,7 @@ void PageController::showOnStartup()
if (!m_settings->isStartMinimized()) {
emit raiseMainWindow();
} else {
#if defined(Q_OS_WIN) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
#ifdef Q_OS_WIN
emit hideMainWindow();
#elif defined Q_OS_MACX
setDockIconVisible(false);
-3
View File
@@ -59,9 +59,6 @@ namespace PageLoader
PageProtocolIKev2Settings,
PageProtocolRaw,
PageProtocolWireGuardClientSettings,
PageProtocolAwgClientSettings,
PageShareFullAccess,
PageDevMenu
+3 -43
View File
@@ -88,12 +88,7 @@ void SettingsController::toggleLogging(bool enable)
void SettingsController::openLogsFolder()
{
Logger::openLogsFolder(false);
}
void SettingsController::openServiceLogsFolder()
{
Logger::openLogsFolder(true);
Logger::openLogsFolder();
}
void SettingsController::exportLogsFile(const QString &fileName)
@@ -105,21 +100,12 @@ void SettingsController::exportLogsFile(const QString &fileName)
#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()
{
#ifdef Q_OS_ANDROID
AndroidController::instance()->clearLogs();
#else
Logger::clearLogs(false);
Logger::clearLogs();
Logger::clearServiceLogs();
#endif
}
@@ -297,31 +283,5 @@ void SettingsController::setGatewayEndpoint(const QString &endpoint)
QString SettingsController::getGatewayEndpoint()
{
return m_settings->isDevGatewayEnv() ? "Dev endpoint" : m_settings->getGatewayEndpoint();
return 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,7 +27,6 @@ public:
Q_PROPERTY(bool isDevModeEnabled READ isDevModeEnabled NOTIFY devModeEnabled)
Q_PROPERTY(QString gatewayEndpoint READ getGatewayEndpoint WRITE setGatewayEndpoint NOTIFY gatewayEndpointChanged)
Q_PROPERTY(bool isDevGatewayEnv READ isDevGatewayEnv WRITE toggleDevGatewayEnv NOTIFY devGatewayEnvChanged)
public slots:
void toggleAmneziaDns(bool enable);
@@ -43,9 +42,7 @@ public slots:
void toggleLogging(bool enable);
void openLogsFolder();
void openServiceLogsFolder();
void exportLogsFile(const QString &fileName);
void exportServiceLogsFile(const QString &fileName);
void clearLogs();
void backupAppConfig(const QString &fileName);
@@ -84,10 +81,6 @@ public slots:
void resetGatewayEndpoint();
void setGatewayEndpoint(const QString &endpoint);
QString getGatewayEndpoint();
bool isDevGatewayEnv();
void toggleDevGatewayEnv(bool enabled);
bool isOnTv();
signals:
void primaryDnsChanged();
@@ -110,7 +103,6 @@ signals:
void devModeEnabled();
void gatewayEndpointChanged(const QString &endpoint);
void devGatewayEnvChanged(bool enabled);
private:
QSharedPointer<ServersModel> m_serversModel;
@@ -125,12 +125,3 @@ void SystemController::setQmlRoot(QObject *qmlRoot)
{
m_qmlRoot = qmlRoot;
}
bool SystemController::isAuthenticated()
{
#ifdef Q_OS_ANDROID
return AndroidController::instance()->requestAuthentication();
#else
return true;
#endif
}
-1
View File
@@ -19,7 +19,6 @@ public slots:
void setQmlRoot(QObject *qmlRoot);
bool isAuthenticated();
signals:
void fileDialogClosed(const bool isAccepted);
+2 -17
View File
@@ -25,8 +25,6 @@ namespace
constexpr char availableCountries[] = "available_countries";
constexpr char storeEndpoint[] = "store_endpoint";
constexpr char isAvailable[] = "is_available";
}
namespace serviceType
@@ -65,12 +63,8 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
return tr("Classic VPN for comfortable work, downloading large files and watching videos. "
"Works for any sites. Speed up to %1 MBit/s")
.arg(speed);
} else if (serviceType == serviceType::amneziaFree){
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;
} else {
return tr("VPN to access blocked sites in regions with high levels of Internet censorship. ");
}
}
case ServiceDescriptionRole: {
@@ -81,14 +75,6 @@ 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");
}
}
case IsServiceAvailableRole: {
if (serviceType == serviceType::amneziaFree) {
if (service.value(configKey::isAvailable).isBool() && !service.value(configKey::isAvailable).toBool()) {
return false;
}
}
return true;
}
case SpeedRole: {
auto speed = serviceInfo.value(configKey::speed).toString();
return tr("%1 MBit/s").arg(speed);
@@ -207,7 +193,6 @@ QHash<int, QByteArray> ApiServicesModel::roleNames() const
roles[NameRole] = "name";
roles[CardDescriptionRole] = "cardDescription";
roles[ServiceDescriptionRole] = "serviceDescription";
roles[IsServiceAvailableRole] = "isServiceAvailable";
roles[SpeedRole] = "speed";
roles[WorkPeriodRole] = "workPeriod";
roles[RegionRole] = "region";
-1
View File
@@ -13,7 +13,6 @@ public:
NameRole = Qt::UserRole + 1,
CardDescriptionRole,
ServiceDescriptionRole,
IsServiceAvailableRole,
SpeedRole,
WorkPeriodRole,
RegionRole,
+3 -11
View File
@@ -20,7 +20,6 @@ namespace
constexpr char latestHandshake[] = "latestHandshake";
constexpr char dataReceived[] = "dataReceived";
constexpr char dataSent[] = "dataSent";
constexpr char allowedIps[] = "allowedIps";
}
}
@@ -50,7 +49,6 @@ QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
case LatestHandshakeRole: return userData.value(configKey::latestHandshake).toString();
case DataReceivedRole: return userData.value(configKey::dataReceived).toString();
case DataSentRole: return userData.value(configKey::dataSent).toString();
case AllowedIpsRole: return userData.value(configKey::allowedIps).toString();
}
return QVariant();
@@ -143,10 +141,6 @@ ErrorCode ClientManagementModel::updateModel(const DockerContainer container, co
userData[configKey::dataSent] = client.dataSent;
}
if (!client.allowedIps.isEmpty()) {
userData[configKey::allowedIps] = client.allowedIps;
}
obj[configKey::userData] = userData;
m_clientsTable.replace(i, obj);
break;
@@ -272,9 +266,8 @@ ErrorCode ClientManagementModel::wgShow(const DockerContainer container, const S
const auto peerList = parts.filter("peer:");
const auto latestHandshakeList = parts.filter("latest handshake:");
const auto transferredDataList = parts.filter("transfer:");
const auto allowedIpsList = parts.filter("allowed ips:");
if (allowedIpsList.isEmpty() || latestHandshakeList.isEmpty() || transferredDataList.isEmpty() || peerList.isEmpty()) {
if (latestHandshakeList.isEmpty() || transferredDataList.isEmpty() || peerList.isEmpty()) {
return error;
}
@@ -288,20 +281,19 @@ ErrorCode ClientManagementModel::wgShow(const DockerContainer container, const S
}
};
for (int i = 0; i < peerList.size() && i < transferredDataList.size() && i < latestHandshakeList.size() && i < allowedIpsList.size(); ++i) {
for (int i = 0; i < peerList.size() && i < transferredDataList.size() && i < latestHandshakeList.size(); ++i) {
const auto transferredData = getStrValue(transferredDataList[i]).split(",");
auto latestHandshake = getStrValue(latestHandshakeList[i]);
auto serverBytesReceived = transferredData.front().trimmed();
auto serverBytesSent = transferredData.back().trimmed();
auto allowedIps = getStrValue(allowedIpsList[i]);
changeHandshakeFormat(latestHandshake);
serverBytesReceived.chop(QStringLiteral(" received").length());
serverBytesSent.chop(QStringLiteral(" sent").length());
data.push_back({ getStrValue(peerList[i]), latestHandshake, serverBytesSent, serverBytesReceived, allowedIps });
data.push_back({ getStrValue(peerList[i]), latestHandshake, serverBytesSent, serverBytesReceived });
}
return error;
+1 -3
View File
@@ -17,8 +17,7 @@ public:
CreationDateRole,
LatestHandshakeRole,
DataReceivedRole,
DataSentRole,
AllowedIpsRole
DataSentRole
};
struct WgShowData
@@ -27,7 +26,6 @@ public:
QString latestHandshake;
QString dataReceived;
QString dataSent;
QString allowedIps;
};
ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
+82 -136
View File
@@ -21,30 +21,17 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in
}
switch (role) {
case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
case Roles::ClientJunkPacketCountRole: m_clientProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
case Roles::ClientJunkPacketMinSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
case Roles::ClientJunkPacketMaxSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
case Roles::ServerJunkPacketCountRole: m_serverProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
case Roles::ServerJunkPacketMinSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
case Roles::ServerJunkPacketMaxSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMaxSize, 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;
case Roles::PortRole: m_protocolConfig.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::JunkPacketMinSizeRole: m_protocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
case Roles::JunkPacketMaxSizeRole: m_protocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
case Roles::InitPacketJunkSizeRole: m_protocolConfig.insert(config_key::initPacketJunkSize, 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::ResponsePacketMagicHeaderRole: m_protocolConfig.insert(config_key::responsePacketMagicHeader, value.toString()); break;
case Roles::UnderloadPacketMagicHeaderRole: m_protocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString()); break;
case Roles::TransportPacketMagicHeaderRole: m_protocolConfig.insert(config_key::transportPacketMagicHeader, value.toString()); break;
}
emit dataChanged(index, index, QList { role });
@@ -58,22 +45,17 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const
}
switch (role) {
case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
case Roles::ClientJunkPacketCountRole: return m_clientProtocolConfig.value(config_key::junkPacketCount);
case Roles::ClientJunkPacketMinSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMinSize);
case Roles::ClientJunkPacketMaxSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMaxSize);
case Roles::ServerJunkPacketCountRole: return m_serverProtocolConfig.value(config_key::junkPacketCount);
case Roles::ServerJunkPacketMinSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMinSize);
case Roles::ServerJunkPacketMaxSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMaxSize);
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);
case Roles::PortRole: return m_protocolConfig.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::JunkPacketMinSizeRole: return m_protocolConfig.value(config_key::junkPacketMinSize);
case Roles::JunkPacketMaxSizeRole: return m_protocolConfig.value(config_key::junkPacketMaxSize);
case Roles::InitPacketJunkSizeRole: return m_protocolConfig.value(config_key::initPacketJunkSize);
case Roles::ResponsePacketJunkSizeRole: return m_protocolConfig.value(config_key::responsePacketJunkSize);
case Roles::InitPacketMagicHeaderRole: return m_protocolConfig.value(config_key::initPacketMagicHeader);
case Roles::ResponsePacketMagicHeaderRole: return m_protocolConfig.value(config_key::responsePacketMagicHeader);
case Roles::UnderloadPacketMagicHeaderRole: return m_protocolConfig.value(config_key::underloadPacketMagicHeader);
case Roles::TransportPacketMagicHeaderRole: return m_protocolConfig.value(config_key::transportPacketMagicHeader);
}
return QVariant();
@@ -86,63 +68,51 @@ void AwgConfigModel::updateModel(const QJsonObject &config)
m_fullConfig = config;
QJsonObject serverProtocolConfig = config.value(config_key::awg).toObject();
QJsonObject protocolConfig = config.value(config_key::awg).toObject();
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Awg), Proto::Awg);
m_serverProtocolConfig.insert(config_key::transport_proto,
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
m_serverProtocolConfig[config_key::junkPacketCount] =
serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
m_serverProtocolConfig[config_key::junkPacketMinSize] =
serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
m_serverProtocolConfig[config_key::junkPacketMaxSize] =
serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
m_serverProtocolConfig[config_key::initPacketJunkSize] =
serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
m_serverProtocolConfig[config_key::responsePacketJunkSize] =
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
m_serverProtocolConfig[config_key::initPacketMagicHeader] =
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
m_serverProtocolConfig[config_key::responsePacketMagicHeader] =
serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
m_serverProtocolConfig[config_key::underloadPacketMagicHeader] =
serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
m_serverProtocolConfig[config_key::transportPacketMagicHeader] =
serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
m_protocolConfig.insert(config_key::transport_proto, protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config);
m_protocolConfig[config_key::port] = protocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
m_protocolConfig[config_key::mtu] = protocolConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu);
m_protocolConfig[config_key::junkPacketCount] =
protocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
m_protocolConfig[config_key::junkPacketMinSize] =
protocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
m_protocolConfig[config_key::junkPacketMaxSize] =
protocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
m_protocolConfig[config_key::initPacketJunkSize] =
protocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
m_protocolConfig[config_key::responsePacketJunkSize] =
protocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
m_protocolConfig[config_key::initPacketMagicHeader] =
protocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
m_protocolConfig[config_key::responsePacketMagicHeader] =
protocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
m_protocolConfig[config_key::underloadPacketMagicHeader] =
protocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
m_protocolConfig[config_key::transportPacketMagicHeader] =
protocolConfig.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();
}
QJsonObject AwgConfigModel::getConfig()
{
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
const AwgConfig newConfig(m_serverProtocolConfig);
const AwgConfig newConfig(m_protocolConfig);
if (!oldConfig.hasEqualServerSettings(newConfig)) {
m_serverProtocolConfig.remove(config_key::last_config);
m_protocolConfig.remove(config_key::last_config);
} else {
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
auto lastConfig = m_protocolConfig.value(config_key::last_config).toString();
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
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];
jsonConfig[config_key::mtu] = newConfig.mtu;
m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
m_protocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
}
m_fullConfig.insert(config_key::awg, m_serverProtocolConfig);
m_fullConfig.insert(config_key::awg, m_protocolConfig);
return m_fullConfig;
}
@@ -156,73 +126,50 @@ bool AwgConfigModel::isPacketSizeEqual(const int s1, const int 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> roles;
roles[PortRole] = "port";
roles[ClientMtuRole] = "clientMtu";
roles[ClientJunkPacketCountRole] = "clientJunkPacketCount";
roles[ClientJunkPacketMinSizeRole] = "clientJunkPacketMinSize";
roles[ClientJunkPacketMaxSizeRole] = "clientJunkPacketMaxSize";
roles[ServerJunkPacketCountRole] = "serverJunkPacketCount";
roles[ServerJunkPacketMinSizeRole] = "serverJunkPacketMinSize";
roles[ServerJunkPacketMaxSizeRole] = "serverJunkPacketMaxSize";
roles[ServerInitPacketJunkSizeRole] = "serverInitPacketJunkSize";
roles[ServerResponsePacketJunkSizeRole] = "serverResponsePacketJunkSize";
roles[ServerInitPacketMagicHeaderRole] = "serverInitPacketMagicHeader";
roles[ServerResponsePacketMagicHeaderRole] = "serverResponsePacketMagicHeader";
roles[ServerUnderloadPacketMagicHeaderRole] = "serverUnderloadPacketMagicHeader";
roles[ServerTransportPacketMagicHeaderRole] = "serverTransportPacketMagicHeader";
roles[MtuRole] = "mtu";
roles[JunkPacketCountRole] = "junkPacketCount";
roles[JunkPacketMinSizeRole] = "junkPacketMinSize";
roles[JunkPacketMaxSizeRole] = "junkPacketMaxSize";
roles[InitPacketJunkSizeRole] = "initPacketJunkSize";
roles[ResponsePacketJunkSizeRole] = "responsePacketJunkSize";
roles[InitPacketMagicHeaderRole] = "initPacketMagicHeader";
roles[ResponsePacketMagicHeaderRole] = "responsePacketMagicHeader";
roles[UnderloadPacketMagicHeaderRole] = "underloadPacketMagicHeader";
roles[TransportPacketMagicHeaderRole] = "transportPacketMagicHeader";
return roles;
}
AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig)
AwgConfig::AwgConfig(const QJsonObject &jsonConfig)
{
auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString();
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::awg::defaultMtu);
clientJunkPacketCount = clientProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
clientJunkPacketMaxSize = clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
serverJunkPacketCount = serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
serverJunkPacketMinSize = serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
serverJunkPacketMaxSize = serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
serverInitPacketJunkSize = serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
serverResponsePacketJunkSize =
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);
port = jsonConfig.value(config_key::port).toString(protocols::awg::defaultPort);
mtu = jsonConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu);
junkPacketCount = jsonConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
junkPacketMinSize = jsonConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
junkPacketMaxSize = jsonConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
initPacketJunkSize = jsonConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
responsePacketJunkSize = jsonConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
initPacketMagicHeader = jsonConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
responsePacketMagicHeader =
jsonConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
underloadPacketMagicHeader =
jsonConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
transportPacketMagicHeader =
jsonConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
}
bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
{
if (port != other.port || serverJunkPacketCount != other.serverJunkPacketCount
|| serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize
|| serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize
|| serverInitPacketMagicHeader != other.serverInitPacketMagicHeader
|| serverResponsePacketMagicHeader != other.serverResponsePacketMagicHeader
|| serverUnderloadPacketMagicHeader != other.serverUnderloadPacketMagicHeader
|| serverTransportPacketMagicHeader != other.serverTransportPacketMagicHeader) {
if (port != other.port || junkPacketCount != other.junkPacketCount || junkPacketMinSize != other.junkPacketMinSize
|| junkPacketMaxSize != other.junkPacketMaxSize || initPacketJunkSize != other.initPacketJunkSize
|| responsePacketJunkSize != other.responsePacketJunkSize || initPacketMagicHeader != other.initPacketMagicHeader
|| responsePacketMagicHeader != other.responsePacketMagicHeader || underloadPacketMagicHeader != other.underloadPacketMagicHeader
|| transportPacketMagicHeader != other.transportPacketMagicHeader) {
return false;
}
return true;
@@ -230,8 +177,7 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const
{
if (clientMtu != other.clientMtu || clientJunkPacketCount != other.clientJunkPacketCount
|| clientJunkPacketMinSize != other.clientJunkPacketMinSize || clientJunkPacketMaxSize != other.clientJunkPacketMaxSize) {
if (mtu != other.mtu) {
return false;
}
return true;
+21 -34
View File
@@ -16,21 +16,16 @@ struct AwgConfig
AwgConfig(const QJsonObject &jsonConfig);
QString port;
QString clientMtu;
QString clientJunkPacketCount;
QString clientJunkPacketMinSize;
QString clientJunkPacketMaxSize;
QString serverJunkPacketCount;
QString serverJunkPacketMinSize;
QString serverJunkPacketMaxSize;
QString serverInitPacketJunkSize;
QString serverResponsePacketJunkSize;
QString serverInitPacketMagicHeader;
QString serverResponsePacketMagicHeader;
QString serverUnderloadPacketMagicHeader;
QString serverTransportPacketMagicHeader;
QString mtu;
QString junkPacketCount;
QString junkPacketMinSize;
QString junkPacketMaxSize;
QString initPacketJunkSize;
QString responsePacketJunkSize;
QString initPacketMagicHeader;
QString responsePacketMagicHeader;
QString underloadPacketMagicHeader;
QString transportPacketMagicHeader;
bool hasEqualServerSettings(const AwgConfig &other) const;
bool hasEqualClientSettings(const AwgConfig &other) const;
@@ -44,21 +39,16 @@ class AwgConfigModel : public QAbstractListModel
public:
enum Roles {
PortRole = Qt::UserRole + 1,
ClientMtuRole,
ClientJunkPacketCountRole,
ClientJunkPacketMinSizeRole,
ClientJunkPacketMaxSizeRole,
ServerJunkPacketCountRole,
ServerJunkPacketMinSizeRole,
ServerJunkPacketMaxSizeRole,
ServerInitPacketJunkSizeRole,
ServerResponsePacketJunkSizeRole,
ServerInitPacketMagicHeaderRole,
ServerResponsePacketMagicHeaderRole,
ServerUnderloadPacketMagicHeaderRole,
ServerTransportPacketMagicHeaderRole
MtuRole,
JunkPacketCountRole,
JunkPacketMinSizeRole,
JunkPacketMaxSizeRole,
InitPacketJunkSizeRole,
ResponsePacketJunkSizeRole,
InitPacketMagicHeaderRole,
ResponsePacketMagicHeaderRole,
UnderloadPacketMagicHeaderRole,
TransportPacketMagicHeaderRole
};
explicit AwgConfigModel(QObject *parent = nullptr);
@@ -75,15 +65,12 @@ public slots:
bool isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4);
bool isPacketSizeEqual(const int s1, const int s2);
bool isServerSettingsEqual();
protected:
QHash<int, QByteArray> roleNames() const override;
private:
DockerContainer m_container;
QJsonObject m_serverProtocolConfig;
QJsonObject m_clientProtocolConfig;
QJsonObject m_protocolConfig;
QJsonObject m_fullConfig;
};
@@ -21,8 +21,8 @@ bool WireGuardConfigModel::setData(const QModelIndex &index, const QVariant &val
}
switch (role) {
case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break;
}
emit dataChanged(index, index, QList { role });
@@ -36,8 +36,8 @@ QVariant WireGuardConfigModel::data(const QModelIndex &index, int role) const
}
switch (role) {
case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString();
}
return QVariant();
@@ -49,18 +49,17 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
m_fullConfig = config;
QJsonObject serverProtocolConfig = config.value(config_key::wireguard).toObject();
QJsonObject protocolConfig = config.value(config_key::wireguard).toObject();
auto defaultTransportProto =
ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard);
m_serverProtocolConfig.insert(config_key::transport_proto,
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard);
m_protocolConfig.insert(config_key::transport_proto,
protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config);
m_protocolConfig[config_key::port] =
protocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
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::wireguard::defaultMtu);
m_protocolConfig[config_key::mtu] =
protocolConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
endResetModel();
}
@@ -68,47 +67,36 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
QJsonObject WireGuardConfigModel::getConfig()
{
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
const WgConfig newConfig(m_serverProtocolConfig);
const WgConfig newConfig(m_protocolConfig);
if (!oldConfig.hasEqualServerSettings(newConfig)) {
m_serverProtocolConfig.remove(config_key::last_config);
m_protocolConfig.remove(config_key::last_config);
} else {
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
auto lastConfig = m_protocolConfig.value(config_key::last_config).toString();
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu];
jsonConfig[config_key::mtu] = newConfig.mtu;
m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
m_protocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
}
m_fullConfig.insert(config_key::wireguard, m_serverProtocolConfig);
m_fullConfig.insert(config_key::wireguard, m_protocolConfig);
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> roles;
roles[PortRole] = "port";
roles[ClientMtuRole] = "clientMtu";
roles[MtuRole] = "mtu";
return roles;
}
WgConfig::WgConfig(const QJsonObject &serverProtocolConfig)
WgConfig::WgConfig(const QJsonObject &jsonConfig)
{
auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString();
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);
port = jsonConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
mtu = jsonConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
}
bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
@@ -121,7 +109,7 @@ bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
bool WgConfig::hasEqualClientSettings(const WgConfig &other) const
{
if (clientMtu != other.clientMtu) {
if (mtu != other.mtu) {
return false;
}
return true;
@@ -11,7 +11,7 @@ struct WgConfig
WgConfig(const QJsonObject &jsonConfig);
QString port;
QString clientMtu;
QString mtu;
bool hasEqualServerSettings(const WgConfig &other) const;
bool hasEqualClientSettings(const WgConfig &other) const;
@@ -25,7 +25,7 @@ class WireGuardConfigModel : public QAbstractListModel
public:
enum Roles {
PortRole = Qt::UserRole + 1,
ClientMtuRole
MtuRole
};
explicit WireGuardConfigModel(QObject *parent = nullptr);
@@ -39,15 +39,12 @@ public slots:
void updateModel(const QJsonObject &config);
QJsonObject getConfig();
bool isServerSettingsEqual();
protected:
QHash<int, QByteArray> roleNames() const override;
private:
DockerContainer m_container;
QJsonObject m_serverProtocolConfig;
QJsonObject m_clientProtocolConfig;
QJsonObject m_protocolConfig;
QJsonObject m_fullConfig;
};
+4 -26
View File
@@ -16,11 +16,9 @@ QHash<int, QByteArray> ProtocolsModel::roleNames() const
QHash<int, QByteArray> roles;
roles[ProtocolNameRole] = "protocolName";
roles[ServerProtocolPageRole] = "serverProtocolPage";
roles[ClientProtocolPageRole] = "clientProtocolPage";
roles[ProtocolPageRole] = "protocolPage";
roles[ProtocolIndexRole] = "protocolIndex";
roles[RawConfigRole] = "rawConfig";
roles[IsClientProtocolExistsRole] = "isClientProtocolExists";
return roles;
}
@@ -36,10 +34,8 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
amnezia::Proto proto = ProtocolProps::protoFromString(m_content.keys().at(index.row()));
return ProtocolProps::protocolHumanNames().value(proto);
}
case ServerProtocolPageRole:
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 ProtocolPageRole:
return static_cast<int>(protocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
case ProtocolIndexRole: return ProtocolProps::protoFromString(m_content.keys().at(index.row()));
case RawConfigRole: {
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
@@ -54,15 +50,6 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
}
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();
@@ -83,7 +70,7 @@ QJsonObject ProtocolsModel::getConfig()
return config;
}
PageLoader::PageEnum ProtocolsModel::serverProtocolPage(Proto protocol) const
PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const
{
switch (protocol) {
case Proto::OpenVpn: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
@@ -103,12 +90,3 @@ PageLoader::PageEnum ProtocolsModel::serverProtocolPage(Proto protocol) const
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;
}
}
+3 -6
View File
@@ -13,11 +13,9 @@ class ProtocolsModel : public QAbstractListModel
public:
enum Roles {
ProtocolNameRole = Qt::UserRole + 1,
ServerProtocolPageRole,
ClientProtocolPageRole,
ProtocolPageRole,
ProtocolIndexRole,
RawConfigRole,
IsClientProtocolExistsRole
RawConfigRole
};
ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
@@ -35,8 +33,7 @@ protected:
QHash<int, QByteArray> roleNames() const override;
private:
PageLoader::PageEnum serverProtocolPage(Proto protocol) const;
PageLoader::PageEnum clientProtocolPage(Proto protocol) const;
PageLoader::PageEnum protocolPage(Proto protocol) const;
std::shared_ptr<Settings> m_settings;
+27
View File
@@ -0,0 +1,27 @@
#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
+5 -6
View File
@@ -14,7 +14,6 @@ Button {
property string defaultButtonColor: AmneziaStyle.color.paleGray
property string progressButtonColor: AmneziaStyle.color.paleGray
property string connectedButtonColor: AmneziaStyle.color.goldenApricot
property bool buttonActiveFocus: activeFocus && (Qt.platform.os !== "android" || SettingsController.isOnTv())
implicitWidth: 190
implicitHeight: 190
@@ -51,14 +50,14 @@ Button {
verticalOffset: 0
radius: 10
samples: 25
color: root.buttonActiveFocus ? AmneziaStyle.color.paleGray : AmneziaStyle.color.goldenApricot
color: root.activeFocus ? AmneziaStyle.color.paleGray : AmneziaStyle.color.goldenApricot
source: backgroundCircle
}
ShapePath {
fillColor: AmneziaStyle.color.transparent
strokeColor: AmneziaStyle.color.paleGray
strokeWidth: root.buttonActiveFocus ? 1 : 0
strokeWidth: root.activeFocus ? 1 : 0
capStyle: ShapePath.RoundCap
PathAngleArc {
@@ -82,14 +81,14 @@ Button {
return defaultButtonColor
}
}
strokeWidth: root.buttonActiveFocus ? 2 : 3
strokeWidth: root.activeFocus ? 2 : 3
capStyle: ShapePath.RoundCap
PathAngleArc {
centerX: backgroundCircle.width / 2
centerY: backgroundCircle.height / 2
radiusX: 93 - (root.buttonActiveFocus ? 2 : 0)
radiusY: 93 - (root.buttonActiveFocus ? 2 : 0)
radiusX: 93 - (root.activeFocus ? 2 : 0)
radiusY: 93 - (root.activeFocus ? 2 : 0)
startAngle: 0
sweepAngle: 360
}

Some files were not shown because too many files have changed in this diff Show More