mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-22 02:01:08 +07:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dc4573ce75 | |||
| ab6f96bb00 | |||
| 23a8dad37f | |||
| b5c121258a | |||
| 2c45c46a45 | |||
| 70daf4c236 | |||
| 1ece6fe418 | |||
| b075676be6 |
@@ -16,7 +16,6 @@ jobs:
|
|||||||
QT_VERSION: 6.6.2
|
QT_VERSION: 6.6.2
|
||||||
QIF_VERSION: 4.7
|
QIF_VERSION: 4.7
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install Qt'
|
- name: 'Install Qt'
|
||||||
@@ -83,7 +82,6 @@ jobs:
|
|||||||
QIF_VERSION: 4.7
|
QIF_VERSION: 4.7
|
||||||
BUILD_ARCH: 64
|
BUILD_ARCH: 64
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Get sources'
|
- name: 'Get sources'
|
||||||
@@ -146,7 +144,6 @@ jobs:
|
|||||||
CC: cc
|
CC: cc
|
||||||
CXX: c++
|
CXX: c++
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Setup xcode'
|
- name: 'Setup xcode'
|
||||||
@@ -238,7 +235,6 @@ jobs:
|
|||||||
QT_VERSION: 6.4.3
|
QT_VERSION: 6.4.3
|
||||||
QIF_VERSION: 4.6
|
QIF_VERSION: 4.6
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Setup xcode'
|
- name: 'Setup xcode'
|
||||||
@@ -301,25 +297,24 @@ jobs:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
ANDROID_BUILD_PLATFORM: android-34
|
ANDROID_BUILD_PLATFORM: android-34
|
||||||
QT_VERSION: 6.7.2
|
QT_VERSION: 6.6.2
|
||||||
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
|
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install desktop Qt'
|
- name: 'Install desktop Qt'
|
||||||
uses: jurplel/install-qt-action@v4
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
version: ${{ env.QT_VERSION }}
|
version: ${{ env.QT_VERSION }}
|
||||||
host: 'linux'
|
host: 'linux'
|
||||||
target: 'desktop'
|
target: 'desktop'
|
||||||
arch: 'linux_gcc_64'
|
arch: 'gcc_64'
|
||||||
modules: ${{ env.QT_MODULES }}
|
modules: ${{ env.QT_MODULES }}
|
||||||
dir: ${{ runner.temp }}
|
dir: ${{ runner.temp }}
|
||||||
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
||||||
|
|
||||||
- name: 'Install android_x86_64 Qt'
|
- name: 'Install android_x86_64 Qt'
|
||||||
uses: jurplel/install-qt-action@v4
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
version: ${{ env.QT_VERSION }}
|
version: ${{ env.QT_VERSION }}
|
||||||
host: 'linux'
|
host: 'linux'
|
||||||
@@ -330,7 +325,7 @@ jobs:
|
|||||||
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
||||||
|
|
||||||
- name: 'Install android_x86 Qt'
|
- name: 'Install android_x86 Qt'
|
||||||
uses: jurplel/install-qt-action@v4
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
version: ${{ env.QT_VERSION }}
|
version: ${{ env.QT_VERSION }}
|
||||||
host: 'linux'
|
host: 'linux'
|
||||||
@@ -341,7 +336,7 @@ jobs:
|
|||||||
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
||||||
|
|
||||||
- name: 'Install android_armv7 Qt'
|
- name: 'Install android_armv7 Qt'
|
||||||
uses: jurplel/install-qt-action@v4
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
version: ${{ env.QT_VERSION }}
|
version: ${{ env.QT_VERSION }}
|
||||||
host: 'linux'
|
host: 'linux'
|
||||||
@@ -352,7 +347,7 @@ jobs:
|
|||||||
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
||||||
|
|
||||||
- name: 'Install android_arm64_v8a Qt'
|
- name: 'Install android_arm64_v8a Qt'
|
||||||
uses: jurplel/install-qt-action@v4
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
version: ${{ env.QT_VERSION }}
|
version: ${{ env.QT_VERSION }}
|
||||||
host: 'linux'
|
host: 'linux'
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ jobs:
|
|||||||
QT_VERSION: 6.4.1
|
QT_VERSION: 6.4.1
|
||||||
QIF_VERSION: 4.5
|
QIF_VERSION: 4.5
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install desktop Qt'
|
- name: 'Install desktop Qt'
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
|||||||
|
|
||||||
set(PROJECT AmneziaVPN)
|
set(PROJECT AmneziaVPN)
|
||||||
|
|
||||||
project(${PROJECT} VERSION 4.8.0.1
|
project(${PROJECT} VERSION 4.7.0.0
|
||||||
DESCRIPTION "AmneziaVPN"
|
DESCRIPTION "AmneziaVPN"
|
||||||
HOMEPAGE_URL "https://amnezia.org/"
|
HOMEPAGE_URL "https://amnezia.org/"
|
||||||
)
|
)
|
||||||
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
|
|||||||
set(RELEASE_DATE "${CURRENT_DATE}")
|
set(RELEASE_DATE "${CURRENT_DATE}")
|
||||||
|
|
||||||
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
|
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
|
||||||
set(APP_ANDROID_VERSION_CODE 59)
|
set(APP_ANDROID_VERSION_CODE 57)
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
set(MZ_PLATFORM_NAME "linux")
|
set(MZ_PLATFORM_NAME "linux")
|
||||||
|
|||||||
+1
-1
Submodule client/3rd-prebuilt updated: ba580dc5bd...c38a587fcd
Vendored
+1
-1
Submodule client/3rd/qtkeychain updated: 7460df6a97...74776e2a3e
@@ -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_AGW_PUBLIC_KEY="$ENV{PROD_AGW_PUBLIC_KEY}")
|
||||||
add_definitions(-DPROD_PROXY_STORAGE_KEY="$ENV{PROD_PROXY_STORAGE_KEY}")
|
add_definitions(-DPROD_PROXY_STORAGE_KEY="$ENV{PROD_PROXY_STORAGE_KEY}")
|
||||||
|
|
||||||
add_definitions(-DDEV_AGW_PUBLIC_KEY="$ENV{DEV_AGW_PUBLIC_KEY}")
|
|
||||||
add_definitions(-DDEV_AGW_ENDPOINT="$ENV{DEV_AGW_ENDPOINT}")
|
|
||||||
|
|
||||||
if(IOS)
|
if(IOS)
|
||||||
set(PACKAGES ${PACKAGES} Multimedia)
|
set(PACKAGES ${PACKAGES} Multimedia)
|
||||||
endif()
|
endif()
|
||||||
@@ -113,7 +110,6 @@ include(${CMAKE_CURRENT_LIST_DIR}/cmake/3rdparty.cmake)
|
|||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_CURRENT_LIST_DIR}/../ipc
|
${CMAKE_CURRENT_LIST_DIR}/../ipc
|
||||||
${CMAKE_CURRENT_LIST_DIR}/../common/logger
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
@@ -135,6 +131,7 @@ set(HEADERS ${HEADERS}
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h
|
${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.h
|
${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/ui/pages.h
|
${CMAKE_CURRENT_LIST_DIR}/ui/pages.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/ui/property_helper.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.h
|
${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.h
|
${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.h
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/version.h
|
${CMAKE_CURRENT_BINARY_DIR}/version.h
|
||||||
@@ -143,7 +140,6 @@ set(HEADERS ${HEADERS}
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/serialization.h
|
${CMAKE_CURRENT_LIST_DIR}/core/serialization/serialization.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/transfer.h
|
${CMAKE_CURRENT_LIST_DIR}/core/serialization/transfer.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/core/enums/apiEnums.h
|
${CMAKE_CURRENT_LIST_DIR}/core/enums/apiEnums.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Mozilla headres
|
# Mozilla headres
|
||||||
@@ -194,7 +190,6 @@ set(SOURCES ${SOURCES}
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/trojan.cpp
|
${CMAKE_CURRENT_LIST_DIR}/core/serialization/trojan.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess.cpp
|
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess_new.cpp
|
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess_new.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Mozilla sources
|
# Mozilla sources
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ void AmneziaApplication::init()
|
|||||||
bool enabled = m_settings->isSaveLogs();
|
bool enabled = m_settings->isSaveLogs();
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
if (!Logger::init(false)) {
|
if (!Logger::init()) {
|
||||||
qWarning() << "Initialization of debug subsystem failed";
|
qWarning() << "Initialization of debug subsystem failed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<manifest
|
<manifest
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="org.amnezia.vpn"
|
||||||
android:versionName="-- %%INSERT_VERSION_NAME%% --"
|
android:versionName="-- %%INSERT_VERSION_NAME%% --"
|
||||||
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
|
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
@@ -45,7 +46,7 @@
|
|||||||
android:configChanges="uiMode|screenSize|smallestScreenSize|screenLayout|orientation|density
|
android:configChanges="uiMode|screenSize|smallestScreenSize|screenLayout|orientation|density
|
||||||
|fontScale|layoutDirection|locale|keyboard|keyboardHidden|navigation|mcc|mnc"
|
|fontScale|layoutDirection|locale|keyboard|keyboardHidden|navigation|mcc|mnc"
|
||||||
android:launchMode="singleInstance"
|
android:launchMode="singleInstance"
|
||||||
android:windowSoftInputMode="stateUnchanged|adjustResize"
|
android:windowSoftInputMode="adjustResize"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -67,6 +68,9 @@
|
|||||||
android:name="android.app.lib_name"
|
android:name="android.app.lib_name"
|
||||||
android:value="-- %%INSERT_APP_LIB_NAME%% --" />
|
android:value="-- %%INSERT_APP_LIB_NAME%% --" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.app.extract_android_style"
|
||||||
|
android:value="minimal" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
@@ -84,13 +88,6 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/Translucent" />
|
android:theme="@style/Translucent" />
|
||||||
|
|
||||||
<activity android:name=".AuthActivity"
|
|
||||||
android:excludeFromRecents="true"
|
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:taskAffinity=""
|
|
||||||
android:exported="false"
|
|
||||||
android:theme="@style/Translucent" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ImportConfigActivity"
|
android:name=".ImportConfigActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
|
|||||||
@@ -3,6 +3,3 @@
|
|||||||
// android.bundle.enableUncompressedNativeLibs is deprecated
|
// android.bundle.enableUncompressedNativeLibs is deprecated
|
||||||
// disable adding gradle property android.bundle.enableUncompressedNativeLibs by androiddeployqt
|
// disable adding gradle property android.bundle.enableUncompressedNativeLibs by androiddeployqt
|
||||||
useLegacyPackaging
|
useLegacyPackaging
|
||||||
|
|
||||||
// package name for androiddeployqt
|
|
||||||
namespace = "org.amnezia.vpn"
|
|
||||||
|
|||||||
@@ -115,11 +115,9 @@ dependencies {
|
|||||||
implementation(project(":xray"))
|
implementation(project(":xray"))
|
||||||
implementation(libs.androidx.core)
|
implementation(libs.androidx.core)
|
||||||
implementation(libs.androidx.activity)
|
implementation(libs.androidx.activity)
|
||||||
implementation(libs.androidx.fragment)
|
|
||||||
implementation(libs.kotlinx.coroutines)
|
implementation(libs.kotlinx.coroutines)
|
||||||
implementation(libs.kotlinx.serialization.protobuf)
|
implementation(libs.kotlinx.serialization.protobuf)
|
||||||
implementation(libs.bundles.androidx.camera)
|
implementation(libs.bundles.androidx.camera)
|
||||||
implementation(libs.google.mlkit)
|
implementation(libs.google.mlkit)
|
||||||
implementation(libs.androidx.datastore)
|
implementation(libs.androidx.datastore)
|
||||||
implementation(libs.androidx.biometric)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,24 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.5.2"
|
agp = "8.2.0"
|
||||||
kotlin = "1.9.24"
|
kotlin = "1.9.20"
|
||||||
androidx-core = "1.13.1"
|
androidx-core = "1.12.0"
|
||||||
androidx-activity = "1.9.1"
|
androidx-activity = "1.8.1"
|
||||||
androidx-annotation = "1.8.2"
|
androidx-annotation = "1.7.0"
|
||||||
androidx-biometric = "1.2.0-alpha05"
|
androidx-camera = "1.3.0"
|
||||||
androidx-camera = "1.3.4"
|
|
||||||
androidx-fragment = "1.8.2"
|
|
||||||
androidx-security-crypto = "1.1.0-alpha06"
|
androidx-security-crypto = "1.1.0-alpha06"
|
||||||
androidx-datastore = "1.1.1"
|
androidx-datastore = "1.1.0-beta01"
|
||||||
kotlinx-coroutines = "1.8.1"
|
kotlinx-coroutines = "1.7.3"
|
||||||
kotlinx-serialization = "1.6.3"
|
kotlinx-serialization = "1.6.3"
|
||||||
google-mlkit = "17.3.0"
|
google-mlkit = "17.2.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
|
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
|
||||||
androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" }
|
androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" }
|
||||||
androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "androidx-annotation" }
|
androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "androidx-annotation" }
|
||||||
androidx-biometric = { module = "androidx.biometric:biometric-ktx", version.ref = "androidx-biometric" }
|
|
||||||
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "androidx-camera" }
|
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "androidx-camera" }
|
||||||
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "androidx-camera" }
|
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "androidx-camera" }
|
||||||
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "androidx-camera" }
|
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "androidx-camera" }
|
||||||
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "androidx-camera" }
|
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "androidx-camera" }
|
||||||
androidx-fragment = { module = "androidx.fragment:fragment-ktx", version.ref = "androidx-fragment" }
|
|
||||||
androidx-security-crypto = { module = "androidx.security:security-crypto-ktx", version.ref = "androidx-security-crypto" }
|
androidx-security-crypto = { module = "androidx.security:security-crypto-ktx", version.ref = "androidx-security-crypto" }
|
||||||
androidx-datastore = { module = "androidx.datastore:datastore-preferences", version.ref = "androidx-datastore" }
|
androidx-datastore = { module = "androidx.datastore:datastore-preferences", version.ref = "androidx-datastore" }
|
||||||
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
|
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
|
||||||
|
|||||||
Binary file not shown.
+3
-1
@@ -1,5 +1,7 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
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
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
Vendored
+2
-5
@@ -15,8 +15,6 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
#
|
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@@ -57,7 +55,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/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.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@@ -86,8 +84,7 @@ done
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
' "$PWD" ) || exit
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
|||||||
Vendored
+10
-12
@@ -13,8 +13,6 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
@rem SPDX-License-Identifier: Apache-2.0
|
|
||||||
@rem
|
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@@ -45,11 +43,11 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@@ -59,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo. 1>&2
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ open class OpenVpn : Protocol() {
|
|||||||
scope = CoroutineScope(Dispatchers.IO)
|
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()
|
val configBuilder = OpenVpnConfig.Builder()
|
||||||
|
|
||||||
openVpnClient = OpenVpnClient(
|
openVpnClient = OpenVpnClient(
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ abstract class Protocol {
|
|||||||
|
|
||||||
protected abstract fun internalInit()
|
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()
|
abstract fun stopVpn()
|
||||||
|
|
||||||
|
|||||||
@@ -21,5 +21,5 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(fileTree(mapOf("dir" to "../libs", "include" to listOf("*.jar"))))
|
implementation(fileTree(mapOf("dir" to "../libs", "include" to listOf("*.jar"))))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="black">#FF0E0E11</color>
|
|
||||||
<style name="NoActionBar">
|
<style name="NoActionBar">
|
||||||
<item name="android:windowBackground">@color/black</item>
|
|
||||||
<item name="android:colorBackground">@color/black</item>
|
|
||||||
<item name="android:windowActionBar">false</item>
|
<item name="android:windowActionBar">false</item>
|
||||||
<item name="android:windowNoTitle">true</item>
|
<item name="android:windowNoTitle">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ dependencyResolutionManagement {
|
|||||||
includeBuild("./gradle/plugins")
|
includeBuild("./gradle/plugins")
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.settings") version "8.5.2"
|
id("com.android.settings") version "8.2.0"
|
||||||
id("settings-property-delegate")
|
id("settings-property-delegate")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -158,10 +158,6 @@ class AmneziaActivity : QtActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
Log.d(TAG, "Create Amnezia activity: $intent")
|
Log.d(TAG, "Create Amnezia activity: $intent")
|
||||||
window.apply {
|
|
||||||
addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
|
||||||
statusBarColor = getColor(R.color.black)
|
|
||||||
}
|
|
||||||
mainScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
mainScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
||||||
val proto = mainScope.async(Dispatchers.IO) {
|
val proto = mainScope.async(Dispatchers.IO) {
|
||||||
VpnStateStore.getVpnState().vpnProto
|
VpnStateStore.getVpnState().vpnProto
|
||||||
@@ -614,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")
|
@Suppress("unused")
|
||||||
fun minimizeApp() {
|
fun minimizeApp() {
|
||||||
Log.v(TAG, "Minimize application")
|
Log.v(TAG, "Minimize application")
|
||||||
@@ -696,17 +684,6 @@ class AmneziaActivity : QtActivity() {
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
fun requestAuthentication() {
|
|
||||||
Log.v(TAG, "Request authentication")
|
|
||||||
mainScope.launch {
|
|
||||||
qtInitialized.await()
|
|
||||||
Intent(this@AmneziaActivity, AuthActivity::class.java).also {
|
|
||||||
startActivity(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utils methods
|
* Utils methods
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import kotlinx.coroutines.Job
|
|||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.TimeoutCancellationException
|
import kotlinx.coroutines.TimeoutCancellationException
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.cancelAndJoin
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
@@ -112,10 +111,6 @@ open class AmneziaVpnService : VpnService() {
|
|||||||
get() = clientMessengers.any { it.value.name == ACTIVITY_MESSENGER_NAME }
|
get() = clientMessengers.any { it.value.name == ACTIVITY_MESSENGER_NAME }
|
||||||
|
|
||||||
private val connectionExceptionHandler = CoroutineExceptionHandler { _, e ->
|
private val connectionExceptionHandler = CoroutineExceptionHandler { _, e ->
|
||||||
connectionJob?.cancel()
|
|
||||||
connectionJob = null
|
|
||||||
disconnectionJob?.cancel()
|
|
||||||
disconnectionJob = null
|
|
||||||
protocolState.value = DISCONNECTED
|
protocolState.value = DISCONNECTED
|
||||||
when (e) {
|
when (e) {
|
||||||
is IllegalArgumentException,
|
is IllegalArgumentException,
|
||||||
@@ -536,7 +531,7 @@ open class AmneziaVpnService : VpnService() {
|
|||||||
protocolState.value = DISCONNECTING
|
protocolState.value = DISCONNECTING
|
||||||
|
|
||||||
disconnectionJob = connectionScope.launch {
|
disconnectionJob = connectionScope.launch {
|
||||||
connectionJob?.cancelAndJoin()
|
connectionJob?.join()
|
||||||
connectionJob = null
|
connectionJob = null
|
||||||
|
|
||||||
vpnProto?.protocol?.stopVpn()
|
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)
|
intent?.let(::readConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent) {
|
override fun onNewIntent(intent: Intent?) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
Log.d(TAG, "onNewIntent: $intent")
|
Log.d(TAG, "onNewIntent: $intent")
|
||||||
intent.let(::readConfig)
|
intent?.let(::readConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readConfig(intent: Intent) {
|
private fun readConfig(intent: Intent) {
|
||||||
|
|||||||
@@ -25,7 +25,5 @@ object QtAndroidController {
|
|||||||
|
|
||||||
external fun onConfigImported(data: String)
|
external fun onConfigImported(data: String)
|
||||||
|
|
||||||
external fun onAuthResult(result: Boolean)
|
|
||||||
|
|
||||||
external fun decodeQrCode(data: String): Boolean
|
external fun decodeQrCode(data: String): Boolean
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ class NetworkState(
|
|||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
connectivityManager.registerBestMatchingNetworkCallback(networkRequest, networkCallback, handler)
|
connectivityManager.registerBestMatchingNetworkCallback(networkRequest, networkCallback, handler)
|
||||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val numberAttempts = 300
|
val numberAttempts = 3
|
||||||
var attemptCount = 0
|
var attemptCount = 0
|
||||||
while(true) {
|
while(true) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ fun getLocalNetworks(context: Context, ipv6: Boolean): List<InetNetwork> {
|
|||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseInetAddress(address: String): InetAddress = InetAddress.getByName(address)
|
fun parseInetAddress(address: String): InetAddress = parseNumericAddressCompat(address)
|
||||||
|
|
||||||
private val parseNumericAddressCompat: (String) -> InetAddress =
|
private val parseNumericAddressCompat: (String) -> InetAddress =
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
|||||||
+1
-39
@@ -1,12 +1,6 @@
|
|||||||
package org.amnezia.vpn.protocol.wireguard
|
package org.amnezia.vpn.protocol.wireguard
|
||||||
|
|
||||||
import android.net.VpnService.Builder
|
import android.net.VpnService.Builder
|
||||||
import java.io.IOException
|
|
||||||
import java.util.Locale
|
|
||||||
import java.util.TreeMap
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import org.amnezia.awg.GoBackend
|
import org.amnezia.awg.GoBackend
|
||||||
import org.amnezia.vpn.protocol.Protocol
|
import org.amnezia.vpn.protocol.Protocol
|
||||||
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
|
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
|
||||||
@@ -51,44 +45,12 @@ open class Wireguard : Protocol() {
|
|||||||
if (!isInitialized) loadSharedLibrary(context, "wg-go")
|
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 wireguardConfig = parseConfig(config)
|
||||||
val startTime = System.currentTimeMillis()
|
|
||||||
start(wireguardConfig, vpnBuilder, protect)
|
start(wireguardConfig, vpnBuilder, protect)
|
||||||
waitForConnection(startTime)
|
|
||||||
state.value = CONNECTED
|
state.value = CONNECTED
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun waitForConnection(startTime: Long) {
|
|
||||||
Log.d(TAG, "Waiting for connection")
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
val time = String.format(Locale.ROOT,"%.3f", startTime / 1000.0)
|
|
||||||
try {
|
|
||||||
delay(1000)
|
|
||||||
var log = getLogcat(time)
|
|
||||||
Log.d(TAG, "First waiting log: $log")
|
|
||||||
// check that there is a connection log,
|
|
||||||
// to avoid infinite connection
|
|
||||||
if (!log.contains("Attaching to interface")) {
|
|
||||||
Log.w(TAG, "Logs do not contain a connection log")
|
|
||||||
return@withContext
|
|
||||||
}
|
|
||||||
while (!log.contains("Received handshake response")) {
|
|
||||||
delay(1000)
|
|
||||||
log = getLogcat(time)
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
|
||||||
Log.e(TAG, "Failed to get logcat: $e")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getLogcat(time: String): String =
|
|
||||||
ProcessBuilder("logcat", "--buffer=main", "--format=raw", "*:S AmneziaWG/awg0", "-t", time)
|
|
||||||
.redirectErrorStream(true)
|
|
||||||
.start()
|
|
||||||
.inputStream.reader().readText()
|
|
||||||
|
|
||||||
protected open fun parseConfig(config: JSONObject): WireguardConfig {
|
protected open fun parseConfig(config: JSONObject): WireguardConfig {
|
||||||
val configData = config.getJSONObject("wireguard_config_data")
|
val configData = config.getJSONObject("wireguard_config_data")
|
||||||
return WireguardConfig.build {
|
return WireguardConfig.build {
|
||||||
|
|||||||
@@ -46,7 +46,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) {
|
if (isRunning) {
|
||||||
Log.w(TAG, "XRay already running")
|
Log.w(TAG, "XRay already running")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ link_directories(${CMAKE_CURRENT_SOURCE_DIR}/platforms/android)
|
|||||||
set(HEADERS ${HEADERS}
|
set(HEADERS ${HEADERS}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_controller.h
|
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_controller.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_utils.h
|
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_utils.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/authResultReceiver.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/protocols/android_vpnprotocol.h
|
${CMAKE_CURRENT_SOURCE_DIR}/protocols/android_vpnprotocol.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/core/installedAppsImageProvider.h
|
${CMAKE_CURRENT_SOURCE_DIR}/core/installedAppsImageProvider.h
|
||||||
)
|
)
|
||||||
@@ -34,6 +35,7 @@ set(HEADERS ${HEADERS}
|
|||||||
set(SOURCES ${SOURCES}
|
set(SOURCES ${SOURCES}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_controller.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_controller.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_utils.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/android_utils.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/platforms/android/authResultReceiver.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/protocols/android_vpnprotocol.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/protocols/android_vpnprotocol.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/core/installedAppsImageProvider.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/core/installedAppsImageProvider.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ QString WireguardConfigurator::createConfig(const ServerCredentials &credentials
|
|||||||
jConfig[config_key::mtu] = wireguarConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
jConfig[config_key::mtu] = wireguarConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
||||||
|
|
||||||
jConfig[config_key::persistent_keep_alive] = 25;
|
jConfig[config_key::persistent_keep_alive] = 25;
|
||||||
QJsonArray allowedIps { "0.0.0.0/0", "::/0" };
|
QJsonArray allowedIps { "0.0.0.0/0" };
|
||||||
jConfig[config_key::allowed_ips] = allowedIps;
|
jConfig[config_key::allowed_ips] = allowedIps;
|
||||||
|
|
||||||
jConfig[config_key::clientId] = connData.clientPubKey;
|
jConfig[config_key::clientId] = connData.clientPubKey;
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
#include "QRsa.h"
|
#include "QRsa.h"
|
||||||
|
|
||||||
#include "amnezia_application.h"
|
#include "amnezia_application.h"
|
||||||
#include "configurators/wireguard_configurator.h"
|
|
||||||
#include "core/enums/apiEnums.h"
|
#include "core/enums/apiEnums.h"
|
||||||
|
#include "configurators/wireguard_configurator.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -42,7 +42,7 @@ namespace
|
|||||||
constexpr char keyPayload[] = "key_payload";
|
constexpr char keyPayload[] = "key_payload";
|
||||||
}
|
}
|
||||||
|
|
||||||
const QStringList proxyStorageUrl = { "" };
|
const QStringList proxyStorageUrl = {""};
|
||||||
|
|
||||||
ErrorCode checkErrors(const QList<QSslError> &sslErrors, QNetworkReply *reply)
|
ErrorCode checkErrors(const QList<QSslError> &sslErrors, QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
@@ -65,8 +65,7 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiController::ApiController(const QString &gatewayEndpoint, bool isDevEnvironment, QObject *parent)
|
ApiController::ApiController(const QString &gatewayEndpoint, QObject *parent) : QObject(parent), m_gatewayEndpoint(gatewayEndpoint)
|
||||||
: QObject(parent), m_gatewayEndpoint(gatewayEndpoint), m_isDevEnvironment(isDevEnvironment)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +143,7 @@ QStringList ApiController::getProxyUrls()
|
|||||||
|
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
QList<QSslError> sslErrors;
|
QList<QSslError> sslErrors;
|
||||||
QNetworkReply *reply;
|
QNetworkReply* reply;
|
||||||
|
|
||||||
for (const auto &proxyStorageUrl : proxyStorageUrl) {
|
for (const auto &proxyStorageUrl : proxyStorageUrl) {
|
||||||
request.setUrl(proxyStorageUrl);
|
request.setUrl(proxyStorageUrl);
|
||||||
@@ -282,7 +281,7 @@ ErrorCode ApiController::getServicesList(QByteArray &responseBody)
|
|||||||
|
|
||||||
request.setUrl(QString("%1v1/services").arg(m_gatewayEndpoint));
|
request.setUrl(QString("%1v1/services").arg(m_gatewayEndpoint));
|
||||||
|
|
||||||
QNetworkReply *reply;
|
QNetworkReply* reply;
|
||||||
reply = amnApp->manager()->get(request);
|
reply = amnApp->manager()->get(request);
|
||||||
|
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
@@ -301,8 +300,7 @@ ErrorCode ApiController::getServicesList(QByteArray &responseBody)
|
|||||||
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
||||||
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
||||||
wait.exec();
|
wait.exec();
|
||||||
if (reply->error() != QNetworkReply::NetworkError::TimeoutError
|
if (reply->error() != QNetworkReply::NetworkError::TimeoutError && reply->error() != QNetworkReply::NetworkError::OperationCanceledError) {
|
||||||
&& reply->error() != QNetworkReply::NetworkError::OperationCanceledError) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
@@ -357,7 +355,7 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co
|
|||||||
|
|
||||||
EVP_PKEY *publicKey = nullptr;
|
EVP_PKEY *publicKey = nullptr;
|
||||||
try {
|
try {
|
||||||
QByteArray key = m_isDevEnvironment ? DEV_AGW_PUBLIC_KEY : PROD_AGW_PUBLIC_KEY;
|
QByteArray key = PROD_AGW_PUBLIC_KEY;
|
||||||
QSimpleCrypto::QRsa rsa;
|
QSimpleCrypto::QRsa rsa;
|
||||||
publicKey = rsa.getPublicKeyFromByteArray(key);
|
publicKey = rsa.getPublicKeyFromByteArray(key);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@@ -377,7 +375,7 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co
|
|||||||
requestBody[configKey::keyPayload] = QString(encryptedKeyPayload.toBase64());
|
requestBody[configKey::keyPayload] = QString(encryptedKeyPayload.toBase64());
|
||||||
requestBody[configKey::apiPayload] = QString(encryptedApiPayload.toBase64());
|
requestBody[configKey::apiPayload] = QString(encryptedApiPayload.toBase64());
|
||||||
|
|
||||||
QNetworkReply *reply = manager.post(request, QJsonDocument(requestBody).toJson());
|
QNetworkReply* reply = manager.post(request, QJsonDocument(requestBody).toJson());
|
||||||
|
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
||||||
@@ -397,8 +395,7 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co
|
|||||||
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
|
||||||
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
|
||||||
wait.exec();
|
wait.exec();
|
||||||
if (reply->error() != QNetworkReply::NetworkError::TimeoutError
|
if (reply->error() != QNetworkReply::NetworkError::TimeoutError && reply->error() != QNetworkReply::NetworkError::OperationCanceledError) {
|
||||||
&& reply->error() != QNetworkReply::NetworkError::OperationCanceledError) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class ApiController : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ApiController(const QString &gatewayEndpoint, bool isDevEnvironment, QObject *parent = nullptr);
|
explicit ApiController(const QString &gatewayEndpoint, QObject *parent = nullptr);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateServerConfigFromApi(const QString &installationUuid, const int serverIndex, QJsonObject serverConfig);
|
void updateServerConfigFromApi(const QString &installationUuid, const int serverIndex, QJsonObject serverConfig);
|
||||||
@@ -44,7 +44,6 @@ private:
|
|||||||
|
|
||||||
QString m_gatewayEndpoint;
|
QString m_gatewayEndpoint;
|
||||||
QStringList m_proxyUrls;
|
QStringList m_proxyUrls;
|
||||||
bool m_isDevEnvironment = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APICONTROLLER_H
|
#endif // APICONTROLLER_H
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
qDebug().noquote() << lineToExec;
|
qDebug().noquote() << lineToExec;
|
||||||
|
Logger::appendSshLog("Run command:" + lineToExec);
|
||||||
|
|
||||||
error = m_sshClient.executeCommand(lineToExec, cbReadStdOut, cbReadStdErr);
|
error = m_sshClient.executeCommand(lineToExec, cbReadStdOut, cbReadStdErr);
|
||||||
if (error != ErrorCode::NoError) {
|
if (error != ErrorCode::NoError) {
|
||||||
@@ -99,13 +100,13 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
|
|||||||
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
|
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
|
||||||
{
|
{
|
||||||
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
||||||
|
Logger::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + ":\n" + script);
|
||||||
|
|
||||||
ErrorCode e = uploadTextFileToContainer(container, credentials, script, fileName);
|
ErrorCode e = uploadTextFileToContainer(container, credentials, script, fileName);
|
||||||
if (e)
|
if (e)
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
QString runner =
|
QString runner = QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash"));
|
||||||
QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash"));
|
|
||||||
e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
||||||
|
|
||||||
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
|
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
|
||||||
@@ -425,7 +426,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
|||||||
if (errorCode)
|
if (errorCode)
|
||||||
return errorCode;
|
return errorCode;
|
||||||
|
|
||||||
errorCode = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(), dockerFilePath);
|
errorCode = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(),dockerFilePath);
|
||||||
|
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
return errorCode;
|
return errorCode;
|
||||||
@@ -436,8 +437,7 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
|||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
};
|
};
|
||||||
|
|
||||||
errorCode =
|
errorCode = runScript(credentials,
|
||||||
runScript(credentials,
|
|
||||||
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
|
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
|
||||||
cbReadStdOut);
|
cbReadStdOut);
|
||||||
if (errorCode)
|
if (errorCode)
|
||||||
@@ -621,15 +621,13 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
|||||||
|
|
||||||
// Socks5 proxy vars
|
// Socks5 proxy vars
|
||||||
vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } });
|
vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } });
|
||||||
auto username = socks5ProxyConfig.value(config_key::userName).toString();
|
auto username = socks5ProxyConfig.value(config_key:: userName).toString();
|
||||||
auto password = socks5ProxyConfig.value(config_key::password).toString();
|
auto password = socks5ProxyConfig.value(config_key::password).toString();
|
||||||
QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : "";
|
QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : "";
|
||||||
vars.append({ { "$SOCKS5_USER", socks5user } });
|
vars.append({ { "$SOCKS5_USER", socks5user } });
|
||||||
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
|
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
|
||||||
|
|
||||||
QString serverIp = (container != DockerContainer::Awg && container != DockerContainer::WireGuard && container != DockerContainer::Xray)
|
QString serverIp = NetworkUtilities::getIPAddress(credentials.hostName);
|
||||||
? NetworkUtilities::getIPAddress(credentials.hostName)
|
|
||||||
: credentials.hostName;
|
|
||||||
if (!serverIp.isEmpty()) {
|
if (!serverIp.isEmpty()) {
|
||||||
vars.append({ { "$SERVER_IP_ADDRESS", serverIp } });
|
vars.append({ { "$SERVER_IP_ADDRESS", serverIp } });
|
||||||
} else {
|
} else {
|
||||||
@@ -715,8 +713,7 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential
|
|||||||
udpProtoScript.append("' | grep -i udp");
|
udpProtoScript.append("' | grep -i udp");
|
||||||
tcpProtoScript.append(" | grep LISTEN");
|
tcpProtoScript.append(" | grep LISTEN");
|
||||||
|
|
||||||
ErrorCode errorCode =
|
ErrorCode errorCode = runScript(credentials, replaceVars(tcpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
||||||
runScript(credentials, replaceVars(tcpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
|
||||||
if (errorCode != ErrorCode::NoError) {
|
if (errorCode != ErrorCode::NoError) {
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,13 +100,7 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair<QStr
|
|||||||
protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString);
|
protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString);
|
||||||
|
|
||||||
QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
||||||
if (container == DockerContainer::Awg || container == DockerContainer::WireGuard) {
|
vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
|
||||||
// add mtu for old configs
|
|
||||||
if (vpnConfigData[config_key::mtu].toString().isEmpty()) {
|
|
||||||
vpnConfigData[config_key::mtu] = container == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData);
|
vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -109,10 +109,7 @@ QStringList NetworkUtilities::summarizeRoutes(const QStringList &ips, const QStr
|
|||||||
|
|
||||||
QString NetworkUtilities::getIPAddress(const QString &host)
|
QString NetworkUtilities::getIPAddress(const QString &host)
|
||||||
{
|
{
|
||||||
QHostAddress address(host);
|
if (ipAddressRegExp().match(host).hasMatch()) {
|
||||||
if (QAbstractSocket::IPv4Protocol == address.protocol()) {
|
|
||||||
return host;
|
|
||||||
} else if (QAbstractSocket::IPv6Protocol == address.protocol()) {
|
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,18 +4,18 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
|
#include <QJsonDocument>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "utilities.h"
|
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
#include <core/ipcclient.h>
|
#include <core/ipcclient.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_IOS
|
#ifdef Q_OS_IOS
|
||||||
@@ -25,9 +25,8 @@
|
|||||||
QFile Logger::m_file;
|
QFile Logger::m_file;
|
||||||
QTextStream Logger::m_textStream;
|
QTextStream Logger::m_textStream;
|
||||||
QString Logger::m_logFileName = QString("%1.log").arg(APPLICATION_NAME);
|
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()) {
|
if (msg.simplified().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
@@ -38,12 +37,12 @@ void debugMessageHandler(QtMsgType type, const QMessageLogContext &context, cons
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.startsWith("Unknown property") || msg.startsWith("Could not create pixmap") || msg.startsWith("Populating font")
|
if (msg.startsWith("Unknown property") || msg.startsWith("Could not create pixmap") || msg.startsWith("Populating font") || msg.startsWith("stale focus object")) {
|
||||||
|| msg.startsWith("stale focus object")) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::m_textStream << qFormatLogMessage(type, context, msg) << Qt::endl << Qt::flush;
|
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;
|
std::cout << qFormatLogMessage(type, context, msg).toStdString() << std::endl << std::flush;
|
||||||
}
|
}
|
||||||
@@ -54,24 +53,36 @@ Logger &Logger::Instance()
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Logger::init(bool isServiceLogger)
|
void Logger::appendSshLog(const QString &log)
|
||||||
{
|
{
|
||||||
QString path = isServiceLogger ? systemLogDir() : userLogsDir();
|
QString dt = QDateTime::currentDateTime().toString();
|
||||||
QString logFileName = isServiceLogger ? m_serviceLogFileName : m_logFileName ;
|
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);
|
QDir appDir(path);
|
||||||
if (!appDir.mkpath(path)) {
|
if (!appDir.mkpath(path)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_file.setFileName(appDir.filePath(logFileName));
|
m_file.setFileName(appDir.filePath(m_logFileName));
|
||||||
if (!m_file.open(QIODevice::Append)) {
|
if (!m_file.open(QIODevice::Append)) {
|
||||||
qWarning() << "Cannot open log file:" << logFileName;
|
qWarning() << "Cannot open log file:" << m_logFileName;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_file.setTextModeEnabled(true);
|
m_file.setTextModeEnabled(true);
|
||||||
m_textStream.setDevice(&m_file);
|
m_textStream.setDevice(&m_file);
|
||||||
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}");
|
|
||||||
|
|
||||||
#if !defined(QT_DEBUG) || defined(Q_OS_IOS)
|
#if !defined(QT_DEBUG) || defined(Q_OS_IOS)
|
||||||
qInstallMessageHandler(debugMessageHandler);
|
qInstallMessageHandler(debugMessageHandler);
|
||||||
@@ -88,8 +99,7 @@ void Logger::deInit()
|
|||||||
m_file.close();
|
m_file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Logger::setServiceLogsEnabled(bool enabled)
|
bool Logger::setServiceLogsEnabled(bool enabled) {
|
||||||
{
|
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
IpcClient *m_IpcClient = new IpcClient;
|
IpcClient *m_IpcClient = new IpcClient;
|
||||||
|
|
||||||
@@ -102,7 +112,8 @@ bool Logger::setServiceLogsEnabled(bool enabled)
|
|||||||
|
|
||||||
if (m_IpcClient->Interface()) {
|
if (m_IpcClient->Interface()) {
|
||||||
m_IpcClient->Interface()->setLogsEnabled(enabled);
|
m_IpcClient->Interface()->setLogsEnabled(enabled);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
qWarning() << "Error occurred setting up service logs";
|
qWarning() << "Error occurred setting up service logs";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -116,32 +127,11 @@ QString Logger::userLogsDir()
|
|||||||
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/log";
|
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()
|
QString Logger::userLogsFilePath()
|
||||||
{
|
{
|
||||||
return userLogsDir() + QDir::separator() + m_logFileName;
|
return userLogsDir() + QDir::separator() + m_logFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Logger::serviceLogsFilePath()
|
|
||||||
{
|
|
||||||
return systemLogDir() + QDir::separator() + m_serviceLogFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Logger::getLogFile()
|
QString Logger::getLogFile()
|
||||||
{
|
{
|
||||||
m_file.flush();
|
m_file.flush();
|
||||||
@@ -155,26 +145,12 @@ QString Logger::getLogFile()
|
|||||||
#else
|
#else
|
||||||
return qtLog;
|
return qtLog;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Logger::getServiceLogFile()
|
bool Logger::openLogsFolder()
|
||||||
{
|
{
|
||||||
m_file.flush();
|
QString path = userLogsDir();
|
||||||
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();
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
path = "file:///" + path;
|
path = "file:///" + path;
|
||||||
#endif
|
#endif
|
||||||
@@ -185,12 +161,27 @@ bool Logger::openLogsFolder(bool isServiceLogger)
|
|||||||
return true;
|
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();
|
bool isLogActive = m_file.isOpen();
|
||||||
m_file.close();
|
m_file.close();
|
||||||
|
|
||||||
QFile file(isServiceLogger ? serviceLogsFilePath() : userLogsFilePath());
|
QFile file(userLogsFilePath());
|
||||||
|
|
||||||
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||||
file.resize(0);
|
file.resize(0);
|
||||||
@@ -201,7 +192,7 @@ void Logger::clearLogs(bool isServiceLogger)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (isLogActive) {
|
if (isLogActive) {
|
||||||
init(isServiceLogger);
|
init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +210,8 @@ void Logger::clearServiceLogs()
|
|||||||
|
|
||||||
if (m_IpcClient->Interface()) {
|
if (m_IpcClient->Interface()) {
|
||||||
m_IpcClient->Interface()->clearLogs();
|
m_IpcClient->Interface()->clearLogs();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
qWarning() << "Error occurred cleaning up service logs";
|
qWarning() << "Error occurred cleaning up service logs";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -227,41 +219,26 @@ void Logger::clearServiceLogs()
|
|||||||
|
|
||||||
void Logger::cleanUp()
|
void Logger::cleanUp()
|
||||||
{
|
{
|
||||||
clearLogs(false);
|
clearLogs();
|
||||||
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
||||||
dir.removeRecursively();
|
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();
|
qDebug() << "Amnezia" << m_logger->className() << m_data->m_buffer.trimmed();
|
||||||
delete m_data;
|
delete m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::Log Logger::error()
|
Logger::Log Logger::error() { return Log(this, LogLevel::Error); }
|
||||||
{
|
Logger::Log Logger::warning() { return Log(this, LogLevel::Warning); }
|
||||||
return Log(this, LogLevel::Error);
|
Logger::Log Logger::info() { return Log(this, LogLevel::Info); }
|
||||||
}
|
Logger::Log Logger::debug() { return Log(this, LogLevel::Debug); }
|
||||||
Logger::Log Logger::warning()
|
QString Logger::sensitive(const QString& input) {
|
||||||
{
|
|
||||||
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
|
#ifdef Q_DEBUG
|
||||||
return input;
|
return input;
|
||||||
#else
|
#else
|
||||||
@@ -270,51 +247,48 @@ QString Logger::sensitive(const QString &input)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define CREATE_LOG_OP_REF(x) \
|
#define CREATE_LOG_OP_REF(x) \
|
||||||
Logger::Log &Logger::Log::operator<<(x t) \
|
Logger::Log& Logger::Log::operator<<(x t) { \
|
||||||
{ \
|
|
||||||
m_data->m_ts << t << ' '; \
|
m_data->m_ts << t << ' '; \
|
||||||
return *this; \
|
return *this; \
|
||||||
}
|
}
|
||||||
|
|
||||||
CREATE_LOG_OP_REF(uint64_t);
|
CREATE_LOG_OP_REF(uint64_t);
|
||||||
CREATE_LOG_OP_REF(const char *);
|
CREATE_LOG_OP_REF(const char*);
|
||||||
CREATE_LOG_OP_REF(const QString &);
|
CREATE_LOG_OP_REF(const QString&);
|
||||||
CREATE_LOG_OP_REF(const QByteArray &);
|
CREATE_LOG_OP_REF(const QByteArray&);
|
||||||
CREATE_LOG_OP_REF(const void *);
|
CREATE_LOG_OP_REF(const void*);
|
||||||
|
|
||||||
#undef CREATE_LOG_OP_REF
|
#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(",") << ']' << ' ';
|
m_data->m_ts << '[' << t.join(",") << ']' << ' ';
|
||||||
return *this;
|
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) << ' ';
|
m_data->m_ts << QJsonDocument(t).toJson(QJsonDocument::Indented) << ' ';
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::Log &Logger::Log::operator<<(QTextStreamFunction t)
|
Logger::Log& Logger::Log::operator<<(QTextStreamFunction t) {
|
||||||
{
|
|
||||||
m_data->m_ts << t;
|
m_data->m_ts << t;
|
||||||
return *this;
|
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));
|
QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
|
||||||
|
|
||||||
QString out;
|
QString out;
|
||||||
QTextStream ts(&out);
|
QTextStream ts(&out);
|
||||||
|
|
||||||
if (const char *scope = me.scope()) {
|
if (const char* scope = me.scope()) {
|
||||||
ts << 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();
|
const bool scoped = me.isScoped();
|
||||||
if (scoped || !key) {
|
if (scoped || !key) {
|
||||||
ts << me.enumName() << (!key ? "(" : "::");
|
ts << me.enumName() << (!key ? "(" : "::");
|
||||||
+107
@@ -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
|
||||||
@@ -149,9 +149,13 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
|||||||
QJsonArray jsAllowedIPAddesses;
|
QJsonArray jsAllowedIPAddesses;
|
||||||
|
|
||||||
QJsonArray plainAllowedIP = wgConfig.value(amnezia::config_key::allowed_ips).toArray();
|
QJsonArray plainAllowedIP = wgConfig.value(amnezia::config_key::allowed_ips).toArray();
|
||||||
QJsonArray defaultAllowedIP = { "0.0.0.0/0", "::/0" };
|
|
||||||
|
|
||||||
if (plainAllowedIP != defaultAllowedIP && !plainAllowedIP.isEmpty()) {
|
bool allowSplitTunnelFromAppSettings = false;
|
||||||
|
if (!plainAllowedIP.isEmpty() && plainAllowedIP.contains("0.0.0.0/0")) {
|
||||||
|
allowSplitTunnelFromAppSettings = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allowSplitTunnelFromAppSettings) {
|
||||||
// Use AllowedIP list from WG config because of higher priority
|
// Use AllowedIP list from WG config because of higher priority
|
||||||
for (auto v : plainAllowedIP) {
|
for (auto v : plainAllowedIP) {
|
||||||
QString ipRange = v.toString();
|
QString ipRange = v.toString();
|
||||||
@@ -170,7 +174,6 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Use APP split tunnel
|
// Use APP split tunnel
|
||||||
if (splitTunnelType == 0 || splitTunnelType == 2) {
|
if (splitTunnelType == 0 || splitTunnelType == 2) {
|
||||||
QJsonObject range_ipv4;
|
QJsonObject range_ipv4;
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ bool AndroidController::initialize()
|
|||||||
{"onStatisticsUpdate", "(JJ)V", reinterpret_cast<void *>(onStatisticsUpdate)},
|
{"onStatisticsUpdate", "(JJ)V", reinterpret_cast<void *>(onStatisticsUpdate)},
|
||||||
{"onFileOpened", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onFileOpened)},
|
{"onFileOpened", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onFileOpened)},
|
||||||
{"onConfigImported", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onConfigImported)},
|
{"onConfigImported", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onConfigImported)},
|
||||||
{"onAuthResult", "(Z)V", reinterpret_cast<void *>(onAuthResult)},
|
|
||||||
{"decodeQrCode", "(Ljava/lang/String;)Z", reinterpret_cast<bool *>(decodeQrCode)}
|
{"decodeQrCode", "(Ljava/lang/String;)Z", reinterpret_cast<bool *>(decodeQrCode)}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -211,11 +210,6 @@ void AndroidController::setScreenshotsEnabled(bool enabled)
|
|||||||
callActivityMethod("setScreenshotsEnabled", "(Z)V", enabled);
|
callActivityMethod("setScreenshotsEnabled", "(Z)V", enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidController::setNavigationBarColor(unsigned int color)
|
|
||||||
{
|
|
||||||
callActivityMethod("setNavigationBarColor", "(I)V", color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AndroidController::minimizeApp()
|
void AndroidController::minimizeApp()
|
||||||
{
|
{
|
||||||
callActivityMethod("minimizeApp", "()V");
|
callActivityMethod("minimizeApp", "()V");
|
||||||
@@ -271,22 +265,6 @@ void AndroidController::requestNotificationPermission()
|
|||||||
callActivityMethod("requestNotificationPermission", "()V");
|
callActivityMethod("requestNotificationPermission", "()V");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidController::requestAuthentication()
|
|
||||||
{
|
|
||||||
QEventLoop wait;
|
|
||||||
bool result;
|
|
||||||
connect(this, &AndroidController::authenticationResult, this,
|
|
||||||
[&result, &wait](const bool &authResult){
|
|
||||||
qDebug() << "Android authentication result:" << authResult;
|
|
||||||
result = authResult;
|
|
||||||
wait.quit();
|
|
||||||
},
|
|
||||||
static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::SingleShotConnection));
|
|
||||||
callActivityMethod("requestAuthentication", "()V");
|
|
||||||
wait.exec();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Moving log processing to the Android side
|
// Moving log processing to the Android side
|
||||||
jclass AndroidController::log;
|
jclass AndroidController::log;
|
||||||
jmethodID AndroidController::logDebug;
|
jmethodID AndroidController::logDebug;
|
||||||
@@ -484,14 +462,6 @@ void AndroidController::onConfigImported(JNIEnv *env, jobject thiz, jstring data
|
|||||||
emit AndroidController::instance()->configImported(AndroidUtils::convertJString(env, data));
|
emit AndroidController::instance()->configImported(AndroidUtils::convertJString(env, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
void AndroidController::onAuthResult(JNIEnv *env, jobject thiz, jboolean result)
|
|
||||||
{
|
|
||||||
Q_UNUSED(thiz);
|
|
||||||
|
|
||||||
emit AndroidController::instance()->authenticationResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool AndroidController::decodeQrCode(JNIEnv *env, jobject thiz, jstring data)
|
bool AndroidController::decodeQrCode(JNIEnv *env, jobject thiz, jstring data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,13 +41,11 @@ public:
|
|||||||
void exportLogsFile(const QString &fileName);
|
void exportLogsFile(const QString &fileName);
|
||||||
void clearLogs();
|
void clearLogs();
|
||||||
void setScreenshotsEnabled(bool enabled);
|
void setScreenshotsEnabled(bool enabled);
|
||||||
void setNavigationBarColor(unsigned int color);
|
|
||||||
void minimizeApp();
|
void minimizeApp();
|
||||||
QJsonArray getAppList();
|
QJsonArray getAppList();
|
||||||
QPixmap getAppIcon(const QString &package, QSize *size, const QSize &requestedSize);
|
QPixmap getAppIcon(const QString &package, QSize *size, const QSize &requestedSize);
|
||||||
bool isNotificationPermissionGranted();
|
bool isNotificationPermissionGranted();
|
||||||
void requestNotificationPermission();
|
void requestNotificationPermission();
|
||||||
bool requestAuthentication();
|
|
||||||
|
|
||||||
static bool initLogging();
|
static bool initLogging();
|
||||||
static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message);
|
static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message);
|
||||||
@@ -65,7 +63,6 @@ signals:
|
|||||||
void configImported(QString config);
|
void configImported(QString config);
|
||||||
void importConfigFromOutside(QString config);
|
void importConfigFromOutside(QString config);
|
||||||
void initConnectionState(Vpn::ConnectionState state);
|
void initConnectionState(Vpn::ConnectionState state);
|
||||||
void authenticationResult(bool result);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isWaitingStatus = true;
|
bool isWaitingStatus = true;
|
||||||
@@ -92,7 +89,6 @@ private:
|
|||||||
static void onStatisticsUpdate(JNIEnv *env, jobject thiz, jlong rxBytes, jlong txBytes);
|
static void onStatisticsUpdate(JNIEnv *env, jobject thiz, jlong rxBytes, jlong txBytes);
|
||||||
static void onConfigImported(JNIEnv *env, jobject thiz, jstring data);
|
static void onConfigImported(JNIEnv *env, jobject thiz, jstring data);
|
||||||
static void onFileOpened(JNIEnv *env, jobject thiz, jstring uri);
|
static void onFileOpened(JNIEnv *env, jobject thiz, jstring uri);
|
||||||
static void onAuthResult(JNIEnv *env, jobject thiz, jboolean result);
|
|
||||||
static bool decodeQrCode(JNIEnv *env, jobject thiz, jstring data);
|
static bool decodeQrCode(JNIEnv *env, jobject thiz, jstring data);
|
||||||
|
|
||||||
template <typename Ret, typename ...Args>
|
template <typename Ret, typename ...Args>
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#include "authResultReceiver.h"
|
||||||
|
|
||||||
|
AuthResultReceiver::AuthResultReceiver(QSharedPointer<AuthResultNotifier> ¬ifier) : m_notifier(notifier)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AuthResultReceiver::handleActivityResult(int receiverRequestCode, int resultCode, const QJniObject &data)
|
||||||
|
{
|
||||||
|
qDebug() << "receiverRequestCode" << receiverRequestCode << "resultCode" << resultCode;
|
||||||
|
|
||||||
|
if (resultCode == -1) { // ResultOK
|
||||||
|
emit m_notifier->authSuccessful();
|
||||||
|
} else {
|
||||||
|
emit m_notifier->authFailed();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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> ¬ifier);
|
||||||
|
|
||||||
|
void handleActivityResult(int receiverRequestCode, int resultCode, const QJniObject &data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSharedPointer<AuthResultNotifier> m_notifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // AUTHRESULTRECEIVER_H
|
||||||
@@ -22,7 +22,7 @@ extension PacketTunnelProvider {
|
|||||||
|
|
||||||
if tunnelConfiguration.peers.first!.allowedIPs
|
if tunnelConfiguration.peers.first!.allowedIPs
|
||||||
.map({ $0.stringRepresentation })
|
.map({ $0.stringRepresentation })
|
||||||
.joined(separator: ", ") == "0.0.0.0/0, ::/0" {
|
.contains("0.0.0.0/0") {
|
||||||
if wgConfig.splitTunnelType == 1 {
|
if wgConfig.splitTunnelType == 1 {
|
||||||
for index in tunnelConfiguration.peers.indices {
|
for index in tunnelConfiguration.peers.indices {
|
||||||
tunnelConfiguration.peers[index].allowedIPs.removeAll()
|
tunnelConfiguration.peers[index].allowedIPs.removeAll()
|
||||||
|
|||||||
@@ -351,6 +351,8 @@ void IosController::vpnStatusDidChange(void *pNotification)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "Disconnect error is absent";
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
@@ -489,7 +491,7 @@ bool IosController::setupWireGuard()
|
|||||||
if (config.contains(config_key::allowed_ips) && config[config_key::allowed_ips].isArray()) {
|
if (config.contains(config_key::allowed_ips) && config[config_key::allowed_ips].isArray()) {
|
||||||
wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]);
|
wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]);
|
||||||
} else {
|
} else {
|
||||||
QJsonArray allowed_ips { "0.0.0.0/0", "::/0" };
|
QJsonArray allowed_ips { "0.0.0.0/0" };
|
||||||
wgConfig.insert(config_key::allowed_ips, allowed_ips);
|
wgConfig.insert(config_key::allowed_ips, allowed_ips);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,7 +576,7 @@ bool IosController::setupAwg()
|
|||||||
if (config.contains(config_key::allowed_ips) && config[config_key::allowed_ips].isArray()) {
|
if (config.contains(config_key::allowed_ips) && config[config_key::allowed_ips].isArray()) {
|
||||||
wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]);
|
wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]);
|
||||||
} else {
|
} else {
|
||||||
QJsonArray allowed_ips { "0.0.0.0/0", "::/0" };
|
QJsonArray allowed_ips { "0.0.0.0/0" };
|
||||||
wgConfig.insert(config_key::allowed_ips, allowed_ips);
|
wgConfig.insert(config_key::allowed_ips, allowed_ips);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -833,7 +835,7 @@ QString IosController::openFile() {
|
|||||||
|
|
||||||
void IosController::requestInetAccess() {
|
void IosController::requestInetAccess() {
|
||||||
NSURL *url = [NSURL URLWithString:@"http://captive.apple.com/generate_204"];
|
NSURL *url = [NSURL URLWithString:@"http://captive.apple.com/generate_204"];
|
||||||
if (!url) {
|
if (url) {
|
||||||
qDebug() << "IosController::requestInetAccess URL error";
|
qDebug() << "IosController::requestInetAccess URL error";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -845,6 +847,7 @@ void IosController::requestInetAccess() {
|
|||||||
} else {
|
} else {
|
||||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
|
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
|
||||||
QString responseBody = QString::fromUtf8((const char*)data.bytes, data.length);
|
QString responseBody = QString::fromUtf8((const char*)data.bytes, data.length);
|
||||||
|
qDebug() << "IosController::requestInetAccess server response:" << httpResponse.statusCode << "\n\n" <<responseBody;
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
[task resume];
|
[task resume];
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
#include "utilities.h"
|
||||||
#include "wireguardprotocol.h"
|
#include "wireguardprotocol.h"
|
||||||
#include "core/networkUtilities.h"
|
|
||||||
|
|
||||||
#include "mozilla/localsocketcontroller.h"
|
#include "mozilla/localsocketcontroller.h"
|
||||||
|
|
||||||
@@ -36,12 +37,6 @@ void WireguardProtocol::stop()
|
|||||||
|
|
||||||
ErrorCode WireguardProtocol::startMzImpl()
|
ErrorCode WireguardProtocol::startMzImpl()
|
||||||
{
|
{
|
||||||
QString protocolName = m_rawConfig.value("protocol").toString();
|
|
||||||
QJsonObject vpnConfigData = m_rawConfig.value(protocolName + "_config_data").toObject();
|
|
||||||
vpnConfigData[config_key::hostName] = NetworkUtilities::getIPAddress(vpnConfigData.value(config_key::hostName).toString());
|
|
||||||
m_rawConfig.insert(protocolName + "_config_data", vpnConfigData);
|
|
||||||
m_rawConfig[config_key::hostName] = NetworkUtilities::getIPAddress(m_rawConfig[config_key::hostName].toString());
|
|
||||||
|
|
||||||
m_impl->activate(m_rawConfig);
|
m_impl->activate(m_rawConfig);
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,9 +43,7 @@ ErrorCode XrayProtocol::start()
|
|||||||
m_xrayCfgFile.setAutoRemove(false);
|
m_xrayCfgFile.setAutoRemove(false);
|
||||||
#endif
|
#endif
|
||||||
m_xrayCfgFile.open();
|
m_xrayCfgFile.open();
|
||||||
QString config = QJsonDocument(m_xrayConfig).toJson();
|
m_xrayCfgFile.write(QJsonDocument(m_xrayConfig).toJson());
|
||||||
config.replace(m_remoteHost, m_remoteAddress);
|
|
||||||
m_xrayCfgFile.write(config.toUtf8());
|
|
||||||
m_xrayCfgFile.close();
|
m_xrayCfgFile.close();
|
||||||
|
|
||||||
QStringList args = QStringList() << "-c" << m_xrayCfgFile.fileName() << "-format=json";
|
QStringList args = QStringList() << "-c" << m_xrayCfgFile.fileName() << "-format=json";
|
||||||
@@ -240,8 +238,7 @@ void XrayProtocol::readXrayConfiguration(const QJsonObject &configuration)
|
|||||||
}
|
}
|
||||||
m_xrayConfig = xrayConfiguration;
|
m_xrayConfig = xrayConfiguration;
|
||||||
m_localPort = QString(amnezia::protocols::xray::defaultLocalProxyPort).toInt();
|
m_localPort = QString(amnezia::protocols::xray::defaultLocalProxyPort).toInt();
|
||||||
m_remoteHost = configuration.value(amnezia::config_key::hostName).toString();
|
m_remoteAddress = configuration.value(amnezia::config_key::hostName).toString();
|
||||||
m_remoteAddress = NetworkUtilities::getIPAddress(m_remoteHost);
|
|
||||||
m_routeMode = configuration.value(amnezia::config_key::splitTunnelType).toInt();
|
m_routeMode = configuration.value(amnezia::config_key::splitTunnelType).toInt();
|
||||||
m_primaryDNS = configuration.value(amnezia::config_key::dns1).toString();
|
m_primaryDNS = configuration.value(amnezia::config_key::dns1).toString();
|
||||||
m_secondaryDNS = configuration.value(amnezia::config_key::dns2).toString();
|
m_secondaryDNS = configuration.value(amnezia::config_key::dns2).toString();
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ private:
|
|||||||
static QString tun2SocksExecPath();
|
static QString tun2SocksExecPath();
|
||||||
private:
|
private:
|
||||||
int m_localPort;
|
int m_localPort;
|
||||||
QString m_remoteHost;
|
|
||||||
QString m_remoteAddress;
|
QString m_remoteAddress;
|
||||||
int m_routeMode;
|
int m_routeMode;
|
||||||
QJsonObject m_configData;
|
QJsonObject m_configData;
|
||||||
|
|||||||
@@ -199,8 +199,6 @@
|
|||||||
<file>server_scripts/socks5_proxy/Dockerfile</file>
|
<file>server_scripts/socks5_proxy/Dockerfile</file>
|
||||||
<file>server_scripts/socks5_proxy/configure_container.sh</file>
|
<file>server_scripts/socks5_proxy/configure_container.sh</file>
|
||||||
<file>server_scripts/socks5_proxy/start.sh</file>
|
<file>server_scripts/socks5_proxy/start.sh</file>
|
||||||
<file>ui/qml/Pages2/PageProtocolAwgClientSettings.qml</file>
|
|
||||||
<file>ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml</file>
|
|
||||||
<file>ui/qml/Pages2/PageSetupWizardApiServicesList.qml</file>
|
<file>ui/qml/Pages2/PageSetupWizardApiServicesList.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml</file>
|
<file>ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml</file>
|
||||||
<file>ui/qml/Controls2/CardWithIconsType.qml</file>
|
<file>ui/qml/Controls2/CardWithIconsType.qml</file>
|
||||||
|
|||||||
@@ -174,25 +174,13 @@ bool SecureQSettings::restoreAppConfig(const QByteArray &json)
|
|||||||
QByteArray SecureQSettings::encryptText(const QByteArray &value) const
|
QByteArray SecureQSettings::encryptText(const QByteArray &value) const
|
||||||
{
|
{
|
||||||
QSimpleCrypto::QBlockCipher cipher;
|
QSimpleCrypto::QBlockCipher cipher;
|
||||||
QByteArray result;
|
return cipher.encryptAesBlockCipher(value, getEncKey(), getEncIv());
|
||||||
try {
|
|
||||||
result = cipher.encryptAesBlockCipher(value, getEncKey(), getEncIv());
|
|
||||||
} catch (...) { // todo change error handling in QSimpleCrypto?
|
|
||||||
qCritical() << "error when encrypting the settings value";
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray SecureQSettings::decryptText(const QByteArray &ba) const
|
QByteArray SecureQSettings::decryptText(const QByteArray &ba) const
|
||||||
{
|
{
|
||||||
QSimpleCrypto::QBlockCipher cipher;
|
QSimpleCrypto::QBlockCipher cipher;
|
||||||
QByteArray result;
|
return cipher.decryptAesBlockCipher(ba, getEncKey(), getEncIv());
|
||||||
try {
|
|
||||||
result = cipher.decryptAesBlockCipher(ba, getEncKey(), getEncIv());
|
|
||||||
} catch (...) { // todo change error handling in QSimpleCrypto?
|
|
||||||
qCritical() << "error when decrypting the settings value";
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SecureQSettings::encryptionRequired() const
|
bool SecureQSettings::encryptionRequired() const
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ H4 = $TRANSPORT_PACKET_MAGIC_HEADER
|
|||||||
[Peer]
|
[Peer]
|
||||||
PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY
|
PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY
|
||||||
PresharedKey = $WIREGUARD_PSK
|
PresharedKey = $WIREGUARD_PSK
|
||||||
AllowedIPs = 0.0.0.0/0, ::/0
|
AllowedIPs = 0.0.0.0/0
|
||||||
Endpoint = $SERVER_IP_ADDRESS:$AWG_SERVER_PORT
|
Endpoint = $SERVER_IP_ADDRESS:$AWG_SERVER_PORT
|
||||||
PersistentKeepalive = 25
|
PersistentKeepalive = 25
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ PrivateKey = $WIREGUARD_CLIENT_PRIVATE_KEY
|
|||||||
[Peer]
|
[Peer]
|
||||||
PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY
|
PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY
|
||||||
PresharedKey = $WIREGUARD_PSK
|
PresharedKey = $WIREGUARD_PSK
|
||||||
AllowedIPs = 0.0.0.0/0, ::/0
|
AllowedIPs = 0.0.0.0/0
|
||||||
Endpoint = $SERVER_IP_ADDRESS:$WIREGUARD_SERVER_PORT
|
Endpoint = $SERVER_IP_ADDRESS:$WIREGUARD_SERVER_PORT
|
||||||
PersistentKeepalive = 25
|
PersistentKeepalive = 25
|
||||||
|
|||||||
@@ -13,5 +13,5 @@ sudo docker network connect amnezia-dns-net $CONTAINER_NAME
|
|||||||
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi'
|
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi'
|
||||||
|
|
||||||
# Prevent to route packets outside of the container in case if server behind of the NAT
|
# Prevent to route packets outside of the container in case if server behind of the NAT
|
||||||
#sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||||
|
|
||||||
echo "Container startup"
|
echo "Container startup"
|
||||||
#ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
|
ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
|
||||||
|
|
||||||
iptables -A INPUT -i lo -j ACCEPT
|
iptables -A INPUT -i lo -j ACCEPT
|
||||||
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
|||||||
+1
-16
@@ -227,7 +227,7 @@ void Settings::setSaveLogs(bool enabled)
|
|||||||
if (!isSaveLogs()) {
|
if (!isSaveLogs()) {
|
||||||
Logger::deInit();
|
Logger::deInit();
|
||||||
} else {
|
} else {
|
||||||
if (!Logger::init(false)) {
|
if (!Logger::init()) {
|
||||||
qWarning() << "Initialization of debug subsystem failed";
|
qWarning() << "Initialization of debug subsystem failed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -519,22 +519,7 @@ void Settings::setGatewayEndpoint(const QString &endpoint)
|
|||||||
m_gatewayEndpoint = endpoint;
|
m_gatewayEndpoint = endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setDevGatewayEndpoint()
|
|
||||||
{
|
|
||||||
m_gatewayEndpoint = DEV_AGW_ENDPOINT;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Settings::getGatewayEndpoint()
|
QString Settings::getGatewayEndpoint()
|
||||||
{
|
{
|
||||||
return m_gatewayEndpoint;
|
return m_gatewayEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Settings::isDevGatewayEnv()
|
|
||||||
{
|
|
||||||
return m_isDevGatewayEnv;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Settings::toggleDevGatewayEnv(bool enabled)
|
|
||||||
{
|
|
||||||
m_isDevGatewayEnv = enabled;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -217,10 +217,7 @@ public:
|
|||||||
|
|
||||||
void resetGatewayEndpoint();
|
void resetGatewayEndpoint();
|
||||||
void setGatewayEndpoint(const QString &endpoint);
|
void setGatewayEndpoint(const QString &endpoint);
|
||||||
void setDevGatewayEndpoint();
|
|
||||||
QString getGatewayEndpoint();
|
QString getGatewayEndpoint();
|
||||||
bool isDevGatewayEnv();
|
|
||||||
void toggleDevGatewayEnv(bool enabled);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void saveLogsChanged(bool enabled);
|
void saveLogsChanged(bool enabled);
|
||||||
@@ -237,7 +234,6 @@ private:
|
|||||||
mutable SecureQSettings m_settings;
|
mutable SecureQSettings m_settings;
|
||||||
|
|
||||||
QString m_gatewayEndpoint;
|
QString m_gatewayEndpoint;
|
||||||
bool m_isDevGatewayEnv;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SETTINGS_H
|
#endif // SETTINGS_H
|
||||||
|
|||||||
@@ -6,47 +6,47 @@
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="63"/>
|
<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>
|
<source>Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to %1 MBit/s</source>
|
||||||
<translation>شبكة VPN كلاسيكية للعمل المريح وتنزيل الملفات الكبيرة ومشاهدة مقاطع الفيديو. تعمل مع أي موقع. تصل السرعة إلى %1 ميجابت/ثانية</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
|
||||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||||
<translation>شبكة VPN للولوج للمواقع المحظورة في بلاد ذو مستوي عالي من الرقابة علي الانترنت. </translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
<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>
|
<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>Amenzia Premium - شبكة VPN للعمل المريح, تحميل ملفات كبيرة الحجم, ومشاهدة مقاطع الفيديو ب جودة عالية. تعمل لجميع المواقع, حتي في البلاد ذو مستوي عالي من الرقابة علي الانترنت</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="75"/>
|
<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>
|
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||||
<translation>Amnezia Free هو VPN مجاني لتخطي الحظر في البلاد ذو مستوي عالي من الرقابة علي الانترنت</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
|
||||||
<source>%1 MBit/s</source>
|
<source>%1 MBit/s</source>
|
||||||
<translation>%1 ميجابت/ثانية</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
|
||||||
<source>%1 days</source>
|
<source>%1 days</source>
|
||||||
<translation>%1 ايام</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
<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, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||||
<translation>سيقوم VPN فقط بفتح المواقع المشهورة المحظورة في بلدك, مثل Instagram, Facebook, Twitter و مواقع اخري. المواقع الاخري ستٌفتح من عنوان ال IP الحقيقي الخاص بك, <a href="%1/free" style="color: #FBB26A;">معلومات اخري علي الموقع.</a></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
|
||||||
<source>Free</source>
|
<source>Free</source>
|
||||||
<translation>مجاني</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
|
||||||
<source>%1 $/month</source>
|
<source>%1 $/month</source>
|
||||||
<translation>%1 دولار/الشهر</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -325,7 +325,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="608"/>
|
<location filename="../ui/controllers/installController.cpp" line="608"/>
|
||||||
<source>Api config removed</source>
|
<source>Api config removed</source>
|
||||||
<translation>تم حذف تكوين Api</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="630"/>
|
<location filename="../ui/controllers/installController.cpp" line="630"/>
|
||||||
@@ -345,17 +345,17 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="845"/>
|
<location filename="../ui/controllers/installController.cpp" line="845"/>
|
||||||
<source>%1 installed successfully.</source>
|
<source>%1 installed successfully.</source>
|
||||||
<translation>تم تحميل %1 بنجاح</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="877"/>
|
<location filename="../ui/controllers/installController.cpp" line="877"/>
|
||||||
<source>API config reloaded</source>
|
<source>API config reloaded</source>
|
||||||
<translation>تمت إعادة تحميل تكوين API</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="881"/>
|
<location filename="../ui/controllers/installController.cpp" line="881"/>
|
||||||
<source>Successfully changed the country of connection to %1</source>
|
<source>Successfully changed the country of connection to %1</source>
|
||||||
<translation>تم تغيير بلد الاتصال بنجاح إلى %1</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -441,7 +441,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="74"/>
|
<location filename="../ui/qml/Pages2/PageDevMenu.qml" line="74"/>
|
||||||
<source>Gateway endpoint</source>
|
<source>Gateway endpoint</source>
|
||||||
<translation>نقطة نهاية البوابة</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -507,47 +507,47 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="147"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="147"/>
|
||||||
<source>Jc - Junk packet count</source>
|
<source>Jc - Junk packet count</source>
|
||||||
<translation>Jc - عدد الحزم غير المرغوب فيها</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="172"/>
|
||||||
<source>Jmin - Junk packet minimum size</source>
|
<source>Jmin - Junk packet minimum size</source>
|
||||||
<translation>Jmin - الحجم الادني للحزم الغير مرغوب فيها</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="193"/>
|
||||||
<source>Jmax - Junk packet maximum size</source>
|
<source>Jmax - Junk packet maximum size</source>
|
||||||
<translation>Jmax - الحجم الاقصي للحزم الغير مرغوب فيها</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="214"/>
|
||||||
<source>S1 - Init packet junk size</source>
|
<source>S1 - Init packet junk size</source>
|
||||||
<translation>S1 - حجم حزمة البيانات العشوائية الأولية</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="235"/>
|
||||||
<source>S2 - Response packet junk size</source>
|
<source>S2 - Response packet junk size</source>
|
||||||
<translation>S2 - حجم حزمة الاستجابة غير المرغوب فيها</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="256"/>
|
||||||
<source>H1 - Init packet magic header</source>
|
<source>H1 - Init packet magic header</source>
|
||||||
<translation>H1 - حزمة رأس سحرية مبدئية</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="277"/>
|
||||||
<source>H2 - Response packet magic header</source>
|
<source>H2 - Response packet magic header</source>
|
||||||
<translation>H2 - رأس حزمة الاستجابة السحرية</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="298"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="298"/>
|
||||||
<source>H4 - Transport packet magic header</source>
|
<source>H4 - Transport packet magic header</source>
|
||||||
<translation>H4 - رأس حزمة النقل السحرية</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="320"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="320"/>
|
||||||
<source>H3 - Underload packet magic header</source>
|
<source>H3 - Underload packet magic header</source>
|
||||||
<translation>H3 - رأس حزمة السحر غير المحمل</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="363"/>
|
||||||
@@ -1164,7 +1164,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettings.qml" line="137"/>
|
<location filename="../ui/qml/Pages2/PageSettings.qml" line="137"/>
|
||||||
<source>Dev console</source>
|
<source>Dev console</source>
|
||||||
<translation>وحدة تحكم التطوير</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettings.qml" line="158"/>
|
<location filename="../ui/qml/Pages2/PageSettings.qml" line="158"/>
|
||||||
@@ -1250,74 +1250,74 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="45"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="45"/>
|
||||||
<source>For the region</source>
|
<source>For the region</source>
|
||||||
<translation>للمنطقة</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="54"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="54"/>
|
||||||
<source>Price</source>
|
<source>Price</source>
|
||||||
<translation>السعر</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
||||||
<source>Work period</source>
|
<source>Work period</source>
|
||||||
<translation>مدة العمل</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
||||||
<source>Speed</source>
|
<source>Speed</source>
|
||||||
<translation>السرعة</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
||||||
<source>Support tag</source>
|
<source>Support tag</source>
|
||||||
<translation>علامة الدعم</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
||||||
<source>Copied</source>
|
<source>Copied</source>
|
||||||
<translation>تم النسخ</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
||||||
<source>Reload API config</source>
|
<source>Reload API config</source>
|
||||||
<translation>إعادة تحميل تكوين API</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
||||||
<source>Reload API config?</source>
|
<source>Reload API config?</source>
|
||||||
<translation>إعادة تحميل تكوين API</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>واصل</translation>
|
<translation type="unfinished">واصل</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>إلغاء</translation>
|
<translation type="unfinished">إلغاء</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
||||||
<source>Cannot reload API config during active connection</source>
|
<source>Cannot reload API config during active connection</source>
|
||||||
<translation>لا يمكن إعادة تحميل تكوين API اثناء تواجد اتصال نشط</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
||||||
<source>Remove from application</source>
|
<source>Remove from application</source>
|
||||||
<translation>احذف من التطبيق</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
||||||
<source>Remove from application?</source>
|
<source>Remove from application?</source>
|
||||||
<translation>احذف من التطبيق؟</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
||||||
<source>Cannot remove server during active connection</source>
|
<source>Cannot remove server during active connection</source>
|
||||||
<translation>لا يمكن إزالة الخادم أثناء الاتصال النشط</translation>
|
<translation type="unfinished">لا يمكن إزالة الخادم أثناء الاتصال النشط</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -1769,7 +1769,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="33"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="33"/>
|
||||||
<source>No new installed containers found</source>
|
<source>No new installed containers found</source>
|
||||||
<translation>لم يتم العثور علي اي خدمات مٌثبتة سابقاً</translation>
|
<translation>لم يتم العثور علي اي حاويات جديدة مٌثبتة</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="127"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="127"/>
|
||||||
@@ -1941,7 +1941,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="190"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="190"/>
|
||||||
<source>Remove %1 from server?</source>
|
<source>Remove %1 from server?</source>
|
||||||
<translation>احذف %1 من الخادم؟</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="191"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="191"/>
|
||||||
@@ -2080,32 +2080,32 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="62"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="62"/>
|
||||||
<source>For the region</source>
|
<source>For the region</source>
|
||||||
<translation>للمنطقة</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="71"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="71"/>
|
||||||
<source>Price</source>
|
<source>Price</source>
|
||||||
<translation>السعر</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="80"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="80"/>
|
||||||
<source>Work period</source>
|
<source>Work period</source>
|
||||||
<translation>مدة العمل</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="91"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="91"/>
|
||||||
<source>Speed</source>
|
<source>Speed</source>
|
||||||
<translation>السرعة</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="100"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="100"/>
|
||||||
<source>Features</source>
|
<source>Features</source>
|
||||||
<translation>المميزات</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="139"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="139"/>
|
||||||
<source>Connect</source>
|
<source>Connect</source>
|
||||||
<translation>اتصل</translation>
|
<translation type="unfinished">اتصل</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -2113,80 +2113,96 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServicesList.qml" line="52"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServicesList.qml" line="52"/>
|
||||||
<source>VPN by Amnezia</source>
|
<source>VPN by Amnezia</source>
|
||||||
<translation>VPN بواسطة Amnezia</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServicesList.qml" line="53"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServicesList.qml" line="53"/>
|
||||||
<source>Choose a VPN service that suits your needs.</source>
|
<source>Choose a VPN service that suits your needs.</source>
|
||||||
<translation>اختر خدمة VPN تلبي احتياجاتك</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageSetupWizardConfigSource</name>
|
<name>PageSetupWizardConfigSource</name>
|
||||||
|
<message>
|
||||||
|
<source>Server connection</source>
|
||||||
|
<translation type="vanished">اتصال الخادم</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Do not use connection codes from untrusted sources, as they may be created to intercept your data.</source>
|
||||||
|
<translation type="vanished">لا تستخدم رموز اتصال من مصادر غير موثوقة, حيث قد يكون تم إنشاؤها لاعتراض بياناتك.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>What do you have?</source>
|
||||||
|
<translation type="vanished">ماذا لديك؟</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>File with connection settings or backup</source>
|
||||||
|
<translation type="vanished">ملف إعدادات اتصال او نسخ احتياطي</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="57"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="57"/>
|
||||||
<source>Connection</source>
|
<source>Connection</source>
|
||||||
<translation>الاتصال</translation>
|
<translation type="unfinished">الاتصال</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
|
||||||
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
||||||
<translation>أدخل المفتاح، أضف ملف تكوين أو امسح رمز الاستجابة السريعة</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
|
||||||
<source>Insert key</source>
|
<source>Insert key</source>
|
||||||
<translation>أدخل مفتاح</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
|
||||||
<source>Insert</source>
|
<source>Insert</source>
|
||||||
<translation>أدخل</translation>
|
<translation type="unfinished">ادخل</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>واصل</translation>
|
<translation type="unfinished">واصل</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
|
||||||
<source>Other connection options</source>
|
<source>Other connection options</source>
|
||||||
<translation>اختيارات اتصال اخري</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
|
||||||
<source>VPN by Amnezia</source>
|
<source>VPN by Amnezia</source>
|
||||||
<translation>VPN بواسطة Amnezia</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
|
||||||
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
||||||
<translation>اتصل بخدمات VPN الكلاسيكية المدفوعة والمجانية من Amnezia</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
|
||||||
<source>Self-hosted VPN</source>
|
<source>Self-hosted VPN</source>
|
||||||
<translation>VPN ذاتية الاستضافة</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
|
||||||
<source>Configure Amnezia VPN on your own server</source>
|
<source>Configure Amnezia VPN on your own server</source>
|
||||||
<translation>قم بتكوين Amnezia VPN على الخادم الخاص بك</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
|
||||||
<source>Restore from backup</source>
|
<source>Restore from backup</source>
|
||||||
<translation>استرجاع من ملف يحتوي علي نسخة احتياطية</translation>
|
<translation type="unfinished">استرجاع من ملف يحتوي علي نسخة احتياطية</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
|
||||||
<source>Open backup file</source>
|
<source>Open backup file</source>
|
||||||
<translation>افتح ملف نسخ احتياطي</translation>
|
<translation type="unfinished">افتح ملف نسخ احتياطي</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
|
||||||
<source>Backup files (*.backup)</source>
|
<source>Backup files (*.backup)</source>
|
||||||
<translation>ملفات نٌسخ احتياطية (*.backup)</translation>
|
<translation type="unfinished">ملفات نٌسخ احتياطية (*.backup)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="198"/>
|
||||||
@@ -2206,7 +2222,11 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
|
||||||
<source>I have nothing</source>
|
<source>I have nothing</source>
|
||||||
<translation>ليس لدي اي شئ</translation>
|
<translation type="unfinished">ليس لدي اي شئ</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Key as text</source>
|
||||||
|
<translation type="vanished">مفتاح كنص</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -2249,12 +2269,12 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="153"/>
|
||||||
<source>How to run your VPN server</source>
|
<source>How to run your VPN server</source>
|
||||||
<translation>كيف تقوم بتشغيل خادم ال VPN الخاص بك</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="154"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="154"/>
|
||||||
<source>Where to get connection data, step-by-step instructions for buying a VPS</source>
|
<source>Where to get connection data, step-by-step instructions for buying a VPS</source>
|
||||||
<translation>اين تحصل علي بيانات الاتصال, تعليمات خطوة ب خطوة لشراء VPS</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="170"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="170"/>
|
||||||
@@ -2372,7 +2392,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<translation>تثبيت</translation>
|
<translation>تثبيت</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="268"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
|
||||||
<source>The port must be in the range of 1 to 65535</source>
|
<source>The port must be in the range of 1 to 65535</source>
|
||||||
<translation>يجب أن يكون المنفذ في النطاق من 1 إلى 65535</translation>
|
<translation>يجب أن يكون المنفذ في النطاق من 1 إلى 65535</translation>
|
||||||
</message>
|
</message>
|
||||||
@@ -2400,10 +2420,30 @@ Already installed containers were found on the server. All installed containers
|
|||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PageSetupWizardStart</name>
|
<name>PageSetupWizardStart</name>
|
||||||
|
<message>
|
||||||
|
<source>Settings restored from backup file</source>
|
||||||
|
<translation type="vanished">تم استرداد الإعدادات من ملف نسخة احتياطية</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Free service for creating a personal VPN on your server.</source>
|
||||||
|
<translation type="vanished">خدمة مجانية لأنشاء VPN شخصي علي الخادم الشخصي.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source> Helps you access blocked content without revealing your privacy, even to VPN providers.</source>
|
||||||
|
<translation type="vanished"> يساعدك في الولوج للمحتوي المحظور بدون إظهار خصوصيات, حتي لمزود ال VPN.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>I have the data to connect</source>
|
||||||
|
<translation type="vanished">لدي البيانات المطلوبة للأتصال</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>I have nothing</source>
|
||||||
|
<translation type="vanished">ليس لدي اي شئ</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardStart.qml" line="48"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardStart.qml" line="48"/>
|
||||||
<source>Let's get started</source>
|
<source>Let's get started</source>
|
||||||
<translation>هيا نبدأ</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -2737,7 +2777,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageStart.qml" line="202"/>
|
<location filename="../ui/qml/Pages2/PageStart.qml" line="202"/>
|
||||||
<source>Settings restored from backup file</source>
|
<source>Settings restored from backup file</source>
|
||||||
<translation>تم تحميل الإعدادات من ملف نسخة احتياطية</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -3181,7 +3221,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../core/errorstrings.cpp" line="63"/>
|
<location filename="../core/errorstrings.cpp" line="63"/>
|
||||||
<source>Missing AGW public key</source>
|
<source>Missing AGW public key</source>
|
||||||
<translation>مفتاح AGW عام مفقود</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../core/errorstrings.cpp" line="66"/>
|
<location filename="../core/errorstrings.cpp" line="66"/>
|
||||||
@@ -3259,7 +3299,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../containers/containers_defs.cpp" line="127"/>
|
<location filename="../containers/containers_defs.cpp" line="127"/>
|
||||||
<source>XRay with REALITY - Suitable for countries with the highest level of internet censorship. Traffic masking as web traffic at the TLS level, and protection against detection by active probing methods.</source>
|
<source>XRay with REALITY - Suitable for countries with the highest level of internet censorship. Traffic masking as web traffic at the TLS level, and protection against detection by active probing methods.</source>
|
||||||
<translation>XRay مع REALITY - مناسبة للبلدان التي لديها أعلى مستوى من الرقابة على الإنترنت. إخفاء حركة المرور كحركة مرور على الويب على مستوى TLS، والحماية من الكشف عن طريق طرق التحقيق النشطة.</translation>
|
<translation>الأشعة السينية مع الواقع - مناسبة للبلدان التي لديها أعلى مستوى من الرقابة على الإنترنت. إخفاء حركة المرور كحركة مرور على الويب على مستوى TLS، والحماية من الكشف عن طريق طرق التحقيق النشطة.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../containers/containers_defs.cpp" line="130"/>
|
<location filename="../containers/containers_defs.cpp" line="130"/>
|
||||||
|
|||||||
@@ -6,47 +6,47 @@
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="63"/>
|
<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>
|
<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 type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="67"/>
|
||||||
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
<source>VPN to access blocked sites in regions with high levels of Internet censorship. </source>
|
||||||
<translation>وی پی ان برای دسترسی به سایتهای مسدود شده در مناطق با سانسور شدید اینترنت.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="72"/>
|
<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>
|
<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>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="75"/>
|
<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>
|
<source>Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship</source>
|
||||||
<translation>امنزیا رایگان یک وی پی ان رایگان برای دور زدن مسدودیتها در کشورهایی با سطح بالای سانسور اینترنت است.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="80"/>
|
||||||
<source>%1 MBit/s</source>
|
<source>%1 MBit/s</source>
|
||||||
<translation>%1 MBit/s</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="87"/>
|
||||||
<source>%1 days</source>
|
<source>%1 days</source>
|
||||||
<translation>%1 روز</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="96"/>
|
<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, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
<source>VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. Other sites will be opened from your real IP address, <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></source>
|
||||||
<translation>وی پی ان فقط سایتهای محبوبی را که در منطقه شما مسدود شدهاند، مانند اینستاگرام، فیسبوک، توییتر و غیره باز میکند. سایر سایتها با آدرس آیپی واقعی شما باز خواهند شد. <a href="%1/free" style="color: #FBB26A;">more details on the website.</a></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="104"/>
|
||||||
<source>Free</source>
|
<source>Free</source>
|
||||||
<translation>رایگان</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
|
<location filename="../ui/models/apiServicesModel.cpp" line="106"/>
|
||||||
<source>%1 $/month</source>
|
<source>%1 $/month</source>
|
||||||
<translation>%1 $/ماه</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -54,22 +54,22 @@
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/appSplitTunnelingController.cpp" line="23"/>
|
<location filename="../ui/controllers/appSplitTunnelingController.cpp" line="23"/>
|
||||||
<source>Application added: %1</source>
|
<source>Application added: %1</source>
|
||||||
<translation>برنامه اضافه شد: %1</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/appSplitTunnelingController.cpp" line="26"/>
|
<location filename="../ui/controllers/appSplitTunnelingController.cpp" line="26"/>
|
||||||
<source>The application has already been added</source>
|
<source>The application has already been added</source>
|
||||||
<translation>برنامه از قبل اضافه شده است</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/appSplitTunnelingController.cpp" line="37"/>
|
<location filename="../ui/controllers/appSplitTunnelingController.cpp" line="37"/>
|
||||||
<source>The selected applications have been added</source>
|
<source>The selected applications have been added</source>
|
||||||
<translation>برنامههای انتخاب شده اضافه شدند</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/appSplitTunnelingController.cpp" line="48"/>
|
<location filename="../ui/controllers/appSplitTunnelingController.cpp" line="48"/>
|
||||||
<source>Application removed: %1</source>
|
<source>Application removed: %1</source>
|
||||||
<translation>برنامه حذف شد: %1</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Components/ConnectButton.qml" line="27"/>
|
<location filename="../ui/qml/Components/ConnectButton.qml" line="27"/>
|
||||||
<source>Unable to disconnect during configuration preparation</source>
|
<source>Unable to disconnect during configuration preparation</source>
|
||||||
<translation>در هنگام آمادهسازی پیکربندی، نمیتوان از اتصال خارج شد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/connectionController.cpp" line="110"/>
|
<location filename="../ui/controllers/connectionController.cpp" line="110"/>
|
||||||
<source>Preparing...</source>
|
<source>Preparing...</source>
|
||||||
<translation>در حال آمادهسازی...</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/connectionController.cpp" line="132"/>
|
<location filename="../ui/controllers/connectionController.cpp" line="132"/>
|
||||||
@@ -118,12 +118,12 @@
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/connectionController.cpp" line="209"/>
|
<location filename="../ui/controllers/connectionController.cpp" line="209"/>
|
||||||
<source>The selected protocol is not supported on the current platform</source>
|
<source>The selected protocol is not supported on the current platform</source>
|
||||||
<translation>پروتکل انتخابشده در پلتفرم فعلی پشتیبانی نمیشود.</translation>
|
<translation type="unfinished">پروتکل انتخاب شده بر روی این پلتفرم پشتیبانی نمیشود</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/connectionController.cpp" line="233"/>
|
<location filename="../ui/controllers/connectionController.cpp" line="233"/>
|
||||||
<source>unable to create configuration</source>
|
<source>unable to create configuration</source>
|
||||||
<translation>نمیتوان پیکربندی را ایجاد کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/connectionController.cpp" line="95"/>
|
<location filename="../ui/controllers/connectionController.cpp" line="95"/>
|
||||||
@@ -256,13 +256,13 @@ Can't be disabled for current server</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="87"/>
|
<location filename="../ui/controllers/importController.cpp" line="87"/>
|
||||||
<source>Unable to open file</source>
|
<source>Unable to open file</source>
|
||||||
<translation>نمیتوان فایل را باز کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="186"/>
|
<location filename="../ui/controllers/importController.cpp" line="186"/>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="191"/>
|
<location filename="../ui/controllers/importController.cpp" line="191"/>
|
||||||
<source>Invalid configuration file</source>
|
<source>Invalid configuration file</source>
|
||||||
<translation>فایل پیکربندی نامعتبر است.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="606"/>
|
<location filename="../ui/controllers/importController.cpp" line="606"/>
|
||||||
@@ -272,7 +272,7 @@ Can't be disabled for current server</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/importController.cpp" line="641"/>
|
<location filename="../ui/controllers/importController.cpp" line="641"/>
|
||||||
<source>In the imported configuration, potentially dangerous lines were found:</source>
|
<source>In the imported configuration, potentially dangerous lines were found:</source>
|
||||||
<translation>در پیکربندی وارد شده، خطوطی که ممکن است خطرناک باشند، یافت شدند:</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -329,12 +329,12 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="608"/>
|
<location filename="../ui/controllers/installController.cpp" line="608"/>
|
||||||
<source>Api config removed</source>
|
<source>Api config removed</source>
|
||||||
<translation>پیکربندی API حذف شد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="630"/>
|
<location filename="../ui/controllers/installController.cpp" line="630"/>
|
||||||
<source>%1 cached profile cleared</source>
|
<source>%1 cached profile cleared</source>
|
||||||
<translation>%1 پروفایل ذخیره شده پاک شد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="769"/>
|
<location filename="../ui/controllers/installController.cpp" line="769"/>
|
||||||
@@ -349,17 +349,17 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="845"/>
|
<location filename="../ui/controllers/installController.cpp" line="845"/>
|
||||||
<source>%1 installed successfully.</source>
|
<source>%1 installed successfully.</source>
|
||||||
<translation>%1 با موفقیت نصب شد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="877"/>
|
<location filename="../ui/controllers/installController.cpp" line="877"/>
|
||||||
<source>API config reloaded</source>
|
<source>API config reloaded</source>
|
||||||
<translation>پیکربندی API دوباره بارگذاری شد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/controllers/installController.cpp" line="881"/>
|
<location filename="../ui/controllers/installController.cpp" line="881"/>
|
||||||
<source>Successfully changed the country of connection to %1</source>
|
<source>Successfully changed the country of connection to %1</source>
|
||||||
<translation>کشور اتصال با موفقیت به %1 تغییر یافت.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -367,17 +367,17 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Components/InstalledAppsDrawer.qml" line="57"/>
|
<location filename="../ui/qml/Components/InstalledAppsDrawer.qml" line="57"/>
|
||||||
<source>Choose application</source>
|
<source>Choose application</source>
|
||||||
<translation>انتخاب برنامه</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Components/InstalledAppsDrawer.qml" line="139"/>
|
<location filename="../ui/qml/Components/InstalledAppsDrawer.qml" line="139"/>
|
||||||
<source>application name</source>
|
<source>application name</source>
|
||||||
<translation>نام برنامه</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Components/InstalledAppsDrawer.qml" line="152"/>
|
<location filename="../ui/qml/Components/InstalledAppsDrawer.qml" line="152"/>
|
||||||
<source>Add selected</source>
|
<source>Add selected</source>
|
||||||
<translation>اضافه کردن انتخاب شده</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -453,7 +453,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageHome.qml" line="67"/>
|
<location filename="../ui/qml/Pages2/PageHome.qml" line="67"/>
|
||||||
<source>Logging enabled</source>
|
<source>Logging enabled</source>
|
||||||
<translation>لاگبرداری فعال شد</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageHome.qml" line="111"/>
|
<location filename="../ui/qml/Pages2/PageHome.qml" line="111"/>
|
||||||
@@ -589,7 +589,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="382"/>
|
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="382"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>نمیتوان تنظیمات را تغییر داد در حالی که اتصال فعال است.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -623,7 +623,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolCloakSettings.qml" line="193"/>
|
<location filename="../ui/qml/Pages2/PageProtocolCloakSettings.qml" line="193"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>نمیتوان تنظیمات را تغییر داد در حالی که اتصال فعال است.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -794,7 +794,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolOpenVpnSettings.qml" line="445"/>
|
<location filename="../ui/qml/Pages2/PageProtocolOpenVpnSettings.qml" line="445"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>نمیتوان تنظیمات را تغییر داد در حالی که اتصال فعال است.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Remove OpenVPN</source>
|
<source>Remove OpenVPN</source>
|
||||||
@@ -895,7 +895,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolShadowSocksSettings.qml" line="181"/>
|
<location filename="../ui/qml/Pages2/PageProtocolShadowSocksSettings.qml" line="181"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>نمیتوان تنظیمات را تغییر داد در حالی که اتصال فعال است.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -903,22 +903,22 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="94"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="94"/>
|
||||||
<source>WG settings</source>
|
<source>WG settings</source>
|
||||||
<translation>تنظیمات WG</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="102"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="102"/>
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
<translation>پورت</translation>
|
<translation type="unfinished">پورت</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="123"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="123"/>
|
||||||
<source>MTU</source>
|
<source>MTU</source>
|
||||||
<translation></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="157"/>
|
<location filename="../ui/qml/Pages2/PageProtocolWireGuardSettings.qml" line="157"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>نمیتوان تنظیمات را تغییر داد در حالی که اتصال فعال است.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
|
<source>All users with whom you shared a connection will no longer be able to connect to it.</source>
|
||||||
@@ -939,22 +939,22 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolXraySettings.qml" line="95"/>
|
<location filename="../ui/qml/Pages2/PageProtocolXraySettings.qml" line="95"/>
|
||||||
<source>XRay settings</source>
|
<source>XRay settings</source>
|
||||||
<translation>تنظیمات XRay</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolXraySettings.qml" line="103"/>
|
<location filename="../ui/qml/Pages2/PageProtocolXraySettings.qml" line="103"/>
|
||||||
<source>Disguised as traffic from</source>
|
<source>Disguised as traffic from</source>
|
||||||
<translation>بهعنوان ترافیک از طرف زیر نمایش داده میشود</translation>
|
<translation type="unfinished">پنهان کردن به عنوان ترافیک از</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolXraySettings.qml" line="129"/>
|
<location filename="../ui/qml/Pages2/PageProtocolXraySettings.qml" line="129"/>
|
||||||
<source>Save</source>
|
<source>Save</source>
|
||||||
<translation>ذخیره</translation>
|
<translation type="unfinished">ذخیره</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageProtocolXraySettings.qml" line="137"/>
|
<location filename="../ui/qml/Pages2/PageProtocolXraySettings.qml" line="137"/>
|
||||||
<source>Unable change settings while there is an active connection</source>
|
<source>Unable change settings while there is an active connection</source>
|
||||||
<translation>نمیتوان تنظیمات را تغییر داد در حالی که اتصال فعال است.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -1001,7 +1001,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceDnsSettings.qml" line="85"/>
|
<location filename="../ui/qml/Pages2/PageServiceDnsSettings.qml" line="85"/>
|
||||||
<source>Cannot remove AmneziaDNS from running server</source>
|
<source>Cannot remove AmneziaDNS from running server</source>
|
||||||
<translation>نمیتوان AmneziaDNS را از سرور در حال اجرا حذف کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -1093,18 +1093,18 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="26"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="26"/>
|
||||||
<source>Settings updated successfully</source>
|
<source>Settings updated successfully</source>
|
||||||
<translation>تنظیمات با موفقیت بهروزرسانی شد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="93"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="93"/>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="250"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="250"/>
|
||||||
<source>SOCKS5 settings</source>
|
<source>SOCKS5 settings</source>
|
||||||
<translation>تنظیمات SOCKS5</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="104"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="104"/>
|
||||||
<source>Host</source>
|
<source>Host</source>
|
||||||
<translation>هاستمیزبان</translation>
|
<translation type="unfinished">هاست</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="114"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="114"/>
|
||||||
@@ -1112,50 +1112,50 @@ 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="162"/>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="189"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="189"/>
|
||||||
<source>Copied</source>
|
<source>Copied</source>
|
||||||
<translation>کپی شد</translation>
|
<translation type="unfinished">کپی شد</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="125"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="125"/>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="260"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="260"/>
|
||||||
<source>Port</source>
|
<source>Port</source>
|
||||||
<translation>پورت</translation>
|
<translation type="unfinished">پورت</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="149"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="149"/>
|
||||||
<source>User name</source>
|
<source>User name</source>
|
||||||
<translation>نام کاربری</translation>
|
<translation type="unfinished">نام کاربری</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="173"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="173"/>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="306"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="306"/>
|
||||||
<source>Password</source>
|
<source>Password</source>
|
||||||
<translation>رمز عبور</translation>
|
<translation type="unfinished">رمز عبور</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="282"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="282"/>
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>نام کاربری</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="336"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="336"/>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="374"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="374"/>
|
||||||
<source>Change connection settings</source>
|
<source>Change connection settings</source>
|
||||||
<translation>تغییر تنظیمات اتصال</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="343"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="343"/>
|
||||||
<source>The port must be in the range of 1 to 65535</source>
|
<source>The port must be in the range of 1 to 65535</source>
|
||||||
<translation>پورت باید در محدوده ۱ تا ۶۵۵۳۵ باشد</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="347"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="347"/>
|
||||||
<source>Password cannot be empty</source>
|
<source>Password cannot be empty</source>
|
||||||
<translation>رمز عبور نمیتواند خالی باشد</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="350"/>
|
<location filename="../ui/qml/Pages2/PageServiceSocksProxySettings.qml" line="350"/>
|
||||||
<source>Username cannot be empty</source>
|
<source>Username cannot be empty</source>
|
||||||
<translation>نام کاربری نمیتواند خالی باشد</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -1285,7 +1285,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="113"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="113"/>
|
||||||
<source>https://t.me/amnezia_vpn_en</source>
|
<source>https://t.me/amnezia_vpn_en</source>
|
||||||
<translation>https://t.me/amnezia_vpn_ir</translation>
|
<translation>https://t.me/amnezia_vpn</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="123"/>
|
||||||
@@ -1337,22 +1337,22 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="45"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="45"/>
|
||||||
<source>For the region</source>
|
<source>For the region</source>
|
||||||
<translation>برای منطقه</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="54"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="54"/>
|
||||||
<source>Price</source>
|
<source>Price</source>
|
||||||
<translation>قیمت</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="63"/>
|
||||||
<source>Work period</source>
|
<source>Work period</source>
|
||||||
<translation>مدت زمان کار</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="74"/>
|
||||||
<source>Speed</source>
|
<source>Speed</source>
|
||||||
<translation>سرعت</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="106"/>
|
||||||
@@ -1362,49 +1362,49 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="119"/>
|
||||||
<source>Copied</source>
|
<source>Copied</source>
|
||||||
<translation>کپی شد</translation>
|
<translation type="unfinished">کپی شد</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="139"/>
|
||||||
<source>Reload API config</source>
|
<source>Reload API config</source>
|
||||||
<translation>بارگذاری مجدد پیکربندی API</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="144"/>
|
||||||
<source>Reload API config?</source>
|
<source>Reload API config?</source>
|
||||||
<translation>آیا میخواهید پیکربندی API را دوباره بارگذاری کنید؟</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="145"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="185"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>ادامه دهید</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="146"/>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="186"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>لغو</translation>
|
<translation type="unfinished">کنسل</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="150"/>
|
||||||
<source>Cannot reload API config during active connection</source>
|
<source>Cannot reload API config during active connection</source>
|
||||||
<translation>نمیتوان پیکربندی API را در حین اتصال فعال دوباره بارگذاری کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="179"/>
|
||||||
<source>Remove from application</source>
|
<source>Remove from application</source>
|
||||||
<translation>حذف از برنامه</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="184"/>
|
||||||
<source>Remove from application?</source>
|
<source>Remove from application?</source>
|
||||||
<translation>آیا میخواهید از برنامه حذف کنید؟</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApiServerInfo.qml" line="190"/>
|
||||||
<source>Cannot remove server during active connection</source>
|
<source>Cannot remove server during active connection</source>
|
||||||
<translation>نمیتوان سرور را در حین اتصال فعال حذف کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -1412,57 +1412,57 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="30"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="30"/>
|
||||||
<source>Cannot change split tunneling settings during active connection</source>
|
<source>Cannot change split tunneling settings during active connection</source>
|
||||||
<translation>نمی توان تنظیمات تونل تقسیم را در طول اتصال فعال تغییر دادنمیتوان تنظیمات تقسیم تونلینگ را در حین اتصال فعال تغییر داد.</translation>
|
<translation type="unfinished">نمی توان تنظیمات تونل تقسیم را در طول اتصال فعال تغییر داد</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="51"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="51"/>
|
||||||
<source>Only the apps from the list should have access via VPN</source>
|
<source>Only the apps from the list should have access via VPN</source>
|
||||||
<translation>فقط برنامههای موجود در لیست باید از طریق VPN دسترسی داشته باشند.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="56"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="56"/>
|
||||||
<source>Apps from the list should not have access via VPN</source>
|
<source>Apps from the list should not have access via VPN</source>
|
||||||
<translation>برنامههای موجود در لیست نباید از طریق VPN دسترسی داشته باشند.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="93"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="93"/>
|
||||||
<source>App split tunneling</source>
|
<source>App split tunneling</source>
|
||||||
<translation>تقسیم تونلینگ برنامهها</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="129"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="129"/>
|
||||||
<source>Mode</source>
|
<source>Mode</source>
|
||||||
<translation>حالت</translation>
|
<translation type="unfinished">حالت</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="221"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="221"/>
|
||||||
<source>Remove </source>
|
<source>Remove </source>
|
||||||
<translation>حذف </translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="222"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="222"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>ادامه دهید</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="223"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="223"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation>کنسل</translation>
|
<translation type="unfinished">کنسل</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="267"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="267"/>
|
||||||
<source>application name</source>
|
<source>application name</source>
|
||||||
<translation>نام برنامه</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="278"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="278"/>
|
||||||
<source>Open executable file</source>
|
<source>Open executable file</source>
|
||||||
<translation>فایل اجرایی را باز کنید</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="279"/>
|
<location filename="../ui/qml/Pages2/PageSettingsAppSplitTunneling.qml" line="279"/>
|
||||||
<source>Executable files (*.*)</source>
|
<source>Executable files (*.*)</source>
|
||||||
<translation>فایلهای اجرایی (*.*)</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -1480,12 +1480,12 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="94"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="94"/>
|
||||||
<source>Enable notifications</source>
|
<source>Enable notifications</source>
|
||||||
<translation>فعال کردن اعلانها</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="95"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="95"/>
|
||||||
<source>Enable notifications to show the VPN state in the status bar</source>
|
<source>Enable notifications to show the VPN state in the status bar</source>
|
||||||
<translation>اعلان ها را فعال کنید تا وضعیت VPN را در نوار وضعیت ببینید</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="117"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="117"/>
|
||||||
@@ -1565,7 +1565,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="240"/>
|
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="240"/>
|
||||||
<source>Cannot reset settings during active connection</source>
|
<source>Cannot reset settings during active connection</source>
|
||||||
<translation>نمیتوان تنظیمات را در حین اتصال فعال بازنشانی کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -1644,7 +1644,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsBackup.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSettingsBackup.qml" line="153"/>
|
||||||
<source>Cannot restore backup settings during active connection</source>
|
<source>Cannot restore backup settings during active connection</source>
|
||||||
<translation>نمیتوان تنظیمات پشتیبان را در حین اتصال فعال بازیابی کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -1682,17 +1682,17 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="154"/>
|
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="154"/>
|
||||||
<source>KillSwitch</source>
|
<source>KillSwitch</source>
|
||||||
<translation>KillSwitch</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="155"/>
|
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="155"/>
|
||||||
<source>Disables your internet if your encrypted VPN connection drops out for any reason.</source>
|
<source>Disables your internet if your encrypted VPN connection drops out for any reason.</source>
|
||||||
<translation>اگر به هر دلیلی اتصال VPN رمزگذاری شده شما قطع شود، اینترنت شما را غیرفعال میکند.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="166"/>
|
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="166"/>
|
||||||
<source>Cannot change killSwitch settings during active connection</source>
|
<source>Cannot change killSwitch settings during active connection</source>
|
||||||
<translation>نمیتوان تنظیمات Kill Switch را در حین اتصال فعال تغییر داد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="97"/>
|
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="97"/>
|
||||||
@@ -1778,7 +1778,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="24"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="24"/>
|
||||||
<source>Logging is enabled. Note that logs will be automatically disabled after 14 days, and all log files will be deleted.</source>
|
<source>Logging is enabled. Note that logs will be automatically disabled after 14 days, and all log files will be deleted.</source>
|
||||||
<translation>ثبت وقایع فعال است. توجه داشته باشید که ثبت وقایع بهطور خودکار پس از ۱۴ روز غیرفعال شده و تمام فایلهای ثبت وقایع حذف خواهند شد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="69"/>
|
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="69"/>
|
||||||
@@ -1919,7 +1919,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="134"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="134"/>
|
||||||
<source>Cannot reboot server during active connection</source>
|
<source>Cannot reboot server during active connection</source>
|
||||||
<translation>نمیتوان سرور را در حین اتصال فعال راهاندازی مجدد کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="176"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="176"/>
|
||||||
@@ -1929,7 +1929,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="183"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="183"/>
|
||||||
<source>Cannot remove server during active connection</source>
|
<source>Cannot remove server during active connection</source>
|
||||||
<translation>نمیتوان سرور را در حین اتصال فعال حذف کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="218"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="218"/>
|
||||||
@@ -1944,7 +1944,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="225"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="225"/>
|
||||||
<source>Cannot clear server from Amnezia software during active connection</source>
|
<source>Cannot clear server from Amnezia software during active connection</source>
|
||||||
<translation>نمیتوان سرور را در حین اتصال فعال از نرمافزار Amnezia پاک کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="253"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="253"/>
|
||||||
@@ -1959,7 +1959,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="266"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="266"/>
|
||||||
<source>Cannot reset API config during active connection</source>
|
<source>Cannot reset API config during active connection</source>
|
||||||
<translation>نمیتوان پیکربندی API را در حین اتصال فعال بازنشانی کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="162"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerData.qml" line="162"/>
|
||||||
@@ -2015,12 +2015,12 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="135"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="135"/>
|
||||||
<source>Clear %1 profile</source>
|
<source>Clear %1 profile</source>
|
||||||
<translation>پاک کردن پروفایل %1</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="138"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="138"/>
|
||||||
<source>Clear %1 profile?</source>
|
<source>Clear %1 profile?</source>
|
||||||
<translation>آیا میخواهید پروفایل %1 را پاک کنید؟</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="137"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="137"/>
|
||||||
@@ -2030,7 +2030,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="145"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="145"/>
|
||||||
<source>Unable to clear %1 profile while there is an active connection</source>
|
<source>Unable to clear %1 profile while there is an active connection</source>
|
||||||
<translation>نمیتوان پروفایل %1 را در حین اتصال فعال پاک کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="186"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="186"/>
|
||||||
@@ -2050,7 +2050,7 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="198"/>
|
||||||
<source>Cannot remove active container</source>
|
<source>Cannot remove active container</source>
|
||||||
<translation>نمیتوان کانتینر فعال را حذف کرد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="140"/>
|
<location filename="../ui/qml/Pages2/PageSettingsServerProtocol.qml" line="140"/>
|
||||||
@@ -2179,32 +2179,32 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="62"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="62"/>
|
||||||
<source>For the region</source>
|
<source>For the region</source>
|
||||||
<translation>برای منطقه</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="71"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="71"/>
|
||||||
<source>Price</source>
|
<source>Price</source>
|
||||||
<translation>قیمت</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="80"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="80"/>
|
||||||
<source>Work period</source>
|
<source>Work period</source>
|
||||||
<translation>مدت زمان کار</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="91"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="91"/>
|
||||||
<source>Speed</source>
|
<source>Speed</source>
|
||||||
<translation>سرعت</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="100"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="100"/>
|
||||||
<source>Features</source>
|
<source>Features</source>
|
||||||
<translation>ویژگیها</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="139"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml" line="139"/>
|
||||||
<source>Connect</source>
|
<source>Connect</source>
|
||||||
<translation>اتصال</translation>
|
<translation type="unfinished">اتصال</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -2212,12 +2212,12 @@ Already installed containers were found on the server. All installed containers
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServicesList.qml" line="52"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServicesList.qml" line="52"/>
|
||||||
<source>VPN by Amnezia</source>
|
<source>VPN by Amnezia</source>
|
||||||
<translation>VPN توسط Amnezia</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardApiServicesList.qml" line="53"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardApiServicesList.qml" line="53"/>
|
||||||
<source>Choose a VPN service that suits your needs.</source>
|
<source>Choose a VPN service that suits your needs.</source>
|
||||||
<translation>یک سرویس VPN که مناسب نیازهای شما باشد را انتخاب کنید.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -2254,67 +2254,67 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="57"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="57"/>
|
||||||
<source>Connection</source>
|
<source>Connection</source>
|
||||||
<translation>ارتباط</translation>
|
<translation type="unfinished">ارتباط</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="67"/>
|
||||||
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
<source>Insert the key, add a configuration file or scan the QR-code</source>
|
||||||
<translation>کلید را وارد کنید، فایل پیکربندی را اضافه کنید یا کد QR را اسکن کنید</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="77"/>
|
||||||
<source>Insert key</source>
|
<source>Insert key</source>
|
||||||
<translation>کلید را وارد کنید</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="78"/>
|
||||||
<source>Insert</source>
|
<source>Insert</source>
|
||||||
<translation>وارد کردن</translation>
|
<translation type="unfinished">وارد کردن</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="98"/>
|
||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation>ادامه دهید</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="116"/>
|
||||||
<source>Other connection options</source>
|
<source>Other connection options</source>
|
||||||
<translation>گزینههای اتصال دیگر</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="129"/>
|
||||||
<source>VPN by Amnezia</source>
|
<source>VPN by Amnezia</source>
|
||||||
<translation>VPN توسط Amnezia</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="130"/>
|
||||||
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
<source>Connect to classic paid and free VPN services from Amnezia</source>
|
||||||
<translation>اتصال به سرویسهای VPN کلاسیک پولی و رایگان از Amnezia</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="153"/>
|
||||||
<source>Self-hosted VPN</source>
|
<source>Self-hosted VPN</source>
|
||||||
<translation>Self-hosted VPN</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="154"/>
|
||||||
<source>Configure Amnezia VPN on your own server</source>
|
<source>Configure Amnezia VPN on your own server</source>
|
||||||
<translation>پیکربندی VPN Amnezia بر روی سرور خودتان</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="174"/>
|
||||||
<source>Restore from backup</source>
|
<source>Restore from backup</source>
|
||||||
<translation>بازیابی از پشتیبان</translation>
|
<translation type="unfinished">بازیابی از پشتیبان</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="180"/>
|
||||||
<source>Open backup file</source>
|
<source>Open backup file</source>
|
||||||
<translation>باز کردن فایل پشتیبان</translation>
|
<translation type="unfinished">باز کردن فایل پشتیبان</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="181"/>
|
||||||
<source>Backup files (*.backup)</source>
|
<source>Backup files (*.backup)</source>
|
||||||
<translation>Backup files (*.backup)</translation>
|
<translation type="unfinished">Backup files (*.backup)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="206"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="206"/>
|
||||||
@@ -2329,7 +2329,7 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardConfigSource.qml" line="248"/>
|
||||||
<source>I have nothing</source>
|
<source>I have nothing</source>
|
||||||
<translation>من هیچی ندارم</translation>
|
<translation type="unfinished">من هیچی ندارم</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Key as text</source>
|
<source>Key as text</source>
|
||||||
@@ -2381,12 +2381,12 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="153"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="153"/>
|
||||||
<source>How to run your VPN server</source>
|
<source>How to run your VPN server</source>
|
||||||
<translation>چگونه سرور VPN خود را اجرا کنید</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="154"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="154"/>
|
||||||
<source>Where to get connection data, step-by-step instructions for buying a VPS</source>
|
<source>Where to get connection data, step-by-step instructions for buying a VPS</source>
|
||||||
<translation>دادههای اتصال را از کجا دریافت کنید و دستورالعملهای مرحله به مرحله برای خرید یک VPS</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="170"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardCredentials.qml" line="170"/>
|
||||||
@@ -2501,7 +2501,7 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardProtocolSettings.qml" line="267"/>
|
||||||
<source>The port must be in the range of 1 to 65535</source>
|
<source>The port must be in the range of 1 to 65535</source>
|
||||||
<translation>پورت باید در محدوده ۱ تا ۶۵۵۳۵ باشد</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -2550,7 +2550,7 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardStart.qml" line="48"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardStart.qml" line="48"/>
|
||||||
<source>Let's get started</source>
|
<source>Let's get started</source>
|
||||||
<translation>بیایید شروع کنیم</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -2601,7 +2601,7 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardViewConfig.qml" line="123"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardViewConfig.qml" line="123"/>
|
||||||
<source>Enable WireGuard obfuscation. It may be useful if WireGuard is blocked on your provider.</source>
|
<source>Enable WireGuard obfuscation. It may be useful if WireGuard is blocked on your provider.</source>
|
||||||
<translation>فعالسازی استتار WireGuard. این ممکن است مفید باشد اگر WireGuard توسط ارائهدهنده شما مسدود شده باشد.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageSetupWizardViewConfig.qml" line="144"/>
|
<location filename="../ui/qml/Pages2/PageSetupWizardViewConfig.qml" line="144"/>
|
||||||
@@ -2680,7 +2680,7 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShare.qml" line="96"/>
|
<location filename="../ui/qml/Pages2/PageShare.qml" line="96"/>
|
||||||
<source>Save XRay config</source>
|
<source>Save XRay config</source>
|
||||||
<translation>ذخیره پیکربندی XRay</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShare.qml" line="122"/>
|
<location filename="../ui/qml/Pages2/PageShare.qml" line="122"/>
|
||||||
@@ -2705,7 +2705,7 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShare.qml" line="152"/>
|
<location filename="../ui/qml/Pages2/PageShare.qml" line="152"/>
|
||||||
<source>XRay native format</source>
|
<source>XRay native format</source>
|
||||||
<translation>فرمت بومی XRay</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShare.qml" line="190"/>
|
<location filename="../ui/qml/Pages2/PageShare.qml" line="190"/>
|
||||||
@@ -2741,22 +2741,22 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShare.qml" line="817"/>
|
<location filename="../ui/qml/Pages2/PageShare.qml" line="817"/>
|
||||||
<source>Creation date: %1</source>
|
<source>Creation date: %1</source>
|
||||||
<translation>تاریخ ایجاد: %1</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShare.qml" line="825"/>
|
<location filename="../ui/qml/Pages2/PageShare.qml" line="825"/>
|
||||||
<source>Latest handshake: %1</source>
|
<source>Latest handshake: %1</source>
|
||||||
<translation>آخرین ارتباط: %1</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShare.qml" line="833"/>
|
<location filename="../ui/qml/Pages2/PageShare.qml" line="833"/>
|
||||||
<source>Data received: %1</source>
|
<source>Data received: %1</source>
|
||||||
<translation>دادههای دریافت شده: %1</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageShare.qml" line="841"/>
|
<location filename="../ui/qml/Pages2/PageShare.qml" line="841"/>
|
||||||
<source>Data sent: %1</source>
|
<source>Data sent: %1</source>
|
||||||
<translation>دادههای ارسال شده: %1</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Creation date: </source>
|
<source>Creation date: </source>
|
||||||
@@ -2882,12 +2882,12 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageStart.qml" line="198"/>
|
<location filename="../ui/qml/Pages2/PageStart.qml" line="198"/>
|
||||||
<source>Logging was disabled after 14 days, log files were deleted</source>
|
<source>Logging was disabled after 14 days, log files were deleted</source>
|
||||||
<translation>ثبت وقایع پس از ۱۴ روز غیرفعال شد و فایلهای ثبت وقایع حذف شدند</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui/qml/Pages2/PageStart.qml" line="202"/>
|
<location filename="../ui/qml/Pages2/PageStart.qml" line="202"/>
|
||||||
<source>Settings restored from backup file</source>
|
<source>Settings restored from backup file</source>
|
||||||
<translation>تنظیمات از فایل پشتیبان بازیابی شد</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@@ -3296,17 +3296,17 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../core/errorstrings.cpp" line="14"/>
|
<location filename="../core/errorstrings.cpp" line="14"/>
|
||||||
<source>Background service is not running</source>
|
<source>Background service is not running</source>
|
||||||
<translation>Background service is not running</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../core/errorstrings.cpp" line="23"/>
|
<location filename="../core/errorstrings.cpp" line="23"/>
|
||||||
<source>Server error: Packet manager error</source>
|
<source>Server error: Packet manager error</source>
|
||||||
<translation>Server error: Packet manager error</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../core/errorstrings.cpp" line="34"/>
|
<location filename="../core/errorstrings.cpp" line="34"/>
|
||||||
<source>SCP error: Generic failure</source>
|
<source>SCP error: Generic failure</source>
|
||||||
<translation>SCP error: Generic failure</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../core/errorstrings.cpp" line="38"/>
|
<location filename="../core/errorstrings.cpp" line="38"/>
|
||||||
@@ -3356,17 +3356,17 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../core/errorstrings.cpp" line="60"/>
|
<location filename="../core/errorstrings.cpp" line="60"/>
|
||||||
<source>In the response from the server, an empty config was received</source>
|
<source>In the response from the server, an empty config was received</source>
|
||||||
<translation>در پاسخ از سرور، پیکربندی خالی دریافت شد</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../core/errorstrings.cpp" line="61"/>
|
<location filename="../core/errorstrings.cpp" line="61"/>
|
||||||
<source>SSL error occurred</source>
|
<source>SSL error occurred</source>
|
||||||
<translation type="unfinished">SSL error occurred</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../core/errorstrings.cpp" line="62"/>
|
<location filename="../core/errorstrings.cpp" line="62"/>
|
||||||
<source>Server response timeout on api request</source>
|
<source>Server response timeout on api request</source>
|
||||||
<translation>Server response timeout on api request</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../core/errorstrings.cpp" line="63"/>
|
<location filename="../core/errorstrings.cpp" line="63"/>
|
||||||
@@ -3426,12 +3426,12 @@ It's okay as long as it's from someone you trust.</source>
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../containers/containers_defs.cpp" line="127"/>
|
<location filename="../containers/containers_defs.cpp" line="127"/>
|
||||||
<source>XRay with REALITY - Suitable for countries with the highest level of internet censorship. Traffic masking as web traffic at the TLS level, and protection against detection by active probing methods.</source>
|
<source>XRay with REALITY - Suitable for countries with the highest level of internet censorship. Traffic masking as web traffic at the TLS level, and protection against detection by active probing methods.</source>
|
||||||
<translation>XRay با REALITY - مناسب برای کشورهایی با بالاترین سطح سانسور اینترنت. استتار ترافیک به عنوان ترافیک وب در سطح TLS و حفاظت در برابر شناسایی با روشهای پروب فعال.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../containers/containers_defs.cpp" line="130"/>
|
<location filename="../containers/containers_defs.cpp" line="130"/>
|
||||||
<source>IKEv2/IPsec - Modern stable protocol, a bit faster than others, restores connection after signal loss. It has native support on the latest versions of Android and iOS.</source>
|
<source>IKEv2/IPsec - Modern stable protocol, a bit faster than others, restores connection after signal loss. It has native support on the latest versions of Android and iOS.</source>
|
||||||
<translation>IKEv2/IPsec - پروتکل مدرن و پایدار، کمی سریعتر از سایرین است و پس از قطع شدن سیگنال، اتصال را بازیابی میکند. از پشتیبانی بومی در آخرین نسخههای Android و iOS برخوردار است.</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../containers/containers_defs.cpp" line="137"/>
|
<location filename="../containers/containers_defs.cpp" line="137"/>
|
||||||
@@ -3504,11 +3504,7 @@ WireGuard به دلیل امضاهای بسته متمایز خود، بسیار
|
|||||||
It uniquely identifies censors during the TLS handshake phase, seamlessly operating as a proxy for legitimate clients while diverting censors to genuine websites like google.com, thus presenting an authentic TLS certificate and data.
|
It uniquely identifies censors during the TLS handshake phase, seamlessly operating as a proxy for legitimate clients while diverting censors to genuine websites like google.com, thus presenting an authentic TLS certificate and data.
|
||||||
This advanced capability differentiates REALITY from similar technologies by its ability to disguise web traffic as coming from random, legitimate sites without the need for specific configurations.
|
This advanced capability differentiates REALITY from similar technologies by its ability to disguise web traffic as coming from random, legitimate sites without the need for specific configurations.
|
||||||
Unlike older protocols such as VMess, VLESS, and the XTLS-Vision transport, REALITY's innovative "friend or foe" recognition at the TLS handshake enhances security and circumvents detection by sophisticated DPI systems employing active probing techniques. This makes REALITY a robust solution for maintaining internet freedom in environments with stringent censorship.</source>
|
Unlike older protocols such as VMess, VLESS, and the XTLS-Vision transport, REALITY's innovative "friend or foe" recognition at the TLS handshake enhances security and circumvents detection by sophisticated DPI systems employing active probing techniques. This makes REALITY a robust solution for maintaining internet freedom in environments with stringent censorship.</source>
|
||||||
<translation>پروتکل REALITY، یک توسعه پیشگامانه توسط خالقان XRay، بهطور خاص برای مقابله با بالاترین سطح سانسور اینترنتی طراحی شده است و از رویکرد نوآورانهای برای دور زدن محدودیتها استفاده میکند.
|
<translation type="unfinished"></translation>
|
||||||
|
|
||||||
REALITY بهطور منحصربهفردی سانسورچیان را در مرحله دستدهی TLS شناسایی میکند و بهصورت یکپارچه بهعنوان پراکسی برای کاربران قانونی عمل میکند، در حالی که سانسورچیان را به سایتهای معتبر مانند google.com هدایت میکند و در نتیجه یک گواهی TLS واقعی و دادههای اصلی ارائه میدهد.
|
|
||||||
|
|
||||||
این قابلیت پیشرفته، REALITY را از فناوریهای مشابه متمایز میکند، زیرا میتواند ترافیک وب را بدون نیاز به پیکربندیهای خاص، بهعنوان ترافیک از سایتهای تصادفی و معتبر جا بزند. برخلاف پروتکلهای قدیمیتر مانند VMess، VLESS و انتقال XTLS-Vision، تشخیص نوآورانه "دوست یا دشمن" REALITY در مرحله دستدهی TLS امنیت را افزایش داده و از شناسایی توسط سیستمهای پیشرفته DPI که از تکنیکهای پروب فعال استفاده میکنند، جلوگیری میکند. این ویژگی REALITY را به یک راهحل قوی برای حفظ آزادی اینترنت در محیطهایی با سانسور شدید تبدیل میکند.</translation>
|
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../containers/containers_defs.cpp" line="230"/>
|
<location filename="../containers/containers_defs.cpp" line="230"/>
|
||||||
@@ -3669,7 +3665,7 @@ For more detailed information, you can
|
|||||||
<location filename="../containers/containers_defs.cpp" line="104"/>
|
<location filename="../containers/containers_defs.cpp" line="104"/>
|
||||||
<location filename="../containers/containers_defs.cpp" line="248"/>
|
<location filename="../containers/containers_defs.cpp" line="248"/>
|
||||||
<source>SOCKS5 proxy server</source>
|
<source>SOCKS5 proxy server</source>
|
||||||
<translation>سرور پروکسی SOCKS5</translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../3rd/qtkeychain/qtkeychain/libsecret.cpp" line="119"/>
|
<location filename="../3rd/qtkeychain/qtkeychain/libsecret.cpp" line="119"/>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,9 @@
|
|||||||
|
|
||||||
#include "core/controllers/vpnConfigurationController.h"
|
#include "core/controllers/vpnConfigurationController.h"
|
||||||
#include "systemController.h"
|
#include "systemController.h"
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
#include "platforms/android/android_utils.h"
|
||||||
|
#endif
|
||||||
#include "qrcodegen.hpp"
|
#include "qrcodegen.hpp"
|
||||||
|
|
||||||
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
|
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
|
||||||
@@ -21,6 +24,12 @@ ExportController::ExportController(const QSharedPointer<ServersModel> &serversMo
|
|||||||
m_clientManagementModel(clientManagementModel),
|
m_clientManagementModel(clientManagementModel),
|
||||||
m_settings(settings)
|
m_settings(settings)
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
m_authResultNotifier.reset(new AuthResultNotifier);
|
||||||
|
m_authResultReceiver.reset(new AuthResultReceiver(m_authResultNotifier));
|
||||||
|
connect(m_authResultNotifier.get(), &AuthResultNotifier::authFailed, this, [this]() { emit exportErrorOccurred(tr("Access error!")); });
|
||||||
|
connect(m_authResultNotifier.get(), &AuthResultNotifier::authSuccessful, this, &ExportController::generateFullAccessConfig);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportController::generateFullAccessConfig()
|
void ExportController::generateFullAccessConfig()
|
||||||
@@ -54,6 +63,26 @@ void ExportController::generateFullAccessConfig()
|
|||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(Q_OS_ANDROID)
|
||||||
|
void ExportController::generateFullAccessConfigAndroid()
|
||||||
|
{
|
||||||
|
/* We use builtin keyguard for ssh key export protection on Android */
|
||||||
|
QJniObject activity = AndroidUtils::getActivity();
|
||||||
|
auto appContext = activity.callObjectMethod("getApplicationContext", "()Landroid/content/Context;");
|
||||||
|
if (appContext.isValid()) {
|
||||||
|
auto intent = QJniObject::callStaticObjectMethod("org/amnezia/vpn/AuthHelper", "getAuthIntent",
|
||||||
|
"(Landroid/content/Context;)Landroid/content/Intent;", appContext.object());
|
||||||
|
if (intent.isValid()) {
|
||||||
|
if (intent.object<jobject>() != nullptr) {
|
||||||
|
QtAndroidPrivate::startActivity(intent.object<jobject>(), 1, m_authResultReceiver.get());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
generateFullAccessConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void ExportController::generateConnectionConfig(const QString &clientName)
|
void ExportController::generateConnectionConfig(const QString &clientName)
|
||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#include "ui/models/clientManagementModel.h"
|
#include "ui/models/clientManagementModel.h"
|
||||||
#include "ui/models/containers_model.h"
|
#include "ui/models/containers_model.h"
|
||||||
#include "ui/models/servers_model.h"
|
#include "ui/models/servers_model.h"
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
#include "platforms/android/authResultReceiver.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class ExportController : public QObject
|
class ExportController : public QObject
|
||||||
{
|
{
|
||||||
@@ -22,6 +25,9 @@ public:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void generateFullAccessConfig();
|
void generateFullAccessConfig();
|
||||||
|
#if defined(Q_OS_ANDROID)
|
||||||
|
void generateFullAccessConfigAndroid();
|
||||||
|
#endif
|
||||||
void generateConnectionConfig(const QString &clientName);
|
void generateConnectionConfig(const QString &clientName);
|
||||||
void generateOpenVpnConfig(const QString &clientName);
|
void generateOpenVpnConfig(const QString &clientName);
|
||||||
void generateWireGuardConfig(const QString &clientName);
|
void generateWireGuardConfig(const QString &clientName);
|
||||||
@@ -68,6 +74,11 @@ private:
|
|||||||
QString m_config;
|
QString m_config;
|
||||||
QString m_nativeConfigString;
|
QString m_nativeConfigString;
|
||||||
QList<QString> m_qrCodes;
|
QList<QString> m_qrCodes;
|
||||||
|
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
QSharedPointer<AuthResultNotifier> m_authResultNotifier;
|
||||||
|
QSharedPointer<QAndroidActivityResultReceiver> m_authResultReceiver;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // EXPORTCONTROLLER_H
|
#endif // EXPORTCONTROLLER_H
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
#include <QStandardPaths>
|
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include "core/errorstrings.h"
|
|
||||||
#include "core/serialization/serialization.h"
|
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
#include "core/serialization/serialization.h"
|
||||||
|
#include "core/errorstrings.h"
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
#include "platforms/android/android_controller.h"
|
#include "platforms/android/android_controller.h"
|
||||||
@@ -96,40 +96,36 @@ bool ImportController::extractConfigFromData(QString data)
|
|||||||
|
|
||||||
if (config.startsWith("vless://")) {
|
if (config.startsWith("vless://")) {
|
||||||
m_configType = ConfigTypes::Xray;
|
m_configType = ConfigTypes::Xray;
|
||||||
m_config = extractXrayConfig(
|
m_config = extractXrayConfig(Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg),
|
||||||
Utils::JsonToString(serialization::vless::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
|
QJsonDocument::JsonFormat::Compact), prefix);
|
||||||
prefix);
|
|
||||||
return m_config.empty() ? false : true;
|
return m_config.empty() ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.startsWith("vmess://") && config.contains("@")) {
|
if (config.startsWith("vmess://") && config.contains("@")) {
|
||||||
m_configType = ConfigTypes::Xray;
|
m_configType = ConfigTypes::Xray;
|
||||||
m_config = extractXrayConfig(
|
m_config = extractXrayConfig(Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg),
|
||||||
Utils::JsonToString(serialization::vmess_new::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
|
QJsonDocument::JsonFormat::Compact), prefix);
|
||||||
prefix);
|
|
||||||
return m_config.empty() ? false : true;
|
return m_config.empty() ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.startsWith("vmess://")) {
|
if (config.startsWith("vmess://")) {
|
||||||
m_configType = ConfigTypes::Xray;
|
m_configType = ConfigTypes::Xray;
|
||||||
m_config = extractXrayConfig(
|
m_config = extractXrayConfig(Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg),
|
||||||
Utils::JsonToString(serialization::vmess::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
|
QJsonDocument::JsonFormat::Compact), prefix);
|
||||||
prefix);
|
|
||||||
return m_config.empty() ? false : true;
|
return m_config.empty() ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.startsWith("trojan://")) {
|
if (config.startsWith("trojan://")) {
|
||||||
m_configType = ConfigTypes::Xray;
|
m_configType = ConfigTypes::Xray;
|
||||||
m_config = extractXrayConfig(
|
m_config = extractXrayConfig(Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg),
|
||||||
Utils::JsonToString(serialization::trojan::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact),
|
QJsonDocument::JsonFormat::Compact), prefix);
|
||||||
prefix);
|
|
||||||
return m_config.empty() ? false : true;
|
return m_config.empty() ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.startsWith("ss://") && !config.contains("plugin=")) {
|
if (config.startsWith("ss://") && !config.contains("plugin=")) {
|
||||||
m_configType = ConfigTypes::ShadowSocks;
|
m_configType = ConfigTypes::ShadowSocks;
|
||||||
m_config = extractXrayConfig(
|
m_config = extractXrayConfig(Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg),
|
||||||
Utils::JsonToString(serialization::ss::Deserialize(config, &prefix, &errormsg), QJsonDocument::JsonFormat::Compact), prefix);
|
QJsonDocument::JsonFormat::Compact), prefix);
|
||||||
return m_config.empty() ? false : true;
|
return m_config.empty() ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +173,6 @@ bool ImportController::extractConfigFromData(QString data)
|
|||||||
}
|
}
|
||||||
case ConfigTypes::Amnezia: {
|
case ConfigTypes::Amnezia: {
|
||||||
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
|
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
|
||||||
processAmneziaConfig(m_config);
|
|
||||||
if (!m_config.empty()) {
|
if (!m_config.empty()) {
|
||||||
checkForMaliciousStrings(m_config);
|
checkForMaliciousStrings(m_config);
|
||||||
return true;
|
return true;
|
||||||
@@ -358,19 +353,20 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
|||||||
QJsonObject lastConfig;
|
QJsonObject lastConfig;
|
||||||
lastConfig[config_key::config] = data;
|
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 hostName;
|
||||||
QString port;
|
QString port;
|
||||||
if (!url.host().isEmpty()) {
|
if (hostNameAndPortMatch.hasCaptured(1)) {
|
||||||
hostName = url.host();
|
hostName = hostNameAndPortMatch.captured(1);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Key parameter 'Endpoint' is missing or has an invalid format";
|
qDebug() << "Key parameter 'Endpoint' is missing";
|
||||||
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
|
emit importErrorOccurred(ErrorCode::ImportInvalidConfigError, false);
|
||||||
return QJsonObject();
|
return QJsonObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.port() != -1) {
|
if (hostNameAndPortMatch.hasCaptured(2)) {
|
||||||
port = QString::number(url.port());
|
port = hostNameAndPortMatch.captured(2);
|
||||||
} else {
|
} else {
|
||||||
port = protocols::wireguard::defaultPort;
|
port = protocols::wireguard::defaultPort;
|
||||||
}
|
}
|
||||||
@@ -427,12 +423,6 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
|||||||
m_configType = ConfigTypes::Awg;
|
m_configType = ConfigTypes::Awg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!configMap.value("MTU").isEmpty()) {
|
|
||||||
lastConfig[config_key::mtu] = configMap.value("MTU");
|
|
||||||
} else {
|
|
||||||
lastConfig[config_key::mtu] = protocolName == "awg" ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject wireguardConfig;
|
QJsonObject wireguardConfig;
|
||||||
wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson());
|
wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson());
|
||||||
wireguardConfig[config_key::isThirdPartyConfig] = true;
|
wireguardConfig[config_key::isThirdPartyConfig] = true;
|
||||||
@@ -660,28 +650,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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -68,8 +68,6 @@ private:
|
|||||||
|
|
||||||
void checkForMaliciousStrings(const QJsonObject &protocolConfig);
|
void checkForMaliciousStrings(const QJsonObject &protocolConfig);
|
||||||
|
|
||||||
void processAmneziaConfig(QJsonObject &config);
|
|
||||||
|
|
||||||
#if defined Q_OS_ANDROID || defined Q_OS_IOS
|
#if defined Q_OS_ANDROID || defined Q_OS_IOS
|
||||||
void stopDecodingQr();
|
void stopDecodingQr();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -799,7 +799,7 @@ void InstallController::addEmptyServer()
|
|||||||
|
|
||||||
bool InstallController::fillAvailableServices()
|
bool InstallController::fillAvailableServices()
|
||||||
{
|
{
|
||||||
ApiController apiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
|
ApiController apiController(m_settings->getGatewayEndpoint());
|
||||||
|
|
||||||
QByteArray responseBody;
|
QByteArray responseBody;
|
||||||
ErrorCode errorCode = apiController.getServicesList(responseBody);
|
ErrorCode errorCode = apiController.getServicesList(responseBody);
|
||||||
@@ -821,7 +821,7 @@ bool InstallController::installServiceFromApi()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiController apiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
|
ApiController apiController(m_settings->getGatewayEndpoint());
|
||||||
QJsonObject serverConfig;
|
QJsonObject serverConfig;
|
||||||
|
|
||||||
ErrorCode errorCode = apiController.getConfigForService(m_settings->getInstallationUuid(true), m_apiServicesModel->getCountryCode(),
|
ErrorCode errorCode = apiController.getConfigForService(m_settings->getInstallationUuid(true), m_apiServicesModel->getCountryCode(),
|
||||||
@@ -849,7 +849,7 @@ bool InstallController::installServiceFromApi()
|
|||||||
bool InstallController::updateServiceFromApi(const int serverIndex, const QString &newCountryCode, const QString &newCountryName,
|
bool InstallController::updateServiceFromApi(const int serverIndex, const QString &newCountryCode, const QString &newCountryName,
|
||||||
bool reloadServiceConfig)
|
bool reloadServiceConfig)
|
||||||
{
|
{
|
||||||
ApiController apiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
|
ApiController apiController(m_settings->getGatewayEndpoint());
|
||||||
|
|
||||||
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||||
auto apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
auto apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
||||||
@@ -885,7 +885,7 @@ bool InstallController::updateServiceFromApi(const int serverIndex, const QStrin
|
|||||||
|
|
||||||
void InstallController::updateServiceFromTelegram(const int serverIndex)
|
void InstallController::updateServiceFromTelegram(const int serverIndex)
|
||||||
{
|
{
|
||||||
ApiController *apiController = new ApiController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv());
|
ApiController *apiController = new ApiController(m_settings->getGatewayEndpoint());
|
||||||
|
|
||||||
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
#include "platforms/android/android_controller.h"
|
#include "platforms/android/android_controller.h"
|
||||||
|
#include "platforms/android/android_utils.h"
|
||||||
|
#include <QJniObject>
|
||||||
#endif
|
#endif
|
||||||
#if defined Q_OS_MAC
|
#if defined Q_OS_MAC
|
||||||
#include "ui/macos_util.h"
|
#include "ui/macos_util.h"
|
||||||
@@ -20,8 +22,18 @@ PageController::PageController(const QSharedPointer<ServersModel> &serversModel,
|
|||||||
: QObject(parent), m_serversModel(serversModel), m_settings(settings)
|
: QObject(parent), m_serversModel(serversModel), m_settings(settings)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
|
// Change color of navigation and status bar's
|
||||||
auto initialPageNavigationBarColor = getInitialPageNavigationBarColor();
|
auto initialPageNavigationBarColor = getInitialPageNavigationBarColor();
|
||||||
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
|
#endif
|
||||||
|
|
||||||
#if defined Q_OS_MACX
|
#if defined Q_OS_MACX
|
||||||
@@ -103,7 +115,14 @@ unsigned int PageController::getInitialPageNavigationBarColor()
|
|||||||
void PageController::updateNavigationBarColor(const int color)
|
void PageController::updateNavigationBarColor(const int color)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_ANDROID
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +131,7 @@ void PageController::showOnStartup()
|
|||||||
if (!m_settings->isStartMinimized()) {
|
if (!m_settings->isStartMinimized()) {
|
||||||
emit raiseMainWindow();
|
emit raiseMainWindow();
|
||||||
} else {
|
} else {
|
||||||
#if defined(Q_OS_WIN) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
|
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX)
|
||||||
emit hideMainWindow();
|
emit hideMainWindow();
|
||||||
#elif defined Q_OS_MACX
|
#elif defined Q_OS_MACX
|
||||||
setDockIconVisible(false);
|
setDockIconVisible(false);
|
||||||
|
|||||||
@@ -59,9 +59,6 @@ namespace PageLoader
|
|||||||
PageProtocolIKev2Settings,
|
PageProtocolIKev2Settings,
|
||||||
PageProtocolRaw,
|
PageProtocolRaw,
|
||||||
|
|
||||||
PageProtocolWireGuardClientSettings,
|
|
||||||
PageProtocolAwgClientSettings,
|
|
||||||
|
|
||||||
PageShareFullAccess,
|
PageShareFullAccess,
|
||||||
|
|
||||||
PageDevMenu
|
PageDevMenu
|
||||||
|
|||||||
@@ -88,12 +88,7 @@ void SettingsController::toggleLogging(bool enable)
|
|||||||
|
|
||||||
void SettingsController::openLogsFolder()
|
void SettingsController::openLogsFolder()
|
||||||
{
|
{
|
||||||
Logger::openLogsFolder(false);
|
Logger::openLogsFolder();
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsController::openServiceLogsFolder()
|
|
||||||
{
|
|
||||||
Logger::openLogsFolder(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsController::exportLogsFile(const QString &fileName)
|
void SettingsController::exportLogsFile(const QString &fileName)
|
||||||
@@ -105,21 +100,12 @@ void SettingsController::exportLogsFile(const QString &fileName)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsController::exportServiceLogsFile(const QString &fileName)
|
|
||||||
{
|
|
||||||
#ifdef Q_OS_ANDROID
|
|
||||||
AndroidController::instance()->exportLogsFile(fileName);
|
|
||||||
#else
|
|
||||||
SystemController::saveFile(fileName, Logger::getServiceLogFile());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsController::clearLogs()
|
void SettingsController::clearLogs()
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
AndroidController::instance()->clearLogs();
|
AndroidController::instance()->clearLogs();
|
||||||
#else
|
#else
|
||||||
Logger::clearLogs(false);
|
Logger::clearLogs();
|
||||||
Logger::clearServiceLogs();
|
Logger::clearServiceLogs();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -297,31 +283,5 @@ void SettingsController::setGatewayEndpoint(const QString &endpoint)
|
|||||||
|
|
||||||
QString SettingsController::getGatewayEndpoint()
|
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(bool isDevModeEnabled READ isDevModeEnabled NOTIFY devModeEnabled)
|
||||||
Q_PROPERTY(QString gatewayEndpoint READ getGatewayEndpoint WRITE setGatewayEndpoint NOTIFY gatewayEndpointChanged)
|
Q_PROPERTY(QString gatewayEndpoint READ getGatewayEndpoint WRITE setGatewayEndpoint NOTIFY gatewayEndpointChanged)
|
||||||
Q_PROPERTY(bool isDevGatewayEnv READ isDevGatewayEnv WRITE toggleDevGatewayEnv NOTIFY devGatewayEnvChanged)
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void toggleAmneziaDns(bool enable);
|
void toggleAmneziaDns(bool enable);
|
||||||
@@ -43,9 +42,7 @@ public slots:
|
|||||||
void toggleLogging(bool enable);
|
void toggleLogging(bool enable);
|
||||||
|
|
||||||
void openLogsFolder();
|
void openLogsFolder();
|
||||||
void openServiceLogsFolder();
|
|
||||||
void exportLogsFile(const QString &fileName);
|
void exportLogsFile(const QString &fileName);
|
||||||
void exportServiceLogsFile(const QString &fileName);
|
|
||||||
void clearLogs();
|
void clearLogs();
|
||||||
|
|
||||||
void backupAppConfig(const QString &fileName);
|
void backupAppConfig(const QString &fileName);
|
||||||
@@ -84,10 +81,6 @@ public slots:
|
|||||||
void resetGatewayEndpoint();
|
void resetGatewayEndpoint();
|
||||||
void setGatewayEndpoint(const QString &endpoint);
|
void setGatewayEndpoint(const QString &endpoint);
|
||||||
QString getGatewayEndpoint();
|
QString getGatewayEndpoint();
|
||||||
bool isDevGatewayEnv();
|
|
||||||
void toggleDevGatewayEnv(bool enabled);
|
|
||||||
|
|
||||||
bool isOnTv();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void primaryDnsChanged();
|
void primaryDnsChanged();
|
||||||
@@ -110,7 +103,6 @@ signals:
|
|||||||
|
|
||||||
void devModeEnabled();
|
void devModeEnabled();
|
||||||
void gatewayEndpointChanged(const QString &endpoint);
|
void gatewayEndpointChanged(const QString &endpoint);
|
||||||
void devGatewayEnvChanged(bool enabled);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
QSharedPointer<ServersModel> m_serversModel;
|
||||||
|
|||||||
@@ -125,12 +125,3 @@ void SystemController::setQmlRoot(QObject *qmlRoot)
|
|||||||
{
|
{
|
||||||
m_qmlRoot = qmlRoot;
|
m_qmlRoot = qmlRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SystemController::isAuthenticated()
|
|
||||||
{
|
|
||||||
#ifdef Q_OS_ANDROID
|
|
||||||
return AndroidController::instance()->requestAuthentication();
|
|
||||||
#else
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ public slots:
|
|||||||
|
|
||||||
void setQmlRoot(QObject *qmlRoot);
|
void setQmlRoot(QObject *qmlRoot);
|
||||||
|
|
||||||
bool isAuthenticated();
|
|
||||||
signals:
|
signals:
|
||||||
void fileDialogClosed(const bool isAccepted);
|
void fileDialogClosed(const bool isAccepted);
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ namespace
|
|||||||
constexpr char availableCountries[] = "available_countries";
|
constexpr char availableCountries[] = "available_countries";
|
||||||
|
|
||||||
constexpr char storeEndpoint[] = "store_endpoint";
|
constexpr char storeEndpoint[] = "store_endpoint";
|
||||||
|
|
||||||
constexpr char isAvailable[] = "is_available";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace serviceType
|
namespace serviceType
|
||||||
@@ -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. "
|
return tr("Classic VPN for comfortable work, downloading large files and watching videos. "
|
||||||
"Works for any sites. Speed up to %1 MBit/s")
|
"Works for any sites. Speed up to %1 MBit/s")
|
||||||
.arg(speed);
|
.arg(speed);
|
||||||
} else if (serviceType == serviceType::amneziaFree){
|
} else {
|
||||||
QString description = tr("VPN to access blocked sites in regions with high levels of Internet censorship. ");
|
return tr("VPN to access blocked sites in regions with high levels of Internet censorship. ");
|
||||||
if (service.value(configKey::isAvailable).isBool() && !service.value(configKey::isAvailable).toBool()) {
|
|
||||||
description += tr("<p><a style=\"color: #EB5757;\">Not available in your region. If you have VPN enabled, disable it, return to the previous screen, and try again.</a>");
|
|
||||||
}
|
|
||||||
return description;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ServiceDescriptionRole: {
|
case ServiceDescriptionRole: {
|
||||||
@@ -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");
|
return tr("Amnezia Free is a free VPN to bypass blocking in countries with high levels of internet censorship");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case IsServiceAvailableRole: {
|
|
||||||
if (serviceType == serviceType::amneziaFree) {
|
|
||||||
if (service.value(configKey::isAvailable).isBool() && !service.value(configKey::isAvailable).toBool()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case SpeedRole: {
|
case SpeedRole: {
|
||||||
auto speed = serviceInfo.value(configKey::speed).toString();
|
auto speed = serviceInfo.value(configKey::speed).toString();
|
||||||
return tr("%1 MBit/s").arg(speed);
|
return tr("%1 MBit/s").arg(speed);
|
||||||
@@ -207,7 +193,6 @@ QHash<int, QByteArray> ApiServicesModel::roleNames() const
|
|||||||
roles[NameRole] = "name";
|
roles[NameRole] = "name";
|
||||||
roles[CardDescriptionRole] = "cardDescription";
|
roles[CardDescriptionRole] = "cardDescription";
|
||||||
roles[ServiceDescriptionRole] = "serviceDescription";
|
roles[ServiceDescriptionRole] = "serviceDescription";
|
||||||
roles[IsServiceAvailableRole] = "isServiceAvailable";
|
|
||||||
roles[SpeedRole] = "speed";
|
roles[SpeedRole] = "speed";
|
||||||
roles[WorkPeriodRole] = "workPeriod";
|
roles[WorkPeriodRole] = "workPeriod";
|
||||||
roles[RegionRole] = "region";
|
roles[RegionRole] = "region";
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ public:
|
|||||||
NameRole = Qt::UserRole + 1,
|
NameRole = Qt::UserRole + 1,
|
||||||
CardDescriptionRole,
|
CardDescriptionRole,
|
||||||
ServiceDescriptionRole,
|
ServiceDescriptionRole,
|
||||||
IsServiceAvailableRole,
|
|
||||||
SpeedRole,
|
SpeedRole,
|
||||||
WorkPeriodRole,
|
WorkPeriodRole,
|
||||||
RegionRole,
|
RegionRole,
|
||||||
|
|||||||
@@ -21,30 +21,17 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, 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::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
|
case Roles::JunkPacketCountRole: m_protocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
||||||
case Roles::ClientJunkPacketCountRole: m_clientProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
case Roles::JunkPacketMinSizeRole: m_protocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
||||||
case Roles::ClientJunkPacketMinSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
case Roles::JunkPacketMaxSizeRole: m_protocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
||||||
case Roles::ClientJunkPacketMaxSizeRole: m_clientProtocolConfig.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::ServerJunkPacketCountRole: m_serverProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
case Roles::InitPacketMagicHeaderRole: m_protocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break;
|
||||||
case Roles::ServerJunkPacketMinSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
case Roles::ResponsePacketMagicHeaderRole: m_protocolConfig.insert(config_key::responsePacketMagicHeader, value.toString()); break;
|
||||||
case Roles::ServerJunkPacketMaxSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
case Roles::UnderloadPacketMagicHeaderRole: m_protocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString()); break;
|
||||||
case Roles::ServerInitPacketJunkSizeRole: m_serverProtocolConfig.insert(config_key::initPacketJunkSize, value.toString()); break;
|
case Roles::TransportPacketMagicHeaderRole: m_protocolConfig.insert(config_key::transportPacketMagicHeader, value.toString()); break;
|
||||||
case Roles::ServerResponsePacketJunkSizeRole:
|
|
||||||
m_serverProtocolConfig.insert(config_key::responsePacketJunkSize, value.toString());
|
|
||||||
break;
|
|
||||||
case Roles::ServerInitPacketMagicHeaderRole: m_serverProtocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break;
|
|
||||||
case Roles::ServerResponsePacketMagicHeaderRole:
|
|
||||||
m_serverProtocolConfig.insert(config_key::responsePacketMagicHeader, value.toString());
|
|
||||||
break;
|
|
||||||
case Roles::ServerUnderloadPacketMagicHeaderRole:
|
|
||||||
m_serverProtocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString());
|
|
||||||
break;
|
|
||||||
case Roles::ServerTransportPacketMagicHeaderRole:
|
|
||||||
m_serverProtocolConfig.insert(config_key::transportPacketMagicHeader, value.toString());
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit dataChanged(index, index, QList { role });
|
emit dataChanged(index, index, QList { role });
|
||||||
@@ -58,22 +45,17 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
|
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
|
||||||
|
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString();
|
||||||
case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
|
case Roles::JunkPacketCountRole: return m_protocolConfig.value(config_key::junkPacketCount);
|
||||||
case Roles::ClientJunkPacketCountRole: return m_clientProtocolConfig.value(config_key::junkPacketCount);
|
case Roles::JunkPacketMinSizeRole: return m_protocolConfig.value(config_key::junkPacketMinSize);
|
||||||
case Roles::ClientJunkPacketMinSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMinSize);
|
case Roles::JunkPacketMaxSizeRole: return m_protocolConfig.value(config_key::junkPacketMaxSize);
|
||||||
case Roles::ClientJunkPacketMaxSizeRole: return m_clientProtocolConfig.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::ServerJunkPacketCountRole: return m_serverProtocolConfig.value(config_key::junkPacketCount);
|
case Roles::InitPacketMagicHeaderRole: return m_protocolConfig.value(config_key::initPacketMagicHeader);
|
||||||
case Roles::ServerJunkPacketMinSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMinSize);
|
case Roles::ResponsePacketMagicHeaderRole: return m_protocolConfig.value(config_key::responsePacketMagicHeader);
|
||||||
case Roles::ServerJunkPacketMaxSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMaxSize);
|
case Roles::UnderloadPacketMagicHeaderRole: return m_protocolConfig.value(config_key::underloadPacketMagicHeader);
|
||||||
case Roles::ServerInitPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::initPacketJunkSize);
|
case Roles::TransportPacketMagicHeaderRole: return m_protocolConfig.value(config_key::transportPacketMagicHeader);
|
||||||
case Roles::ServerResponsePacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::responsePacketJunkSize);
|
|
||||||
case Roles::ServerInitPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::initPacketMagicHeader);
|
|
||||||
case Roles::ServerResponsePacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::responsePacketMagicHeader);
|
|
||||||
case Roles::ServerUnderloadPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::underloadPacketMagicHeader);
|
|
||||||
case Roles::ServerTransportPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::transportPacketMagicHeader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@@ -86,63 +68,51 @@ void AwgConfigModel::updateModel(const QJsonObject &config)
|
|||||||
|
|
||||||
m_fullConfig = 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);
|
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Awg), Proto::Awg);
|
||||||
m_serverProtocolConfig.insert(config_key::transport_proto,
|
m_protocolConfig.insert(config_key::transport_proto, protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
||||||
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config);
|
||||||
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
|
m_protocolConfig[config_key::port] = protocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||||
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
m_protocolConfig[config_key::mtu] = protocolConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu);
|
||||||
m_serverProtocolConfig[config_key::junkPacketCount] =
|
m_protocolConfig[config_key::junkPacketCount] =
|
||||||
serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
protocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||||
m_serverProtocolConfig[config_key::junkPacketMinSize] =
|
m_protocolConfig[config_key::junkPacketMinSize] =
|
||||||
serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
protocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||||
m_serverProtocolConfig[config_key::junkPacketMaxSize] =
|
m_protocolConfig[config_key::junkPacketMaxSize] =
|
||||||
serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
protocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||||
m_serverProtocolConfig[config_key::initPacketJunkSize] =
|
m_protocolConfig[config_key::initPacketJunkSize] =
|
||||||
serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
protocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
||||||
m_serverProtocolConfig[config_key::responsePacketJunkSize] =
|
m_protocolConfig[config_key::responsePacketJunkSize] =
|
||||||
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
protocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
||||||
m_serverProtocolConfig[config_key::initPacketMagicHeader] =
|
m_protocolConfig[config_key::initPacketMagicHeader] =
|
||||||
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
protocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||||
m_serverProtocolConfig[config_key::responsePacketMagicHeader] =
|
m_protocolConfig[config_key::responsePacketMagicHeader] =
|
||||||
serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
|
protocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
|
||||||
m_serverProtocolConfig[config_key::underloadPacketMagicHeader] =
|
m_protocolConfig[config_key::underloadPacketMagicHeader] =
|
||||||
serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
protocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
||||||
m_serverProtocolConfig[config_key::transportPacketMagicHeader] =
|
m_protocolConfig[config_key::transportPacketMagicHeader] =
|
||||||
serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
|
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();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject AwgConfigModel::getConfig()
|
QJsonObject AwgConfigModel::getConfig()
|
||||||
{
|
{
|
||||||
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
|
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
|
||||||
const AwgConfig newConfig(m_serverProtocolConfig);
|
const AwgConfig newConfig(m_protocolConfig);
|
||||||
|
|
||||||
if (!oldConfig.hasEqualServerSettings(newConfig)) {
|
if (!oldConfig.hasEqualServerSettings(newConfig)) {
|
||||||
m_serverProtocolConfig.remove(config_key::last_config);
|
m_protocolConfig.remove(config_key::last_config);
|
||||||
} else {
|
} 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();
|
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||||
jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu];
|
jsonConfig[config_key::mtu] = newConfig.mtu;
|
||||||
jsonConfig[config_key::junkPacketCount] = m_clientProtocolConfig[config_key::junkPacketCount];
|
|
||||||
jsonConfig[config_key::junkPacketMinSize] = m_clientProtocolConfig[config_key::junkPacketMinSize];
|
|
||||||
jsonConfig[config_key::junkPacketMaxSize] = m_clientProtocolConfig[config_key::junkPacketMaxSize];
|
|
||||||
|
|
||||||
m_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;
|
return m_fullConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,73 +126,50 @@ bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2)
|
|||||||
return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2);
|
return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AwgConfigModel::isServerSettingsEqual()
|
|
||||||
{
|
|
||||||
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
|
|
||||||
const AwgConfig newConfig(m_serverProtocolConfig);
|
|
||||||
|
|
||||||
return oldConfig.hasEqualServerSettings(newConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, QByteArray> AwgConfigModel::roleNames() const
|
QHash<int, QByteArray> AwgConfigModel::roleNames() const
|
||||||
{
|
{
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
|
|
||||||
roles[PortRole] = "port";
|
roles[PortRole] = "port";
|
||||||
|
roles[MtuRole] = "mtu";
|
||||||
roles[ClientMtuRole] = "clientMtu";
|
roles[JunkPacketCountRole] = "junkPacketCount";
|
||||||
roles[ClientJunkPacketCountRole] = "clientJunkPacketCount";
|
roles[JunkPacketMinSizeRole] = "junkPacketMinSize";
|
||||||
roles[ClientJunkPacketMinSizeRole] = "clientJunkPacketMinSize";
|
roles[JunkPacketMaxSizeRole] = "junkPacketMaxSize";
|
||||||
roles[ClientJunkPacketMaxSizeRole] = "clientJunkPacketMaxSize";
|
roles[InitPacketJunkSizeRole] = "initPacketJunkSize";
|
||||||
|
roles[ResponsePacketJunkSizeRole] = "responsePacketJunkSize";
|
||||||
roles[ServerJunkPacketCountRole] = "serverJunkPacketCount";
|
roles[InitPacketMagicHeaderRole] = "initPacketMagicHeader";
|
||||||
roles[ServerJunkPacketMinSizeRole] = "serverJunkPacketMinSize";
|
roles[ResponsePacketMagicHeaderRole] = "responsePacketMagicHeader";
|
||||||
roles[ServerJunkPacketMaxSizeRole] = "serverJunkPacketMaxSize";
|
roles[UnderloadPacketMagicHeaderRole] = "underloadPacketMagicHeader";
|
||||||
roles[ServerInitPacketJunkSizeRole] = "serverInitPacketJunkSize";
|
roles[TransportPacketMagicHeaderRole] = "transportPacketMagicHeader";
|
||||||
roles[ServerResponsePacketJunkSizeRole] = "serverResponsePacketJunkSize";
|
|
||||||
roles[ServerInitPacketMagicHeaderRole] = "serverInitPacketMagicHeader";
|
|
||||||
roles[ServerResponsePacketMagicHeaderRole] = "serverResponsePacketMagicHeader";
|
|
||||||
roles[ServerUnderloadPacketMagicHeaderRole] = "serverUnderloadPacketMagicHeader";
|
|
||||||
roles[ServerTransportPacketMagicHeaderRole] = "serverTransportPacketMagicHeader";
|
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig)
|
AwgConfig::AwgConfig(const QJsonObject &jsonConfig)
|
||||||
{
|
{
|
||||||
auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString();
|
port = jsonConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||||
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
mtu = jsonConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu);
|
||||||
clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::awg::defaultMtu);
|
junkPacketCount = jsonConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||||
clientJunkPacketCount = clientProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
junkPacketMinSize = jsonConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||||
clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
junkPacketMaxSize = jsonConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||||
clientJunkPacketMaxSize = clientProtocolConfig.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);
|
||||||
port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
initPacketMagicHeader = jsonConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||||
serverJunkPacketCount = serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
responsePacketMagicHeader =
|
||||||
serverJunkPacketMinSize = serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
jsonConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
|
||||||
serverJunkPacketMaxSize = serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
underloadPacketMagicHeader =
|
||||||
serverInitPacketJunkSize = serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
jsonConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
||||||
serverResponsePacketJunkSize =
|
transportPacketMagicHeader =
|
||||||
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
jsonConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
|
||||||
serverInitPacketMagicHeader =
|
|
||||||
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
|
||||||
serverResponsePacketMagicHeader =
|
|
||||||
serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
|
|
||||||
serverUnderloadPacketMagicHeader =
|
|
||||||
serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
|
||||||
serverTransportPacketMagicHeader =
|
|
||||||
serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
|
bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
|
||||||
{
|
{
|
||||||
if (port != other.port || serverJunkPacketCount != other.serverJunkPacketCount
|
if (port != other.port || junkPacketCount != other.junkPacketCount || junkPacketMinSize != other.junkPacketMinSize
|
||||||
|| serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize
|
|| junkPacketMaxSize != other.junkPacketMaxSize || initPacketJunkSize != other.initPacketJunkSize
|
||||||
|| serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize
|
|| responsePacketJunkSize != other.responsePacketJunkSize || initPacketMagicHeader != other.initPacketMagicHeader
|
||||||
|| serverInitPacketMagicHeader != other.serverInitPacketMagicHeader
|
|| responsePacketMagicHeader != other.responsePacketMagicHeader || underloadPacketMagicHeader != other.underloadPacketMagicHeader
|
||||||
|| serverResponsePacketMagicHeader != other.serverResponsePacketMagicHeader
|
|| transportPacketMagicHeader != other.transportPacketMagicHeader) {
|
||||||
|| serverUnderloadPacketMagicHeader != other.serverUnderloadPacketMagicHeader
|
|
||||||
|| serverTransportPacketMagicHeader != other.serverTransportPacketMagicHeader) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -230,8 +177,7 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
|
|||||||
|
|
||||||
bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const
|
bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const
|
||||||
{
|
{
|
||||||
if (clientMtu != other.clientMtu || clientJunkPacketCount != other.clientJunkPacketCount
|
if (mtu != other.mtu) {
|
||||||
|| clientJunkPacketMinSize != other.clientJunkPacketMinSize || clientJunkPacketMaxSize != other.clientJunkPacketMaxSize) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -16,21 +16,16 @@ struct AwgConfig
|
|||||||
AwgConfig(const QJsonObject &jsonConfig);
|
AwgConfig(const QJsonObject &jsonConfig);
|
||||||
|
|
||||||
QString port;
|
QString port;
|
||||||
|
QString mtu;
|
||||||
QString clientMtu;
|
QString junkPacketCount;
|
||||||
QString clientJunkPacketCount;
|
QString junkPacketMinSize;
|
||||||
QString clientJunkPacketMinSize;
|
QString junkPacketMaxSize;
|
||||||
QString clientJunkPacketMaxSize;
|
QString initPacketJunkSize;
|
||||||
|
QString responsePacketJunkSize;
|
||||||
QString serverJunkPacketCount;
|
QString initPacketMagicHeader;
|
||||||
QString serverJunkPacketMinSize;
|
QString responsePacketMagicHeader;
|
||||||
QString serverJunkPacketMaxSize;
|
QString underloadPacketMagicHeader;
|
||||||
QString serverInitPacketJunkSize;
|
QString transportPacketMagicHeader;
|
||||||
QString serverResponsePacketJunkSize;
|
|
||||||
QString serverInitPacketMagicHeader;
|
|
||||||
QString serverResponsePacketMagicHeader;
|
|
||||||
QString serverUnderloadPacketMagicHeader;
|
|
||||||
QString serverTransportPacketMagicHeader;
|
|
||||||
|
|
||||||
bool hasEqualServerSettings(const AwgConfig &other) const;
|
bool hasEqualServerSettings(const AwgConfig &other) const;
|
||||||
bool hasEqualClientSettings(const AwgConfig &other) const;
|
bool hasEqualClientSettings(const AwgConfig &other) const;
|
||||||
@@ -44,21 +39,16 @@ class AwgConfigModel : public QAbstractListModel
|
|||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
PortRole = Qt::UserRole + 1,
|
PortRole = Qt::UserRole + 1,
|
||||||
|
MtuRole,
|
||||||
ClientMtuRole,
|
JunkPacketCountRole,
|
||||||
ClientJunkPacketCountRole,
|
JunkPacketMinSizeRole,
|
||||||
ClientJunkPacketMinSizeRole,
|
JunkPacketMaxSizeRole,
|
||||||
ClientJunkPacketMaxSizeRole,
|
InitPacketJunkSizeRole,
|
||||||
|
ResponsePacketJunkSizeRole,
|
||||||
ServerJunkPacketCountRole,
|
InitPacketMagicHeaderRole,
|
||||||
ServerJunkPacketMinSizeRole,
|
ResponsePacketMagicHeaderRole,
|
||||||
ServerJunkPacketMaxSizeRole,
|
UnderloadPacketMagicHeaderRole,
|
||||||
ServerInitPacketJunkSizeRole,
|
TransportPacketMagicHeaderRole
|
||||||
ServerResponsePacketJunkSizeRole,
|
|
||||||
ServerInitPacketMagicHeaderRole,
|
|
||||||
ServerResponsePacketMagicHeaderRole,
|
|
||||||
ServerUnderloadPacketMagicHeaderRole,
|
|
||||||
ServerTransportPacketMagicHeaderRole
|
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit AwgConfigModel(QObject *parent = nullptr);
|
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 isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4);
|
||||||
bool isPacketSizeEqual(const int s1, const int s2);
|
bool isPacketSizeEqual(const int s1, const int s2);
|
||||||
|
|
||||||
bool isServerSettingsEqual();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DockerContainer m_container;
|
DockerContainer m_container;
|
||||||
QJsonObject m_serverProtocolConfig;
|
QJsonObject m_protocolConfig;
|
||||||
QJsonObject m_clientProtocolConfig;
|
|
||||||
QJsonObject m_fullConfig;
|
QJsonObject m_fullConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ bool WireGuardConfigModel::setData(const QModelIndex &index, const QVariant &val
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
|
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
||||||
case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
|
case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit dataChanged(index, index, QList { role });
|
emit dataChanged(index, index, QList { role });
|
||||||
@@ -36,8 +36,8 @@ QVariant WireGuardConfigModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
|
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
|
||||||
case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
|
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@@ -49,18 +49,17 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
|
|||||||
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
|
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
|
||||||
|
|
||||||
m_fullConfig = config;
|
m_fullConfig = config;
|
||||||
QJsonObject serverProtocolConfig = config.value(config_key::wireguard).toObject();
|
QJsonObject protocolConfig = config.value(config_key::wireguard).toObject();
|
||||||
|
|
||||||
auto defaultTransportProto =
|
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard);
|
||||||
ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard);
|
m_protocolConfig.insert(config_key::transport_proto,
|
||||||
m_serverProtocolConfig.insert(config_key::transport_proto,
|
protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
||||||
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config);
|
||||||
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
|
m_protocolConfig[config_key::port] =
|
||||||
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
protocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
||||||
|
|
||||||
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
|
m_protocolConfig[config_key::mtu] =
|
||||||
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
protocolConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
||||||
m_clientProtocolConfig[config_key::mtu] = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu);
|
|
||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
@@ -68,47 +67,36 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
|
|||||||
QJsonObject WireGuardConfigModel::getConfig()
|
QJsonObject WireGuardConfigModel::getConfig()
|
||||||
{
|
{
|
||||||
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
|
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
|
||||||
const WgConfig newConfig(m_serverProtocolConfig);
|
const WgConfig newConfig(m_protocolConfig);
|
||||||
|
|
||||||
if (!oldConfig.hasEqualServerSettings(newConfig)) {
|
if (!oldConfig.hasEqualServerSettings(newConfig)) {
|
||||||
m_serverProtocolConfig.remove(config_key::last_config);
|
m_protocolConfig.remove(config_key::last_config);
|
||||||
} else {
|
} 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();
|
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;
|
return m_fullConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WireGuardConfigModel::isServerSettingsEqual()
|
|
||||||
{
|
|
||||||
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
|
|
||||||
const WgConfig newConfig(m_serverProtocolConfig);
|
|
||||||
|
|
||||||
return oldConfig.hasEqualServerSettings(newConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, QByteArray> WireGuardConfigModel::roleNames() const
|
QHash<int, QByteArray> WireGuardConfigModel::roleNames() const
|
||||||
{
|
{
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
|
|
||||||
roles[PortRole] = "port";
|
roles[PortRole] = "port";
|
||||||
roles[ClientMtuRole] = "clientMtu";
|
roles[MtuRole] = "mtu";
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
WgConfig::WgConfig(const QJsonObject &serverProtocolConfig)
|
WgConfig::WgConfig(const QJsonObject &jsonConfig)
|
||||||
{
|
{
|
||||||
auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString();
|
port = jsonConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
||||||
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
mtu = jsonConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
||||||
clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu);
|
|
||||||
|
|
||||||
port = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
|
bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
|
||||||
@@ -121,7 +109,7 @@ bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
|
|||||||
|
|
||||||
bool WgConfig::hasEqualClientSettings(const WgConfig &other) const
|
bool WgConfig::hasEqualClientSettings(const WgConfig &other) const
|
||||||
{
|
{
|
||||||
if (clientMtu != other.clientMtu) {
|
if (mtu != other.mtu) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ struct WgConfig
|
|||||||
WgConfig(const QJsonObject &jsonConfig);
|
WgConfig(const QJsonObject &jsonConfig);
|
||||||
|
|
||||||
QString port;
|
QString port;
|
||||||
QString clientMtu;
|
QString mtu;
|
||||||
|
|
||||||
bool hasEqualServerSettings(const WgConfig &other) const;
|
bool hasEqualServerSettings(const WgConfig &other) const;
|
||||||
bool hasEqualClientSettings(const WgConfig &other) const;
|
bool hasEqualClientSettings(const WgConfig &other) const;
|
||||||
@@ -25,7 +25,7 @@ class WireGuardConfigModel : public QAbstractListModel
|
|||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
PortRole = Qt::UserRole + 1,
|
PortRole = Qt::UserRole + 1,
|
||||||
ClientMtuRole
|
MtuRole
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit WireGuardConfigModel(QObject *parent = nullptr);
|
explicit WireGuardConfigModel(QObject *parent = nullptr);
|
||||||
@@ -39,15 +39,12 @@ public slots:
|
|||||||
void updateModel(const QJsonObject &config);
|
void updateModel(const QJsonObject &config);
|
||||||
QJsonObject getConfig();
|
QJsonObject getConfig();
|
||||||
|
|
||||||
bool isServerSettingsEqual();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DockerContainer m_container;
|
DockerContainer m_container;
|
||||||
QJsonObject m_serverProtocolConfig;
|
QJsonObject m_protocolConfig;
|
||||||
QJsonObject m_clientProtocolConfig;
|
|
||||||
QJsonObject m_fullConfig;
|
QJsonObject m_fullConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,11 +16,9 @@ QHash<int, QByteArray> ProtocolsModel::roleNames() const
|
|||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
|
|
||||||
roles[ProtocolNameRole] = "protocolName";
|
roles[ProtocolNameRole] = "protocolName";
|
||||||
roles[ServerProtocolPageRole] = "serverProtocolPage";
|
roles[ProtocolPageRole] = "protocolPage";
|
||||||
roles[ClientProtocolPageRole] = "clientProtocolPage";
|
|
||||||
roles[ProtocolIndexRole] = "protocolIndex";
|
roles[ProtocolIndexRole] = "protocolIndex";
|
||||||
roles[RawConfigRole] = "rawConfig";
|
roles[RawConfigRole] = "rawConfig";
|
||||||
roles[IsClientProtocolExistsRole] = "isClientProtocolExists";
|
|
||||||
|
|
||||||
return roles;
|
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()));
|
amnezia::Proto proto = ProtocolProps::protoFromString(m_content.keys().at(index.row()));
|
||||||
return ProtocolProps::protocolHumanNames().value(proto);
|
return ProtocolProps::protocolHumanNames().value(proto);
|
||||||
}
|
}
|
||||||
case ServerProtocolPageRole:
|
case ProtocolPageRole:
|
||||||
return static_cast<int>(serverProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
|
return static_cast<int>(protocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
|
||||||
case ClientProtocolPageRole:
|
|
||||||
return static_cast<int>(clientProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
|
|
||||||
case ProtocolIndexRole: return ProtocolProps::protoFromString(m_content.keys().at(index.row()));
|
case ProtocolIndexRole: return ProtocolProps::protoFromString(m_content.keys().at(index.row()));
|
||||||
case RawConfigRole: {
|
case RawConfigRole: {
|
||||||
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
|
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
|
||||||
@@ -54,15 +50,6 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
return rawConfig;
|
return rawConfig;
|
||||||
}
|
}
|
||||||
case IsClientProtocolExistsRole: {
|
|
||||||
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
|
|
||||||
auto lastConfigJsonDoc =
|
|
||||||
QJsonDocument::fromJson(protocolConfig.value(config_key::last_config).toString().toUtf8());
|
|
||||||
auto lastConfigJson = lastConfigJsonDoc.object();
|
|
||||||
|
|
||||||
auto configString = lastConfigJson.value(config_key::config).toString();
|
|
||||||
return !configString.isEmpty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@@ -83,7 +70,7 @@ QJsonObject ProtocolsModel::getConfig()
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageLoader::PageEnum ProtocolsModel::serverProtocolPage(Proto protocol) const
|
PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const
|
||||||
{
|
{
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case Proto::OpenVpn: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
case Proto::OpenVpn: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||||
@@ -103,12 +90,3 @@ PageLoader::PageEnum ProtocolsModel::serverProtocolPage(Proto protocol) const
|
|||||||
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PageLoader::PageEnum ProtocolsModel::clientProtocolPage(Proto protocol) const
|
|
||||||
{
|
|
||||||
switch (protocol) {
|
|
||||||
case Proto::WireGuard: return PageLoader::PageEnum::PageProtocolWireGuardClientSettings;
|
|
||||||
case Proto::Awg: return PageLoader::PageEnum::PageProtocolAwgClientSettings;
|
|
||||||
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,11 +13,9 @@ class ProtocolsModel : public QAbstractListModel
|
|||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
ProtocolNameRole = Qt::UserRole + 1,
|
ProtocolNameRole = Qt::UserRole + 1,
|
||||||
ServerProtocolPageRole,
|
ProtocolPageRole,
|
||||||
ClientProtocolPageRole,
|
|
||||||
ProtocolIndexRole,
|
ProtocolIndexRole,
|
||||||
RawConfigRole,
|
RawConfigRole
|
||||||
IsClientProtocolExistsRole
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||||
@@ -35,8 +33,7 @@ protected:
|
|||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PageLoader::PageEnum serverProtocolPage(Proto protocol) const;
|
PageLoader::PageEnum protocolPage(Proto protocol) const;
|
||||||
PageLoader::PageEnum clientProtocolPage(Proto protocol) const;
|
|
||||||
|
|
||||||
std::shared_ptr<Settings> m_settings;
|
std::shared_ptr<Settings> m_settings;
|
||||||
|
|
||||||
|
|||||||
@@ -694,7 +694,16 @@ bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling()
|
|||||||
QJsonObject serverProtocolConfig = container.value(ContainerProps::containerTypeToString(defaultContainer)).toObject();
|
QJsonObject serverProtocolConfig = container.value(ContainerProps::containerTypeToString(defaultContainer)).toObject();
|
||||||
QString clientProtocolConfigString = serverProtocolConfig.value(config_key::last_config).toString();
|
QString clientProtocolConfigString = serverProtocolConfig.value(config_key::last_config).toString();
|
||||||
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(clientProtocolConfigString.toUtf8()).object();
|
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(clientProtocolConfigString.toUtf8()).object();
|
||||||
return (clientProtocolConfigString.contains("AllowedIPs") && !clientProtocolConfigString.contains("AllowedIPs = 0.0.0.0/0, ::/0"))
|
QString nativeProtocolConfigString = clientProtocolConfig.value(config_key::config).toString();
|
||||||
|
|
||||||
|
const static QRegularExpression allowedIpsRegExp("AllowedIPs\\s*=\\s*([^\n]*)");
|
||||||
|
QRegularExpressionMatch allowedIpsMatch = allowedIpsRegExp.match(nativeProtocolConfigString);
|
||||||
|
QString allowedIpsString;
|
||||||
|
if (allowedIpsMatch.hasCaptured(1)) {
|
||||||
|
allowedIpsString = allowedIpsMatch.captured(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !allowedIpsString.contains("0.0.0.0/0")
|
||||||
|| (!clientProtocolConfig.value(config_key::allowed_ips).toArray().isEmpty()
|
|| (!clientProtocolConfig.value(config_key::allowed_ips).toArray().isEmpty()
|
||||||
&& !clientProtocolConfig.value(config_key::allowed_ips).toArray().contains("0.0.0.0/0"));
|
&& !clientProtocolConfig.value(config_key::allowed_ips).toArray().contains("0.0.0.0/0"));
|
||||||
} else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn
|
} else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -14,7 +14,6 @@ Button {
|
|||||||
property string defaultButtonColor: AmneziaStyle.color.paleGray
|
property string defaultButtonColor: AmneziaStyle.color.paleGray
|
||||||
property string progressButtonColor: AmneziaStyle.color.paleGray
|
property string progressButtonColor: AmneziaStyle.color.paleGray
|
||||||
property string connectedButtonColor: AmneziaStyle.color.goldenApricot
|
property string connectedButtonColor: AmneziaStyle.color.goldenApricot
|
||||||
property bool buttonActiveFocus: activeFocus && (Qt.platform.os !== "android" || SettingsController.isOnTv())
|
|
||||||
|
|
||||||
implicitWidth: 190
|
implicitWidth: 190
|
||||||
implicitHeight: 190
|
implicitHeight: 190
|
||||||
@@ -51,14 +50,14 @@ Button {
|
|||||||
verticalOffset: 0
|
verticalOffset: 0
|
||||||
radius: 10
|
radius: 10
|
||||||
samples: 25
|
samples: 25
|
||||||
color: root.buttonActiveFocus ? AmneziaStyle.color.paleGray : AmneziaStyle.color.goldenApricot
|
color: root.activeFocus ? AmneziaStyle.color.paleGray : AmneziaStyle.color.goldenApricot
|
||||||
source: backgroundCircle
|
source: backgroundCircle
|
||||||
}
|
}
|
||||||
|
|
||||||
ShapePath {
|
ShapePath {
|
||||||
fillColor: AmneziaStyle.color.transparent
|
fillColor: AmneziaStyle.color.transparent
|
||||||
strokeColor: AmneziaStyle.color.paleGray
|
strokeColor: AmneziaStyle.color.paleGray
|
||||||
strokeWidth: root.buttonActiveFocus ? 1 : 0
|
strokeWidth: root.activeFocus ? 1 : 0
|
||||||
capStyle: ShapePath.RoundCap
|
capStyle: ShapePath.RoundCap
|
||||||
|
|
||||||
PathAngleArc {
|
PathAngleArc {
|
||||||
@@ -82,14 +81,14 @@ Button {
|
|||||||
return defaultButtonColor
|
return defaultButtonColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strokeWidth: root.buttonActiveFocus ? 2 : 3
|
strokeWidth: root.activeFocus ? 2 : 3
|
||||||
capStyle: ShapePath.RoundCap
|
capStyle: ShapePath.RoundCap
|
||||||
|
|
||||||
PathAngleArc {
|
PathAngleArc {
|
||||||
centerX: backgroundCircle.width / 2
|
centerX: backgroundCircle.width / 2
|
||||||
centerY: backgroundCircle.height / 2
|
centerY: backgroundCircle.height / 2
|
||||||
radiusX: 93 - (root.buttonActiveFocus ? 2 : 0)
|
radiusX: 93 - (root.activeFocus ? 2 : 0)
|
||||||
radiusY: 93 - (root.buttonActiveFocus ? 2 : 0)
|
radiusY: 93 - (root.activeFocus ? 2 : 0)
|
||||||
startAngle: 0
|
startAngle: 0
|
||||||
sweepAngle: 360
|
sweepAngle: 360
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import "../Config"
|
|||||||
DrawerType2 {
|
DrawerType2 {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool isAppSplitTinnelingEnabled: Qt.platform.os === "windows" || Qt.platform.os === "android"
|
property bool isAppSplitTunnelingEnabled: Qt.platform.os === "windows" || Qt.platform.os === "android"
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
expandedHeight: parent.height * 0.9
|
expandedHeight: parent.height * 0.9
|
||||||
@@ -24,6 +24,8 @@ DrawerType2 {
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
|
property bool isServerSplitTunnelingEnabled: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: root
|
target: root
|
||||||
enabled: !GC.isMobile()
|
enabled: !GC.isMobile()
|
||||||
@@ -53,7 +55,7 @@ DrawerType2 {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling
|
visible: isServerSplitTunnelingEnabled
|
||||||
|
|
||||||
text: qsTr("Split tunneling on the server")
|
text: qsTr("Split tunneling on the server")
|
||||||
descriptionText: qsTr("Enabled \nCan't be disabled for current server")
|
descriptionText: qsTr("Enabled \nCan't be disabled for current server")
|
||||||
@@ -68,7 +70,7 @@ DrawerType2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DividerType {
|
DividerType {
|
||||||
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling
|
visible: isServerSplitTunnelingEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
@@ -95,7 +97,7 @@ DrawerType2 {
|
|||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
id: appSplitTunnelingSwitch
|
id: appSplitTunnelingSwitch
|
||||||
visible: isAppSplitTinnelingEnabled
|
visible: isAppSplitTunnelingEnabled
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
@@ -112,7 +114,7 @@ DrawerType2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DividerType {
|
DividerType {
|
||||||
visible: isAppSplitTinnelingEnabled
|
visible: isAppSplitTunnelingEnabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ Button {
|
|||||||
visible: text !== ""
|
visible: text !== ""
|
||||||
|
|
||||||
color: AmneziaStyle.color.mutedGray
|
color: AmneziaStyle.color.mutedGray
|
||||||
textFormat: Text.RichText
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ Item {
|
|||||||
property string buttonImageSource
|
property string buttonImageSource
|
||||||
property string rightImageSource
|
property string rightImageSource
|
||||||
property string leftImageSource
|
property string leftImageSource
|
||||||
property bool isLeftImageHoverEnabled: true
|
property bool isLeftImageHoverEnabled: true //todo separete this qml file to 3
|
||||||
property bool isSmallLeftImage: false
|
|
||||||
|
|
||||||
property alias rightButton: rightImage
|
property alias rightButton: rightImage
|
||||||
property alias eyeButton: eyeImage
|
property alias eyeButton: eyeImage
|
||||||
@@ -115,9 +114,9 @@ Item {
|
|||||||
|
|
||||||
visible: leftImageSource ? true : false
|
visible: leftImageSource ? true : false
|
||||||
|
|
||||||
Layout.preferredHeight: (rightImageSource || !isLeftImageHoverEnabled || isSmallLeftImage) ? 40 : 56
|
Layout.preferredHeight: rightImageSource || !isLeftImageHoverEnabled ? leftImage.implicitHeight : 56
|
||||||
Layout.preferredWidth: (rightImageSource || !isLeftImageHoverEnabled || isSmallLeftImage)? 40 : 56
|
Layout.preferredWidth: rightImageSource || !isLeftImageHoverEnabled ? leftImage.implicitWidth : 56
|
||||||
Layout.rightMargin: isSmallLeftImage ? 8 : (rightImageSource || !isLeftImageHoverEnabled) ? 16 : 0
|
Layout.rightMargin: rightImageSource || !isLeftImageHoverEnabled ? 16 : 0
|
||||||
|
|
||||||
radius: 12
|
radius: 12
|
||||||
color: AmneziaStyle.color.transparent
|
color: AmneziaStyle.color.transparent
|
||||||
|
|||||||
@@ -102,7 +102,8 @@ Switch {
|
|||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
id: content
|
id: content
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|
||||||
ListItemTitleType {
|
ListItemTitleType {
|
||||||
|
|||||||
@@ -89,21 +89,6 @@ PageType {
|
|||||||
|
|
||||||
// KeyNavigation.tab: saveButton
|
// KeyNavigation.tab: saveButton
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitcherType {
|
|
||||||
id: switcher
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
text: qsTr("Dev gateway environment")
|
|
||||||
checked: SettingsController.isDevGatewayEnv
|
|
||||||
onToggled: function() {
|
|
||||||
SettingsController.isDevGatewayEnv = checked
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,312 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Layouts
|
|
||||||
|
|
||||||
import SortFilterProxyModel 0.2
|
|
||||||
|
|
||||||
import PageEnum 1.0
|
|
||||||
|
|
||||||
import "./"
|
|
||||||
import "../Controls2"
|
|
||||||
import "../Controls2/TextTypes"
|
|
||||||
import "../Config"
|
|
||||||
import "../Components"
|
|
||||||
|
|
||||||
|
|
||||||
PageType {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
defaultActiveFocusItem: listview.currentItem.mtuTextField.textField
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: focusItem
|
|
||||||
onFocusChanged: {
|
|
||||||
if (activeFocus) {
|
|
||||||
fl.ensureVisible(focusItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
KeyNavigation.tab: backButton
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: backButtonLayout
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
anchors.topMargin: 20
|
|
||||||
|
|
||||||
BackButtonType {
|
|
||||||
id: backButton
|
|
||||||
KeyNavigation.tab: listview.currentItem.mtuTextField.textField
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
|
||||||
id: fl
|
|
||||||
anchors.top: backButtonLayout.bottom
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
contentHeight: content.implicitHeight + saveButton.implicitHeight + saveButton.anchors.bottomMargin + saveButton.anchors.topMargin
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: content
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
id: listview
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
height: listview.contentItem.height
|
|
||||||
|
|
||||||
clip: true
|
|
||||||
interactive: false
|
|
||||||
|
|
||||||
model: AwgConfigModel
|
|
||||||
|
|
||||||
delegate: Item {
|
|
||||||
id: delegateItem
|
|
||||||
implicitWidth: listview.width
|
|
||||||
implicitHeight: col.implicitHeight
|
|
||||||
|
|
||||||
property alias mtuTextField: mtuTextField
|
|
||||||
property bool isSaveButtonEnabled: mtuTextField.errorText === "" &&
|
|
||||||
junkPacketMaxSizeTextField.errorText === "" &&
|
|
||||||
junkPacketMinSizeTextField.errorText === "" &&
|
|
||||||
junkPacketCountTextField.errorText === ""
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: col
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
HeaderType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
headerText: qsTr("AmneziaWG settings")
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: mtuTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 40
|
|
||||||
|
|
||||||
headerText: qsTr("MTU")
|
|
||||||
textFieldText: clientMtu
|
|
||||||
textField.validator: IntValidator { bottom: 576; top: 65535 }
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textFieldText !== clientMtu) {
|
|
||||||
clientMtu = textFieldText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checkEmptyText: true
|
|
||||||
KeyNavigation.tab: junkPacketCountTextField.textField
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: junkPacketCountTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
headerText: "Jc - Junk packet count"
|
|
||||||
textFieldText: clientJunkPacketCount
|
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
|
||||||
parentFlickable: fl
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textFieldText !== clientJunkPacketCount) {
|
|
||||||
clientJunkPacketCount = textFieldText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
|
|
||||||
KeyNavigation.tab: junkPacketMinSizeTextField.textField
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: junkPacketMinSizeTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
headerText: "Jmin - Junk packet minimum size"
|
|
||||||
textFieldText: clientJunkPacketMinSize
|
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
|
||||||
parentFlickable: fl
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textFieldText !== clientJunkPacketMinSize) {
|
|
||||||
clientJunkPacketMinSize = textFieldText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
|
|
||||||
KeyNavigation.tab: junkPacketMaxSizeTextField.textField
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: junkPacketMaxSizeTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
headerText: "Jmax - Junk packet maximum size"
|
|
||||||
textFieldText: clientJunkPacketMaxSize
|
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
|
||||||
parentFlickable: fl
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textFieldText !== clientJunkPacketMaxSize) {
|
|
||||||
clientJunkPacketMaxSize = textFieldText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
|
|
||||||
Keys.onTabPressed: saveButton.forceActiveFocus()
|
|
||||||
}
|
|
||||||
|
|
||||||
Header2TextType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
text: qsTr("Server settings")
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: portTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
headerText: qsTr("Port")
|
|
||||||
textFieldText: port
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: initPacketJunkSizeTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
headerText: "S1 - Init packet junk size"
|
|
||||||
textFieldText: serverInitPacketJunkSize
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: responsePacketJunkSizeTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
headerText: "S2 - Response packet junk size"
|
|
||||||
textFieldText: serverResponsePacketJunkSize
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: initPacketMagicHeaderTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
headerText: "H1 - Init packet magic header"
|
|
||||||
textFieldText: serverInitPacketMagicHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: responsePacketMagicHeaderTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
headerText: "H2 - Response packet magic header"
|
|
||||||
textFieldText: serverResponsePacketMagicHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: underloadPacketMagicHeaderTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
parentFlickable: fl
|
|
||||||
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
headerText: "H3 - Underload packet magic header"
|
|
||||||
textFieldText: serverUnderloadPacketMagicHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: transportPacketMagicHeaderTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
headerText: "H4 - Transport packet magic header"
|
|
||||||
textFieldText: serverTransportPacketMagicHeader
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicButtonType {
|
|
||||||
id: saveButton
|
|
||||||
|
|
||||||
anchors.right: root.right
|
|
||||||
anchors.left: root.left
|
|
||||||
anchors.bottom: root.bottom
|
|
||||||
|
|
||||||
anchors.topMargin: 24
|
|
||||||
anchors.bottomMargin: 24
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
|
|
||||||
enabled: listview.currentItem.isSaveButtonEnabled
|
|
||||||
|
|
||||||
text: qsTr("Save")
|
|
||||||
|
|
||||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
|
||||||
|
|
||||||
clickedFunc: function() {
|
|
||||||
forceActiveFocus()
|
|
||||||
var headerText = qsTr("Save settings?")
|
|
||||||
var descriptionText = qsTr("Only the settings for this device will be changed")
|
|
||||||
var yesButtonText = qsTr("Continue")
|
|
||||||
var noButtonText = qsTr("Cancel")
|
|
||||||
|
|
||||||
var yesButtonFunction = function() {
|
|
||||||
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
|
||||||
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
|
||||||
InstallController.updateContainer(AwgConfigModel.getConfig())
|
|
||||||
}
|
|
||||||
var noButtonFunction = function() {
|
|
||||||
if (!GC.isMobile()) {
|
|
||||||
saveButton.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -57,6 +57,8 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listview
|
id: listview
|
||||||
|
|
||||||
@@ -69,12 +71,12 @@ PageType {
|
|||||||
model: AwgConfigModel
|
model: AwgConfigModel
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
id: delegateItem
|
id: _delegate
|
||||||
|
|
||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
property alias portTextField: portTextField
|
property alias portTextField:portTextField
|
||||||
property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess()
|
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
@@ -99,8 +101,6 @@ PageType {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
|
||||||
|
|
||||||
headerText: qsTr("Port")
|
headerText: qsTr("Port")
|
||||||
textFieldText: port
|
textFieldText: port
|
||||||
textField.maximumLength: 5
|
textField.maximumLength: 5
|
||||||
@@ -115,6 +115,27 @@ PageType {
|
|||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: mtuTextField.textField
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFieldWithHeaderType {
|
||||||
|
id: mtuTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
|
headerText: qsTr("MTU")
|
||||||
|
textFieldText: mtu
|
||||||
|
textField.validator: IntValidator { bottom: 576; top: 65535 }
|
||||||
|
|
||||||
|
textField.onEditingFinished: {
|
||||||
|
if (textFieldText === "") {
|
||||||
|
textFieldText = "0"
|
||||||
|
}
|
||||||
|
if (textFieldText !== mtu) {
|
||||||
|
mtu = textFieldText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkEmptyText: true
|
||||||
KeyNavigation.tab: junkPacketCountTextField.textField
|
KeyNavigation.tab: junkPacketCountTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +145,7 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("Jc - Junk packet count")
|
headerText: qsTr("Jc - Junk packet count")
|
||||||
textFieldText: serverJunkPacketCount
|
textFieldText: junkPacketCount
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
@@ -133,8 +154,8 @@ PageType {
|
|||||||
textFieldText = "0"
|
textFieldText = "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textFieldText !== serverJunkPacketCount) {
|
if (textFieldText !== junkPacketCount) {
|
||||||
serverJunkPacketCount = textFieldText
|
junkPacketCount = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,13 +170,13 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("Jmin - Junk packet minimum size")
|
headerText: qsTr("Jmin - Junk packet minimum size")
|
||||||
textFieldText: serverJunkPacketMinSize
|
textFieldText: junkPacketMinSize
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textFieldText !== serverJunkPacketMinSize) {
|
if (textFieldText !== junkPacketMinSize) {
|
||||||
serverJunkPacketMinSize = textFieldText
|
junkPacketMinSize = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,13 +191,13 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("Jmax - Junk packet maximum size")
|
headerText: qsTr("Jmax - Junk packet maximum size")
|
||||||
textFieldText: serverJunkPacketMaxSize
|
textFieldText: junkPacketMaxSize
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textFieldText !== serverJunkPacketMaxSize) {
|
if (textFieldText !== junkPacketMaxSize) {
|
||||||
serverJunkPacketMaxSize = textFieldText
|
junkPacketMaxSize = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,13 +212,13 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("S1 - Init packet junk size")
|
headerText: qsTr("S1 - Init packet junk size")
|
||||||
textFieldText: serverInitPacketJunkSize
|
textFieldText: initPacketJunkSize
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textFieldText !== serverInitPacketJunkSize) {
|
if (textFieldText !== initPacketJunkSize) {
|
||||||
serverInitPacketJunkSize = textFieldText
|
initPacketJunkSize = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,13 +233,13 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("S2 - Response packet junk size")
|
headerText: qsTr("S2 - Response packet junk size")
|
||||||
textFieldText: serverResponsePacketJunkSize
|
textFieldText: responsePacketJunkSize
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textFieldText !== serverResponsePacketJunkSize) {
|
if (textFieldText !== responsePacketJunkSize) {
|
||||||
serverResponsePacketJunkSize = textFieldText
|
responsePacketJunkSize = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,13 +254,13 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("H1 - Init packet magic header")
|
headerText: qsTr("H1 - Init packet magic header")
|
||||||
textFieldText: serverInitPacketMagicHeader
|
textFieldText: initPacketMagicHeader
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textFieldText !== serverInitPacketMagicHeader) {
|
if (textFieldText !== initPacketMagicHeader) {
|
||||||
serverInitPacketMagicHeader = textFieldText
|
initPacketMagicHeader = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,13 +275,13 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("H2 - Response packet magic header")
|
headerText: qsTr("H2 - Response packet magic header")
|
||||||
textFieldText: serverResponsePacketMagicHeader
|
textFieldText: responsePacketMagicHeader
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textFieldText !== serverResponsePacketMagicHeader) {
|
if (textFieldText !== responsePacketMagicHeader) {
|
||||||
serverResponsePacketMagicHeader = textFieldText
|
responsePacketMagicHeader = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,13 +296,13 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("H4 - Transport packet magic header")
|
headerText: qsTr("H4 - Transport packet magic header")
|
||||||
textFieldText: serverTransportPacketMagicHeader
|
textFieldText: transportPacketMagicHeader
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textFieldText !== serverTransportPacketMagicHeader) {
|
if (textFieldText !== transportPacketMagicHeader) {
|
||||||
serverTransportPacketMagicHeader = textFieldText
|
transportPacketMagicHeader = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,12 +318,12 @@ PageType {
|
|||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
headerText: qsTr("H3 - Underload packet magic header")
|
headerText: qsTr("H3 - Underload packet magic header")
|
||||||
textFieldText: serverUnderloadPacketMagicHeader
|
textFieldText: underloadPacketMagicHeader
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textFieldText !== serverUnderloadPacketMagicHeader) {
|
if (textFieldText !== underloadPacketMagicHeader) {
|
||||||
serverUnderloadPacketMagicHeader = textFieldText
|
underloadPacketMagicHeader = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,9 +356,6 @@ PageType {
|
|||||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||||
|
|
||||||
clickedFunc: function() {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
|
||||||
|
|
||||||
if (delegateItem.isEnabled) {
|
|
||||||
if (AwgConfigModel.isHeadersEqual(underloadPacketMagicHeaderTextField.textField.text,
|
if (AwgConfigModel.isHeadersEqual(underloadPacketMagicHeaderTextField.textField.text,
|
||||||
transportPacketMagicHeaderTextField.textField.text,
|
transportPacketMagicHeaderTextField.textField.text,
|
||||||
responsePacketMagicHeaderTextField.textField.text,
|
responsePacketMagicHeaderTextField.textField.text,
|
||||||
@@ -351,7 +369,6 @@ PageType {
|
|||||||
PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)"))
|
PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var headerText = qsTr("Save settings?")
|
var headerText = qsTr("Save settings?")
|
||||||
var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.")
|
var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.")
|
||||||
@@ -359,6 +376,8 @@ PageType {
|
|||||||
var noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
var yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
|
forceActiveFocus()
|
||||||
|
|
||||||
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
||||||
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,179 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Layouts
|
|
||||||
|
|
||||||
import SortFilterProxyModel 0.2
|
|
||||||
|
|
||||||
import PageEnum 1.0
|
|
||||||
|
|
||||||
import "./"
|
|
||||||
import "../Controls2"
|
|
||||||
import "../Controls2/TextTypes"
|
|
||||||
import "../Config"
|
|
||||||
import "../Components"
|
|
||||||
|
|
||||||
|
|
||||||
PageType {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
defaultActiveFocusItem: listview.currentItem.mtuTextField.textField
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: focusItem
|
|
||||||
onFocusChanged: {
|
|
||||||
if (activeFocus) {
|
|
||||||
fl.ensureVisible(focusItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
KeyNavigation.tab: backButton
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: backButtonLayout
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
anchors.topMargin: 20
|
|
||||||
|
|
||||||
BackButtonType {
|
|
||||||
id: backButton
|
|
||||||
KeyNavigation.tab: listview.currentItem.mtuTextField.textField
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
|
||||||
id: fl
|
|
||||||
anchors.top: backButtonLayout.bottom
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
contentHeight: content.implicitHeight + saveButton.implicitHeight + saveButton.anchors.bottomMargin + saveButton.anchors.topMargin
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: content
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
id: listview
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
height: listview.contentItem.height
|
|
||||||
|
|
||||||
clip: true
|
|
||||||
interactive: false
|
|
||||||
|
|
||||||
model: WireGuardConfigModel
|
|
||||||
|
|
||||||
delegate: Item {
|
|
||||||
id: delegateItem
|
|
||||||
implicitWidth: listview.width
|
|
||||||
implicitHeight: col.implicitHeight
|
|
||||||
|
|
||||||
property alias mtuTextField: mtuTextField
|
|
||||||
property bool isSaveButtonEnabled: mtuTextField.errorText === ""
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: col
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
HeaderType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
headerText: qsTr("WG settings")
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: mtuTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 40
|
|
||||||
|
|
||||||
headerText: qsTr("MTU")
|
|
||||||
textFieldText: clientMtu
|
|
||||||
textField.validator: IntValidator { bottom: 576; top: 65535 }
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textFieldText !== clientMtu) {
|
|
||||||
clientMtu = textFieldText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checkEmptyText: true
|
|
||||||
KeyNavigation.tab: saveButton
|
|
||||||
}
|
|
||||||
|
|
||||||
Header2TextType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
text: qsTr("Server settings")
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: portTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
headerText: qsTr("Port")
|
|
||||||
textFieldText: port
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicButtonType {
|
|
||||||
id: saveButton
|
|
||||||
|
|
||||||
anchors.right: root.right
|
|
||||||
anchors.left: root.left
|
|
||||||
anchors.bottom: root.bottom
|
|
||||||
|
|
||||||
anchors.topMargin: 24
|
|
||||||
anchors.bottomMargin: 24
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
|
|
||||||
enabled: listview.currentItem.isSaveButtonEnabled
|
|
||||||
|
|
||||||
text: qsTr("Save")
|
|
||||||
|
|
||||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
|
||||||
|
|
||||||
clickedFunc: function() {
|
|
||||||
forceActiveFocus()
|
|
||||||
var headerText = qsTr("Save settings?")
|
|
||||||
var descriptionText = qsTr("Only the settings for this device will be changed")
|
|
||||||
var yesButtonText = qsTr("Continue")
|
|
||||||
var noButtonText = qsTr("Cancel")
|
|
||||||
|
|
||||||
var yesButtonFunction = function() {
|
|
||||||
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
|
||||||
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
|
||||||
InstallController.updateContainer(WireGuardConfigModel.getConfig())
|
|
||||||
}
|
|
||||||
var noButtonFunction = function() {
|
|
||||||
if (!GC.isMobile()) {
|
|
||||||
saveButton.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -72,10 +72,7 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
id: delegateItem
|
|
||||||
|
|
||||||
property alias focusItemId: portTextField.textField
|
property alias focusItemId: portTextField.textField
|
||||||
property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess()
|
|
||||||
|
|
||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
@@ -102,14 +99,12 @@ PageType {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
|
||||||
|
|
||||||
headerText: qsTr("Port")
|
headerText: qsTr("Port")
|
||||||
textFieldText: port
|
textFieldText: port
|
||||||
textField.maximumLength: 5
|
textField.maximumLength: 5
|
||||||
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
||||||
|
|
||||||
KeyNavigation.tab: saveButton
|
KeyNavigation.tab: mtuTextField.textField
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textFieldText !== port) {
|
if (textFieldText !== port) {
|
||||||
@@ -120,27 +115,44 @@ PageType {
|
|||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextFieldWithHeaderType {
|
||||||
|
id: mtuTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
|
headerText: qsTr("MTU")
|
||||||
|
textFieldText: mtu
|
||||||
|
textField.validator: IntValidator { bottom: 576; top: 65535 }
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveButton
|
||||||
|
|
||||||
|
textField.onEditingFinished: {
|
||||||
|
if (textFieldText === "") {
|
||||||
|
textFieldText = "0"
|
||||||
|
}
|
||||||
|
if (textFieldText !== mtu) {
|
||||||
|
mtu = textFieldText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkEmptyText: true
|
||||||
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
id: saveButton
|
id: saveButton
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
enabled: portTextField.errorText === ""
|
enabled: mtuTextField.errorText === "" &&
|
||||||
|
portTextField.errorText === ""
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||||
|
|
||||||
onClicked: function() {
|
onClicked: {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
|
|
||||||
var headerText = qsTr("Save settings?")
|
|
||||||
var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.")
|
|
||||||
var yesButtonText = qsTr("Continue")
|
|
||||||
var noButtonText = qsTr("Cancel")
|
|
||||||
|
|
||||||
var yesButtonFunction = function() {
|
|
||||||
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
||||||
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
||||||
return
|
return
|
||||||
@@ -148,13 +160,7 @@ PageType {
|
|||||||
|
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.updateContainer(WireGuardConfigModel.getConfig())
|
InstallController.updateContainer(WireGuardConfigModel.getConfig())
|
||||||
}
|
focusItem.forceActiveFocus()
|
||||||
var noButtonFunction = function() {
|
|
||||||
if (!GC.isMobile()) {
|
|
||||||
saveRestartButton.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onEnterPressed: saveButton.clicked()
|
Keys.onEnterPressed: saveButton.clicked()
|
||||||
|
|||||||
@@ -16,6 +16,18 @@ import "../Controls2/TextTypes"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SettingsController
|
||||||
|
|
||||||
|
function onLoggingStateChanged() {
|
||||||
|
if (SettingsController.isLoggingEnabled) {
|
||||||
|
var message = qsTr("Logging is enabled. Note that logs will be automatically \
|
||||||
|
disabled after 14 days, and all log files will be deleted.")
|
||||||
|
PageController.showNotificationMessage(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
defaultActiveFocusItem: focusItem
|
defaultActiveFocusItem: focusItem
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -46,12 +58,13 @@ PageType {
|
|||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
spacing: 0
|
anchors.leftMargin: 16
|
||||||
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
HeaderType {
|
HeaderType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Logging")
|
headerText: qsTr("Logging")
|
||||||
descriptionText: qsTr("Enabling this function will save application's logs automatically. " +
|
descriptionText: qsTr("Enabling this function will save application's logs automatically. " +
|
||||||
@@ -62,13 +75,11 @@ PageType {
|
|||||||
id: switcher
|
id: switcher
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
|
|
||||||
text: qsTr("Enable logs")
|
text: qsTr("Save logs")
|
||||||
|
|
||||||
checked: SettingsController.isLoggingEnabled
|
checked: SettingsController.isLoggingEnabled
|
||||||
//KeyNavigation.tab: openFolderButton
|
KeyNavigation.tab: openFolderButton
|
||||||
onCheckedChanged: {
|
onCheckedChanged: {
|
||||||
if (checked !== SettingsController.isLoggingEnabled) {
|
if (checked !== SettingsController.isLoggingEnabled) {
|
||||||
SettingsController.isLoggingEnabled = checked
|
SettingsController.isLoggingEnabled = checked
|
||||||
@@ -76,20 +87,100 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {}
|
RowLayout {
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
// id: labelWithButton2
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: -8
|
|
||||||
|
|
||||||
text: qsTr("Clear logs")
|
ColumnLayout {
|
||||||
leftImageSource: "qrc:/images/controls/trash.svg"
|
Layout.alignment: Qt.AlignBaseline
|
||||||
isSmallLeftImage: true
|
Layout.preferredWidth: GC.isMobile() ? 0 : root.width / 3
|
||||||
|
visible: !GC.isMobile()
|
||||||
|
|
||||||
// KeyNavigation.tab: labelWithButton3
|
ImageButtonType {
|
||||||
|
id: openFolderButton
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
clickedFunction: function() {
|
implicitWidth: 56
|
||||||
|
implicitHeight: 56
|
||||||
|
|
||||||
|
image: "qrc:/images/controls/folder-open.svg"
|
||||||
|
KeyNavigation.tab: saveButton
|
||||||
|
|
||||||
|
onClicked: SettingsController.openLogsFolder()
|
||||||
|
Keys.onReturnPressed: openFolderButton.clicked()
|
||||||
|
Keys.onEnterPressed: openFolderButton.clicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
CaptionTextType {
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
text: qsTr("Open folder with logs")
|
||||||
|
color: AmneziaStyle.color.paleGray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.alignment: Qt.AlignBaseline
|
||||||
|
Layout.preferredWidth: root.width / ( GC.isMobile() ? 2 : 3 )
|
||||||
|
|
||||||
|
ImageButtonType {
|
||||||
|
id: saveButton
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
implicitWidth: 56
|
||||||
|
implicitHeight: 56
|
||||||
|
|
||||||
|
image: "qrc:/images/controls/save.svg"
|
||||||
|
KeyNavigation.tab: clearButton
|
||||||
|
|
||||||
|
Keys.onReturnPressed: saveButton.clicked()
|
||||||
|
Keys.onEnterPressed: saveButton.clicked()
|
||||||
|
onClicked: {
|
||||||
|
var fileName = ""
|
||||||
|
if (GC.isMobile()) {
|
||||||
|
fileName = "AmneziaVPN.log"
|
||||||
|
} else {
|
||||||
|
fileName = SystemController.getFileName(qsTr("Save"),
|
||||||
|
qsTr("Logs files (*.log)"),
|
||||||
|
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN",
|
||||||
|
true,
|
||||||
|
".log")
|
||||||
|
}
|
||||||
|
if (fileName !== "") {
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
SettingsController.exportLogsFile(fileName)
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
PageController.showNotificationMessage(qsTr("Logs file saved"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CaptionTextType {
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
text: qsTr("Save logs to file")
|
||||||
|
color: AmneziaStyle.color.paleGray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.alignment: Qt.AlignBaseline
|
||||||
|
Layout.preferredWidth: root.width / ( GC.isMobile() ? 2 : 3 )
|
||||||
|
|
||||||
|
ImageButtonType {
|
||||||
|
id: clearButton
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
implicitWidth: 56
|
||||||
|
implicitHeight: 56
|
||||||
|
|
||||||
|
image: "qrc:/images/controls/delete.svg"
|
||||||
|
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||||
|
|
||||||
|
Keys.onReturnPressed: clearButton.clicked()
|
||||||
|
Keys.onEnterPressed: clearButton.clicked()
|
||||||
|
onClicked: function() {
|
||||||
var headerText = qsTr("Clear logs?")
|
var headerText = qsTr("Clear logs?")
|
||||||
var yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
var noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
@@ -113,162 +204,14 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ListItemTitleType {
|
CaptionTextType {
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 8
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
|
|
||||||
text: qsTr("Client logs")
|
text: qsTr("Clear logs")
|
||||||
}
|
color: AmneziaStyle.color.paleGray
|
||||||
|
|
||||||
ParagraphTextType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
|
|
||||||
color: AmneziaStyle.color.mutedGray
|
|
||||||
text: qsTr("AmneziaVPN logs")
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
// id: labelWithButton2
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: -8
|
|
||||||
Layout.bottomMargin: -8
|
|
||||||
|
|
||||||
text: qsTr("Open logs folder")
|
|
||||||
leftImageSource: "qrc:/images/controls/folder-open.svg"
|
|
||||||
isSmallLeftImage: true
|
|
||||||
|
|
||||||
// KeyNavigation.tab: labelWithButton3
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
SettingsController.openLogsFolder()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
// id: labelWithButton2
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: -8
|
|
||||||
Layout.bottomMargin: -8
|
|
||||||
|
|
||||||
text: qsTr("Export logs")
|
|
||||||
leftImageSource: "qrc:/images/controls/save.svg"
|
|
||||||
isSmallLeftImage: true
|
|
||||||
|
|
||||||
// KeyNavigation.tab: labelWithButton3
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
var fileName = ""
|
|
||||||
if (GC.isMobile()) {
|
|
||||||
fileName = "AmneziaVPN.log"
|
|
||||||
} else {
|
|
||||||
fileName = SystemController.getFileName(qsTr("Save"),
|
|
||||||
qsTr("Logs files (*.log)"),
|
|
||||||
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN",
|
|
||||||
true,
|
|
||||||
".log")
|
|
||||||
}
|
|
||||||
if (fileName !== "") {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
SettingsController.exportLogsFile(fileName)
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
PageController.showNotificationMessage(qsTr("Logs file saved"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {}
|
|
||||||
|
|
||||||
ListItemTitleType {
|
|
||||||
visible: !GC.isMobile()
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 32
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
|
|
||||||
text: qsTr("Service logs")
|
|
||||||
}
|
|
||||||
|
|
||||||
ParagraphTextType {
|
|
||||||
visible: !GC.isMobile()
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 8
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
|
|
||||||
color: AmneziaStyle.color.mutedGray
|
|
||||||
text: qsTr("AmneziaVPN-service logs")
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
// id: labelWithButton2
|
|
||||||
|
|
||||||
visible: !GC.isMobile()
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: -8
|
|
||||||
Layout.bottomMargin: -8
|
|
||||||
|
|
||||||
text: qsTr("Open logs folder")
|
|
||||||
leftImageSource: "qrc:/images/controls/folder-open.svg"
|
|
||||||
isSmallLeftImage: true
|
|
||||||
|
|
||||||
// KeyNavigation.tab: labelWithButton3
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
SettingsController.openServiceLogsFolder()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {
|
|
||||||
visible: !GC.isMobile()
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
// id: labelWithButton2
|
|
||||||
|
|
||||||
visible: !GC.isMobile()
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: -8
|
|
||||||
Layout.bottomMargin: -8
|
|
||||||
|
|
||||||
text: qsTr("Export logs")
|
|
||||||
leftImageSource: "qrc:/images/controls/save.svg"
|
|
||||||
isSmallLeftImage: true
|
|
||||||
|
|
||||||
// KeyNavigation.tab: labelWithButton3
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
var fileName = ""
|
|
||||||
if (GC.isMobile()) {
|
|
||||||
fileName = "AmneziaVPN-service.log"
|
|
||||||
} else {
|
|
||||||
fileName = SystemController.getFileName(qsTr("Save"),
|
|
||||||
qsTr("Logs files (*.log)"),
|
|
||||||
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN-service",
|
|
||||||
true,
|
|
||||||
".log")
|
|
||||||
}
|
|
||||||
if (fileName !== "") {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
SettingsController.exportServiceLogsFile(fileName)
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
PageController.showNotificationMessage(qsTr("Logs file saved"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {
|
|
||||||
visible: !GC.isMobile()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
property var focusItem: clientSettings.rightButton
|
property var focusItem: button.rightButton
|
||||||
|
|
||||||
implicitWidth: protocols.width
|
implicitWidth: protocols.width
|
||||||
implicitHeight: delegateContent.implicitHeight
|
implicitHeight: delegateContent.implicitHeight
|
||||||
@@ -89,49 +89,13 @@ PageType {
|
|||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
property bool isClientSettingsVisible: protocolIndex === ProtocolEnum.WireGuard || protocolIndex === ProtocolEnum.Awg
|
|
||||||
property bool isServerSettingsVisible: ServersModel.isProcessedServerHasWriteAccess()
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
id: clientSettings
|
id: button
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: protocolName + qsTr(" connection settings")
|
text: protocolName
|
||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
visible: delegateContent.isClientSettingsVisible
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
if (isClientProtocolExists) {
|
|
||||||
switch (protocolIndex) {
|
|
||||||
case ProtocolEnum.WireGuard: WireGuardConfigModel.updateModel(ProtocolsModel.getConfig()); break;
|
|
||||||
case ProtocolEnum.Awg: AwgConfigModel.updateModel(ProtocolsModel.getConfig()); break;
|
|
||||||
}
|
|
||||||
PageController.goToPage(clientProtocolPage);
|
|
||||||
} else {
|
|
||||||
PageController.showNotificationMessage(qsTr("Click the \"connect\" button to create a connection configuration"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: clientSettings
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
enabled: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {
|
|
||||||
visible: delegateContent.isClientSettingsVisible
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
id: serverSettings
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
text: protocolName + qsTr(" server settings")
|
|
||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
|
||||||
visible: delegateContent.isServerSettingsVisible
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
switch (protocolIndex) {
|
switch (protocolIndex) {
|
||||||
@@ -145,19 +109,17 @@ PageType {
|
|||||||
case ProtocolEnum.Ipsec: Ikev2ConfigModel.updateModel(ProtocolsModel.getConfig()); break;
|
case ProtocolEnum.Ipsec: Ikev2ConfigModel.updateModel(ProtocolsModel.getConfig()); break;
|
||||||
case ProtocolEnum.Socks5Proxy: Socks5ProxyConfigModel.updateModel(ProtocolsModel.getConfig()); break;
|
case ProtocolEnum.Socks5Proxy: Socks5ProxyConfigModel.updateModel(ProtocolsModel.getConfig()); break;
|
||||||
}
|
}
|
||||||
PageController.goToPage(serverProtocolPage);
|
PageController.goToPage(protocolPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: serverSettings
|
anchors.fill: button
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
enabled: false
|
enabled: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {
|
DividerType {}
|
||||||
visible: delegateContent.isServerSettingsVisible
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,11 +132,11 @@ PageType {
|
|||||||
visible: root.isClearCacheVisible
|
visible: root.isClearCacheVisible
|
||||||
KeyNavigation.tab: removeButton
|
KeyNavigation.tab: removeButton
|
||||||
|
|
||||||
text: qsTr("Clear profile")
|
text: qsTr("Clear %1 profile").arg(ContainersModel.getProcessedContainerName())
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
var headerText = qsTr("Clear %1 profile?").arg(ContainersModel.getProcessedContainerName())
|
var headerText = qsTr("Clear %1 profile?").arg(ContainersModel.getProcessedContainerName())
|
||||||
var descriptionText = qsTr("The connection configuration will be deleted for this device only")
|
var descriptionText = qsTr("")
|
||||||
var yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
var noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
@@ -221,7 +183,7 @@ PageType {
|
|||||||
visible: ServersModel.isProcessedServerHasWriteAccess()
|
visible: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||||
|
|
||||||
text: qsTr("Remove ")
|
text: qsTr("Remove ") + ContainersModel.getProcessedContainerName()
|
||||||
textColor: AmneziaStyle.color.vibrantRed
|
textColor: AmneziaStyle.color.vibrantRed
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ PageType {
|
|||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (isServiceAvailable) {
|
|
||||||
ApiServicesModel.setServiceIndex(index)
|
ApiServicesModel.setServiceIndex(index)
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardApiServiceInfo)
|
PageController.goToPage(PageEnum.PageSetupWizardApiServiceInfo)
|
||||||
}
|
}
|
||||||
@@ -98,5 +97,4 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,51 +55,6 @@ PageType {
|
|||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("Connection")
|
headerText: qsTr("Connection")
|
||||||
|
|
||||||
actionButtonImage: PageController.isStartPageVisible() ? "qrc:/images/controls/more-vertical.svg" : ""
|
|
||||||
actionButtonFunction: function() {
|
|
||||||
moreActionsDrawer.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawerType2 {
|
|
||||||
id: moreActionsDrawer
|
|
||||||
|
|
||||||
parent: root
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
expandedHeight: root.height * 0.35
|
|
||||||
|
|
||||||
expandedContent: ColumnLayout {
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
|
|
||||||
HeaderType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 32
|
|
||||||
|
|
||||||
headerText: qsTr("Settings")
|
|
||||||
}
|
|
||||||
|
|
||||||
SwitcherType {
|
|
||||||
id: switcher
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
text: qsTr("Enable logs")
|
|
||||||
|
|
||||||
checked: SettingsController.isLoggingEnabled
|
|
||||||
onCheckedChanged: {
|
|
||||||
if (checked !== SettingsController.isLoggingEnabled) {
|
|
||||||
SettingsController.isLoggingEnabled = checked
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphTextType {
|
ParagraphTextType {
|
||||||
@@ -164,6 +119,8 @@ PageType {
|
|||||||
CardWithIconsType {
|
CardWithIconsType {
|
||||||
id: apiInstalling
|
id: apiInstalling
|
||||||
|
|
||||||
|
visible: false
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ PageType {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
headerText: qsTr("Server IP address [:port]")
|
headerText: qsTr("Server IP address [:port]")
|
||||||
textFieldPlaceholderText: qsTr("255.255.255.255:22")
|
textFieldPlaceholderText: qsTr("255.255.255.255:22")
|
||||||
|
textField.validator: RegularExpressionValidator {
|
||||||
|
regularExpression: InstallController.ipAddressPortRegExp()
|
||||||
|
}
|
||||||
|
|
||||||
textField.onFocusChanged: {
|
textField.onFocusChanged: {
|
||||||
textField.text = textField.text.replace(/^\s+|\s+$/g, '')
|
textField.text = textField.text.replace(/^\s+|\s+$/g, '')
|
||||||
|
|||||||
@@ -140,23 +140,22 @@ PageType {
|
|||||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||||
|
|
||||||
clickedFunc: function() {
|
clickedFunc: function() {
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
|
|
||||||
if (Qt.platform.os === "android" && !SystemController.isAuthenticated()) {
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
ExportController.exportErrorOccurred(qsTr("Access error!"))
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
ExportController.generateFullAccessConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
||||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
||||||
|
|
||||||
shareConnectionDrawer.open()
|
shareConnectionDrawer.open()
|
||||||
shareConnectionDrawer.contentVisible = true
|
shareConnectionDrawer.contentVisible = false
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
|
||||||
|
if (Qt.platform.os === "android") {
|
||||||
|
ExportController.generateFullAccessConfigAndroid();
|
||||||
|
} else {
|
||||||
|
ExportController.generateFullAccessConfig();
|
||||||
|
}
|
||||||
|
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
|
|
||||||
|
shareConnectionDrawer.contentVisible = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,14 +202,6 @@ PageType {
|
|||||||
PageController.showNotificationMessage(qsTr("Settings restored from backup file"))
|
PageController.showNotificationMessage(qsTr("Settings restored from backup file"))
|
||||||
PageController.goToPageHome()
|
PageController.goToPageHome()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLoggingStateChanged() {
|
|
||||||
if (SettingsController.isLoggingEnabled) {
|
|
||||||
var message = qsTr("Logging is enabled. Note that logs will be automatically" +
|
|
||||||
"disabled after 14 days, and all log files will be deleted.")
|
|
||||||
PageController.showNotificationMessage(message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StackViewType {
|
StackViewType {
|
||||||
|
|||||||
@@ -69,6 +69,22 @@ QString Utils::JsonToString(const QJsonArray &array, QJsonDocument::JsonFormat f
|
|||||||
return doc.toJson(format);
|
return doc.toJson(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Utils::systemLogPath()
|
||||||
|
{
|
||||||
|
#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
|
||||||
|
}
|
||||||
|
|
||||||
bool Utils::initializePath(const QString &path)
|
bool Utils::initializePath(const QString &path)
|
||||||
{
|
{
|
||||||
QDir dir;
|
QDir dir;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user