diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0c9dfb32..35e740b0 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,7 +10,7 @@ env: jobs: Build-Linux-Ubuntu: - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 env: QT_VERSION: 6.6.2 @@ -20,8 +20,6 @@ jobs: DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} - FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} - PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Install Qt' @@ -92,8 +90,6 @@ jobs: DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} - FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} - PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Get sources' @@ -160,8 +156,6 @@ jobs: DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} - FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} - PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Setup xcode' @@ -196,7 +190,7 @@ jobs: - name: 'Install go' uses: actions/setup-go@v5 with: - go-version: '1.24' + go-version: '1.22.1' cache: false - name: 'Setup gomobile' @@ -249,82 +243,18 @@ jobs: # ------------------------------------------------------ - Build-MacOS-old: + Build-MacOS: runs-on: macos-latest env: # Keep compat with MacOS 10.15 aka Catalina by Qt 6.4 QT_VERSION: 6.4.3 + QIF_VERSION: 4.6 PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} - FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} - PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} - - steps: - - name: 'Setup xcode' - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: '15.4.0' - - - name: 'Install Qt' - uses: jurplel/install-qt-action@v3 - with: - version: ${{ env.QT_VERSION }} - host: 'mac' - target: 'desktop' - arch: 'clang_64' - modules: 'qtremoteobjects qt5compat qtshadertools' - dir: ${{ runner.temp }} - setup-python: 'true' - set-env: 'true' - extra: '--external 7z --base ${{ env.QT_MIRROR }}' - - - - name: 'Get sources' - uses: actions/checkout@v4 - with: - submodules: 'true' - fetch-depth: 10 - - - name: 'Setup ccache' - uses: hendrikmuhs/ccache-action@v1.2 - - - name: 'Build project' - run: | - export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin" - bash deploy/build_macos.sh - - - name: 'Upload installer artifact' - uses: actions/upload-artifact@v4 - with: - name: AmneziaVPN_MacOS_old_installer - path: deploy/build/pkg/AmneziaVPN.pkg - retention-days: 7 - - - name: 'Upload unpacked artifact' - uses: actions/upload-artifact@v4 - with: - name: AmneziaVPN_MacOS_old_unpacked - path: deploy/build/client/AmneziaVPN.app - retention-days: 7 - -# ------------------------------------------------------ - - Build-MacOS: - runs-on: macos-latest - - env: - QT_VERSION: 6.8.0 - PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} - PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} - DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} - DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} - DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} - FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} - PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Setup xcode' @@ -345,6 +275,11 @@ jobs: set-env: 'true' extra: '--external 7z --base ${{ env.QT_MIRROR }}' + - name: 'Install Qt Installer Framework ${{ env.QIF_VERSION }}' + run: | + mkdir -pv ${{ runner.temp }}/Qt/Tools/QtInstallerFramework + wget https://qt.amzsvc.com/tools/ifw/${{ env.QIF_VERSION }}.zip + unzip ${{ env.QIF_VERSION }}.zip -d ${{ runner.temp }}/Qt/Tools/QtInstallerFramework/ - name: 'Get sources' uses: actions/checkout@v4 @@ -358,13 +293,14 @@ jobs: - name: 'Build project' run: | export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin" + export QIF_BIN_DIR="${{ runner.temp }}/Qt/Tools/QtInstallerFramework/${{ env.QIF_VERSION }}/bin" bash deploy/build_macos.sh - name: 'Upload installer artifact' uses: actions/upload-artifact@v4 with: name: AmneziaVPN_MacOS_installer - path: deploy/build/pkg/AmneziaVPN.pkg + path: AmneziaVPN.dmg retention-days: 7 - name: 'Upload unpacked artifact' @@ -388,8 +324,6 @@ jobs: DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} - FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} - PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Install desktop Qt' diff --git a/.github/workflows/tag-deploy.yml b/.github/workflows/tag-deploy.yml index 31c334bf..2bcbd8c6 100644 --- a/.github/workflows/tag-deploy.yml +++ b/.github/workflows/tag-deploy.yml @@ -20,8 +20,6 @@ jobs: DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }} DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }} - FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }} - PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }} steps: - name: 'Install desktop Qt' diff --git a/.github/workflows/tag-upload.yml b/.github/workflows/tag-upload.yml index 9ac2da58..22629ed3 100644 --- a/.github/workflows/tag-upload.yml +++ b/.github/workflows/tag-upload.yml @@ -1,41 +1,64 @@ name: 'Upload a new version' on: - workflow_dispatch: - inputs: - RELEASE_VERSION: - description: 'Release version (e.g. 1.2.3.4)' - required: true - type: string + push: + tags: + - '[0-9]+.[0-9]+.[0-9]+.[0-9]+' jobs: - Upload-S3: + upload: runs-on: ubuntu-latest + name: upload steps: - - name: Checkout + - name: Checkout CMakeLists.txt uses: actions/checkout@v4 with: - ref: ${{ inputs.RELEASE_VERSION }} + ref: ${{ github.ref_name }} sparse-checkout: | CMakeLists.txt - deploy/deploy_s3.sh sparse-checkout-cone-mode: false - name: Verify git tag run: | - TAG_NAME=${{ inputs.RELEASE_VERSION }} + GIT_TAG=${{ github.ref_name }} CMAKE_TAG=$(grep 'project.*VERSION' CMakeLists.txt | sed -E 's/.* ([0-9]+.[0-9]+.[0-9]+.[0-9]+)$/\1/') - if [[ "$TAG_NAME" == "$CMAKE_TAG" ]]; then - echo "Git tag ($TAG_NAME) matches CMakeLists.txt version ($CMAKE_TAG)." + + if [[ "$GIT_TAG" == "$CMAKE_TAG" ]]; then + echo "Git tag ($GIT_TAG) and version in CMakeLists.txt ($CMAKE_TAG) are the same. Continuing..." else - echo "::error::Mismatch: Git tag ($TAG_NAME) != CMakeLists.txt version ($CMAKE_TAG). Exiting with error..." + echo "Git tag ($GIT_TAG) and version in CMakeLists.txt ($CMAKE_TAG) are not the same! Cancelling..." exit 1 fi - - name: Setup Rclone - uses: AnimMouse/setup-rclone@v1 + - name: Download artifacts from the "${{ github.ref_name }}" tag + uses: robinraju/release-downloader@v1.8 with: - rclone_config: ${{ secrets.RCLONE_CONFIG }} + tag: ${{ github.ref_name }} + fileName: "AmneziaVPN_(Linux_|)${{ github.ref_name }}*" + out-file-path: ${{ github.ref_name }} - - name: Send dist to S3 - run: bash deploy/deploy_s3.sh ${{ inputs.RELEASE_VERSION }} + - name: Upload beta version + uses: jakejarvis/s3-sync-action@master + if: contains(github.event.base_ref, 'dev') + with: + args: --include "AmneziaVPN*" --delete + env: + AWS_S3_BUCKET: updates + AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_SECRET_ACCESS_KEY }} + AWS_S3_ENDPOINT: https://${{ vars.CF_ACCOUNT_ID }}.r2.cloudflarestorage.com + SOURCE_DIR: ${{ github.ref_name }} + DEST_DIR: beta/${{ github.ref_name }} + + - name: Upload stable version + uses: jakejarvis/s3-sync-action@master + if: contains(github.event.base_ref, 'master') + with: + args: --include "AmneziaVPN*" --delete + env: + AWS_S3_BUCKET: updates + AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_SECRET_ACCESS_KEY }} + AWS_S3_ENDPOINT: https://${{ vars.CF_ACCOUNT_ID }}.r2.cloudflarestorage.com + SOURCE_DIR: ${{ github.ref_name }} + DEST_DIR: stable/${{ github.ref_name }} diff --git a/.gitignore b/.gitignore index 503adc2d..5b90fd55 100644 --- a/.gitignore +++ b/.gitignore @@ -133,8 +133,4 @@ client/3rd/ShadowSocks/ss_ios.xcconfig out/ # CMake files -CMakeFiles/ - -ios-ne-build.sh -macos-ne-build.sh -macos-signed-build.sh +CMakeFiles/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 90edb582..3ceaa56e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ +[submodule "client/3rd/OpenVPNAdapter"] + path = client/3rd/OpenVPNAdapter + url = https://github.com/amnezia-vpn/OpenVPNAdapter.git [submodule "client/3rd/qtkeychain"] path = client/3rd/qtkeychain url = https://github.com/frankosterfeld/qtkeychain.git @@ -7,7 +10,6 @@ [submodule "client/3rd-prebuilt"] path = client/3rd-prebuilt url = https://github.com/amnezia-vpn/3rd-prebuilt - branch = feature/special-handshake [submodule "client/3rd/amneziawg-apple"] path = client/3rd/amneziawg-apple url = https://github.com/amnezia-vpn/amneziawg-apple diff --git a/CMakeLists.txt b/CMakeLists.txt index fec613de..98f3be14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR) set(PROJECT AmneziaVPN) -project(${PROJECT} VERSION 4.8.8.1 +project(${PROJECT} VERSION 4.8.3.0 DESCRIPTION "AmneziaVPN" HOMEPAGE_URL "https://amnezia.org/" ) @@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d") set(RELEASE_DATE "${CURRENT_DATE}") set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}) -set(APP_ANDROID_VERSION_CODE 2087) +set(APP_ANDROID_VERSION_CODE 2072) if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(MZ_PLATFORM_NAME "linux") diff --git a/README.md b/README.md index 992c3ad0..8f887808 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ [![Image](https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/uipic4.png)](https://amnezia.org) -### [Website](https://amnezia.org) | [Alt website link](https://storage.googleapis.com/amnezia/amnezia.org) | [Documentation](https://docs.amnezia.org) | [Troubleshooting](https://docs.amnezia.org/troubleshooting) +### [Website](https://amnezia.org) | [Alt website link](https://storage.googleapis.com/kldscp/amnezia.org) | [Documentation](https://docs.amnezia.org) | [Troubleshooting](https://docs.amnezia.org/troubleshooting) > [!TIP] -> If the [Amnezia website](https://amnezia.org) is blocked in your region, you can use an [Alternative website link](https://storage.googleapis.com/amnezia/amnezia.org ). +> If the [Amnezia website](https://amnezia.org) is blocked in your region, you can use an [Alternative website link](https://storage.googleapis.com/kldscp/amnezia.org). - + [All releases](https://github.com/amnezia-vpn/amnezia-client/releases) @@ -185,7 +185,7 @@ GPL v3.0 Patreon: [https://www.patreon.com/amneziavpn](https://www.patreon.com/amneziavpn) -Bitcoin: bc1qmhtgcf9637rl3kqyy22r2a8wa8laka4t9rx2mf
+Bitcoin: bc1q26eevjcg9j0wuyywd2e3uc9cs2w58lpkpjxq6p
USDT BEP20: 0x6abD576765a826f87D1D95183438f9408C901bE4
USDT TRC20: TELAitazF1MZGmiNjTcnxDjEiH5oe7LC9d
XMR: 48spms39jt1L2L5vyw2RQW6CXD6odUd4jFu19GZcDyKKQV9U88wsJVjSbL4CfRys37jVMdoaWVPSvezCQPhHXUW5UKLqUp3
diff --git a/README_RU.md b/README_RU.md index 44681875..59518f4b 100644 --- a/README_RU.md +++ b/README_RU.md @@ -6,16 +6,16 @@ [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/amnezia-vpn/amnezia-client) ### [English](https://github.com/amnezia-vpn/amnezia-client/blob/dev/README.md) | Русский -[AmneziaVPN](https://amnezia.org) — это open source VPN-клиент, ключевая особенность которого заключается в возможности развернуть собственный VPN на вашем сервере. +[AmneziaVPN](https://amnezia.org) — это open sourse VPN-клиент, ключевая особенность которого заключается в возможности развернуть собственный VPN на вашем сервере. [![Image](https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/uipic4.png)](https://amnezia.org) -### [Сайт](https://amnezia.org) | [Зеркало сайта](https://storage.googleapis.com/amnezia/amnezia.org) | [Документация](https://docs.amnezia.org) | [Решение проблем](https://docs.amnezia.org/troubleshooting) +### [Сайт](https://amnezia.org) | [Зеркало на сайт](https://storage.googleapis.com/kldscp/amnezia.org) | [Документация](https://docs.amnezia.org) | [Решение проблем](https://docs.amnezia.org/troubleshooting) > [!TIP] -> Если [сайт Amnezia](https://amnezia.org) заблокирован в вашем регионе, вы можете воспользоваться [ссылкой на зеркало](https://storage.googleapis.com/amnezia/amnezia.org). +> Если [сайт Amnezia](https://amnezia.org) заблокирован в вашем регионе, вы можете воспользоваться [ссылкой на зеркало](https://storage.googleapis.com/kldscp/amnezia.org). - + [Все релизы](https://github.com/amnezia-vpn/amnezia-client/releases) @@ -30,7 +30,7 @@ - Классические VPN-протоколы: OpenVPN, WireGuard и IKEv2. - Протоколы с маскировкой трафика (обфускацией): OpenVPN с плагином [Cloak](https://github.com/cbeuw/Cloak), Shadowsocks (OpenVPN over Shadowsocks), [AmneziaWG](https://docs.amnezia.org/documentation/amnezia-wg/) and XRay. - Поддержка Split Tunneling — добавляйте любые сайты или приложения в список, чтобы включить VPN только для них. -- Поддерживает платформы: Windows, macOS, Linux, Android, iOS. +- Поддерживает платформы: Windows, MacOS, Linux, Android, iOS. - Поддержка конфигурации протокола AmneziaWG на [бета-прошивке Keenetic](https://docs.keenetic.com/ua/air/kn-1611/en/6319-latest-development-release.html#UUID-186c4108-5afd-c10b-f38a-cdff6c17fab3_section-idm33192196168192-improved). ## Ссылки @@ -38,10 +38,10 @@ - [https://amnezia.org](https://amnezia.org) - Веб-сайт проекта | [Альтернативная ссылка (зеркало)](https://storage.googleapis.com/kldscp/amnezia.org) - [https://docs.amnezia.org](https://docs.amnezia.org) - Документация - [https://www.reddit.com/r/AmneziaVPN](https://www.reddit.com/r/AmneziaVPN) - Reddit -- [https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Канал поддержки в Telegram (Английский) -- [https://t.me/amnezia_vpn_ir](https://t.me/amnezia_vpn_ir) - Канал поддержки в Telegram (Фарси) -- [https://t.me/amnezia_vpn_mm](https://t.me/amnezia_vpn_mm) - Канал поддержки в Telegram (Мьянма) -- [https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Канал поддержки в Telegram (Русский) +- [https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Канал поддржки в Telegram (Английский) +- [https://t.me/amnezia_vpn_ir](https://t.me/amnezia_vpn_ir) - Канал поддржки в Telegram (Фарси) +- [https://t.me/amnezia_vpn_mm](https://t.me/amnezia_vpn_mm) - Канал поддржки в Telegram (Мьянма) +- [https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Канал поддржки в Telegram (Русский) - [https://vpnpay.io/en/amnezia-premium/](https://vpnpay.io/en/amnezia-premium/) - Amnezia Premium | [Зеркало](https://storage.googleapis.com/kldscp/vpnpay.io/ru/amnezia-premium\) ## Технологии @@ -80,8 +80,8 @@ git submodule update --init --recursive Проверьте папку deploy для скриптов сборки. ### Как собрать iOS-приложение из исходного кода на MacOS -1. Убедитесь, что у вас установлен Xcode версии 14 или выше. -2. Для генерации проекта Xcode используется QT. Требуется версия QT 6.6.2. Установите QT для MacOS здесь или через QT Online Installer. Необходимые модули: +1. Убедитесь, что у вас установлен XCode версии 14 или выше. +2. Для генерации проекта XCode используется QT. Требуется версия QT 6.6.2. Установите QT для MacOS здесь или через QT Online Installer. Необходимые модули: - MacOS - iOS - Модуль совместимости с Qt 5 @@ -117,7 +117,7 @@ $QT_IOS_BIN/qt-cmake . -B build-ios -GXcode -DQT_HOST_PATH=$QT_MACOS_ROOT_DIR export PATH=$(PATH):/path/to/GOPATH/bin ``` -6. Откройте проект в Xcode. Теперь вы можете тестировать, архивировать или публиковать приложение. +6. Откройте проект в XCode. Теперь вы можете тестировать, архивировать или публиковать приложение. Если сборка завершится с ошибкой: ``` @@ -169,7 +169,7 @@ GPL v3.0 Patreon: [https://www.patreon.com/amneziavpn](https://www.patreon.com/amneziavpn) -Bitcoin: bc1qmhtgcf9637rl3kqyy22r2a8wa8laka4t9rx2mf
+Bitcoin: bc1q26eevjcg9j0wuyywd2e3uc9cs2w58lpkpjxq6p
USDT BEP20: 0x6abD576765a826f87D1D95183438f9408C901bE4
USDT TRC20: TELAitazF1MZGmiNjTcnxDjEiH5oe7LC9d
XMR: 48spms39jt1L2L5vyw2RQW6CXD6odUd4jFu19GZcDyKKQV9U88wsJVjSbL4CfRys37jVMdoaWVPSvezCQPhHXUW5UKLqUp3
diff --git a/client/3rd-prebuilt b/client/3rd-prebuilt index 840b7b07..ba580dc5 160000 --- a/client/3rd-prebuilt +++ b/client/3rd-prebuilt @@ -1 +1 @@ -Subproject commit 840b7b070e6ac8b90dda2fac6e98859b23727c0c +Subproject commit ba580dc5bd7784f7b1e110ff0365f3286e549a61 diff --git a/client/3rd/OpenVPNAdapter b/client/3rd/OpenVPNAdapter new file mode 160000 index 00000000..7c821a8d --- /dev/null +++ b/client/3rd/OpenVPNAdapter @@ -0,0 +1 @@ +Subproject commit 7c821a8d5c1ad5ad94e0763b4f25a875b5a6fe1b diff --git a/client/3rd/amneziawg-apple b/client/3rd/amneziawg-apple index 811af0a8..76e7db55 160000 --- a/client/3rd/amneziawg-apple +++ b/client/3rd/amneziawg-apple @@ -1 +1 @@ -Subproject commit 811af0a83b3faeade89a9093a588595666d32066 +Subproject commit 76e7db556a6d7e2582f9481df91db188a46c009c diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index a454142d..3ef92385 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -31,8 +31,9 @@ add_definitions(-DDEV_AGW_PUBLIC_KEY="$ENV{DEV_AGW_PUBLIC_KEY}") add_definitions(-DDEV_AGW_ENDPOINT="$ENV{DEV_AGW_ENDPOINT}") add_definitions(-DDEV_S3_ENDPOINT="$ENV{DEV_S3_ENDPOINT}") -add_definitions(-DFREE_V2_ENDPOINT="$ENV{FREE_V2_ENDPOINT}") -add_definitions(-DPREM_V1_ENDPOINT="$ENV{PREM_V1_ENDPOINT}") +if(IOS) + set(PACKAGES ${PACKAGES} Multimedia) +endif() if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID)) set(PACKAGES ${PACKAGES} Widgets) @@ -47,6 +48,10 @@ set(LIBS ${LIBS} Qt6::Core5Compat Qt6::Concurrent ) +if(IOS) + set(LIBS ${LIBS} Qt6::Multimedia) +endif() + if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID)) set(LIBS ${LIBS} Qt6::Widgets) endif() @@ -91,6 +96,11 @@ configure_file(${CMAKE_CURRENT_LIST_DIR}/translations/translations.qrc.in ${CMAK qt6_add_resources(QRC ${I18NQRC} ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) # -- i18n end +if(IOS) + execute_process(COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/ios/scripts/openvpn.sh args + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) +endif() + set(IS_CI ${CI}) if(IS_CI) message("Detected CI env") @@ -100,8 +110,8 @@ if(IS_CI) endif() endif() + include(${CMAKE_CURRENT_LIST_DIR}/cmake/3rdparty.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/cmake/sources.cmake) include_directories( ${CMAKE_CURRENT_LIST_DIR}/../ipc @@ -110,22 +120,167 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) +configure_file(${CMAKE_CURRENT_LIST_DIR}/../version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h) + +set(HEADERS ${HEADERS} + ${CMAKE_CURRENT_LIST_DIR}/migrations.h + ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc.h + ${CMAKE_CURRENT_LIST_DIR}/amnezia_application.h + ${CMAKE_CURRENT_LIST_DIR}/containers/containers_defs.h + ${CMAKE_CURRENT_LIST_DIR}/core/defs.h + ${CMAKE_CURRENT_LIST_DIR}/core/errorstrings.h + ${CMAKE_CURRENT_LIST_DIR}/core/scripts_registry.h + ${CMAKE_CURRENT_LIST_DIR}/core/server_defs.h + ${CMAKE_CURRENT_LIST_DIR}/core/controllers/apiController.h + ${CMAKE_CURRENT_LIST_DIR}/core/controllers/serverController.h + ${CMAKE_CURRENT_LIST_DIR}/core/controllers/vpnConfigurationController.h + ${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h + ${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.h + ${CMAKE_CURRENT_LIST_DIR}/ui/pages.h + ${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.h + ${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.h + ${CMAKE_CURRENT_BINARY_DIR}/version.h + ${CMAKE_CURRENT_LIST_DIR}/core/sshclient.h + ${CMAKE_CURRENT_LIST_DIR}/core/networkUtilities.h + ${CMAKE_CURRENT_LIST_DIR}/core/serialization/serialization.h + ${CMAKE_CURRENT_LIST_DIR}/core/serialization/transfer.h + ${CMAKE_CURRENT_LIST_DIR}/core/enums/apiEnums.h + ${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.h + ${CMAKE_CURRENT_LIST_DIR}/utils/qmlUtils.h +) + +# Mozilla headres +set(HEADERS ${HEADERS} + ${CMAKE_CURRENT_LIST_DIR}/mozilla/models/server.h + ${CMAKE_CURRENT_LIST_DIR}/mozilla/shared/ipaddress.h + ${CMAKE_CURRENT_LIST_DIR}/mozilla/shared/leakdetector.h + ${CMAKE_CURRENT_LIST_DIR}/mozilla/controllerimpl.h + ${CMAKE_CURRENT_LIST_DIR}/mozilla/localsocketcontroller.h +) + include_directories(mozilla) include_directories(mozilla/shared) include_directories(mozilla/models) -configure_file(${CMAKE_CURRENT_LIST_DIR}/../version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h) +if(NOT IOS) + set(HEADERS ${HEADERS} + ${CMAKE_CURRENT_LIST_DIR}/platforms/ios/QRCodeReaderBase.h + ) +endif() + +if(NOT ANDROID) + set(HEADERS ${HEADERS} + ${CMAKE_CURRENT_LIST_DIR}/ui/notificationhandler.h + ) +endif() + +set(SOURCES ${SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/migrations.cpp + ${CMAKE_CURRENT_LIST_DIR}/amnezia_application.cpp + ${CMAKE_CURRENT_LIST_DIR}/containers/containers_defs.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/errorstrings.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/scripts_registry.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/server_defs.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/controllers/apiController.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/controllers/serverController.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/controllers/vpnConfigurationController.cpp + ${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.cpp + ${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.cpp + ${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/sshclient.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/networkUtilities.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/serialization/outbound.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/serialization/inbound.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/serialization/ss.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/serialization/ssd.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/serialization/vless.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/serialization/trojan.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess_new.cpp + ${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.cpp + ${CMAKE_CURRENT_LIST_DIR}/utils/qmlUtils.cpp +) + +# Mozilla sources +set(SOURCES ${SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/mozilla/models/server.cpp + ${CMAKE_CURRENT_LIST_DIR}/mozilla/shared/ipaddress.cpp + ${CMAKE_CURRENT_LIST_DIR}/mozilla/shared/leakdetector.cpp + ${CMAKE_CURRENT_LIST_DIR}/mozilla/localsocketcontroller.cpp +) if(CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_definitions(${PROJECT} PRIVATE "MZ_DEBUG") endif() +if(NOT IOS) + set(SOURCES ${SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/platforms/ios/QRCodeReaderBase.cpp + ) +endif() + +if(NOT ANDROID) + set(SOURCES ${SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/ui/notificationhandler.cpp + ) +endif() + +file(GLOB COMMON_FILES_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/*.h) +file(GLOB COMMON_FILES_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/*.cpp) + +file(GLOB_RECURSE PAGE_LOGIC_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/pages_logic/*.h) +file(GLOB_RECURSE PAGE_LOGIC_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/pages_logic/*.cpp) + +file(GLOB CONFIGURATORS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configurators/*.h) +file(GLOB CONFIGURATORS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configurators/*.cpp) + +file(GLOB UI_MODELS_H CONFIGURE_DEPENDS + ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.h + ${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.h + ${CMAKE_CURRENT_LIST_DIR}/ui/models/services/*.h +) +file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS + ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.cpp + ${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.cpp + ${CMAKE_CURRENT_LIST_DIR}/ui/models/services/*.cpp +) + +file(GLOB UI_CONTROLLERS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.h) +file(GLOB UI_CONTROLLERS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.cpp) + +set(HEADERS ${HEADERS} + ${COMMON_FILES_H} + ${PAGE_LOGIC_H} + ${CONFIGURATORS_H} + ${UI_MODELS_H} + ${UI_CONTROLLERS_H} +) +set(SOURCES ${SOURCES} + ${COMMON_FILES_CPP} + ${PAGE_LOGIC_CPP} + ${CONFIGURATORS_CPP} + ${UI_MODELS_CPP} + ${UI_CONTROLLERS_CPP} +) + if(WIN32) configure_file( ${CMAKE_CURRENT_LIST_DIR}/platforms/windows/amneziavpn.rc.in ${CMAKE_CURRENT_BINARY_DIR}/amneziavpn.rc ) + set(HEADERS ${HEADERS} + ${CMAKE_CURRENT_LIST_DIR}/protocols/ikev2_vpn_protocol_windows.h + ) + + set(SOURCES ${SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/protocols/ikev2_vpn_protocol_windows.cpp + ) + + set(RESOURCES ${RESOURCES} + ${CMAKE_CURRENT_BINARY_DIR}/amneziavpn.rc + ) + set(LIBS ${LIBS} user32 rasapi32 @@ -169,6 +324,30 @@ endif() if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID)) message("Client desktop build") add_compile_definitions(AMNEZIA_DESKTOP) + + set(HEADERS ${HEADERS} + ${CMAKE_CURRENT_LIST_DIR}/core/ipcclient.h + ${CMAKE_CURRENT_LIST_DIR}/core/privileged_process.h + ${CMAKE_CURRENT_LIST_DIR}/ui/systemtray_notificationhandler.h + ${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnprotocol.h + ${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.h + ${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.h + ${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.h + ${CMAKE_CURRENT_LIST_DIR}/protocols/xrayprotocol.h + ${CMAKE_CURRENT_LIST_DIR}/protocols/awgprotocol.h + ) + + set(SOURCES ${SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/core/ipcclient.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/privileged_process.cpp + ${CMAKE_CURRENT_LIST_DIR}/ui/systemtray_notificationhandler.cpp + ${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnprotocol.cpp + ${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.cpp + ${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.cpp + ${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.cpp + ${CMAKE_CURRENT_LIST_DIR}/protocols/xrayprotocol.cpp + ${CMAKE_CURRENT_LIST_DIR}/protocols/awgprotocol.cpp + ) endif() if(ANDROID) diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index f32d525a..aeed439b 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -2,8 +2,6 @@ #include #include -#include -#include #include #include #include @@ -12,16 +10,26 @@ #include #include #include +#include +#include #include "logger.h" -#include "ui/controllers/pageController.h" #include "ui/models/installedAppsModel.h" #include "version.h" #include "platforms/ios/QRCodeReaderBase.h" +#if defined(Q_OS_ANDROID) + #include "core/installedAppsImageProvider.h" + #include "platforms/android/android_controller.h" +#endif #include "protocols/qml_register_protocols.h" +#if defined(Q_OS_IOS) + #include "platforms/ios/ios_controller.h" + #include +#endif + AmneziaApplication::AmneziaApplication(int &argc, char *argv[]) : AMNEZIA_BASE_CLASS(argc, argv) { setQuitOnLastWindowClosed(false); @@ -76,12 +84,79 @@ void AmneziaApplication::init() m_vpnConnection->moveToThread(&m_vpnConnectionThread); m_vpnConnectionThread.start(); - m_coreController.reset(new CoreController(m_vpnConnection, m_settings, m_engine)); + initModels(); + loadTranslator(); + initControllers(); + +#ifdef Q_OS_ANDROID + if (!AndroidController::initLogging()) { + qFatal("Android logging initialization failed"); + } + AndroidController::instance()->setSaveLogs(m_settings->isSaveLogs()); + connect(m_settings.get(), &Settings::saveLogsChanged, AndroidController::instance(), &AndroidController::setSaveLogs); + + AndroidController::instance()->setScreenshotsEnabled(m_settings->isScreenshotsEnabled()); + connect(m_settings.get(), &Settings::screenshotsEnabledChanged, AndroidController::instance(), &AndroidController::setScreenshotsEnabled); + + connect(m_settings.get(), &Settings::serverRemoved, AndroidController::instance(), &AndroidController::resetLastServer); + + connect(m_settings.get(), &Settings::settingsCleared, []() { AndroidController::instance()->resetLastServer(-1); }); + + connect(AndroidController::instance(), &AndroidController::initConnectionState, this, [this](Vpn::ConnectionState state) { + m_connectionController->onConnectionStateChanged(state); + if (m_vpnConnection) + m_vpnConnection->restoreConnection(); + }); + if (!AndroidController::instance()->initialize()) { + qFatal("Android controller initialization failed"); + } + + connect(AndroidController::instance(), &AndroidController::importConfigFromOutside, this, [this](QString data) { + emit m_pageController->goToPageHome(); + m_importController->extractConfigFromData(data); + data.clear(); + emit m_pageController->goToPageViewConfig(); + }); + + m_engine->addImageProvider(QLatin1String("installedAppImage"), new InstalledAppsImageProvider); +#endif + +#ifdef Q_OS_IOS + IosController::Instance()->initialize(); + connect(IosController::Instance(), &IosController::importConfigFromOutside, this, [this](QString data) { + emit m_pageController->goToPageHome(); + m_importController->extractConfigFromData(data); + emit m_pageController->goToPageViewConfig(); + }); + + connect(IosController::Instance(), &IosController::importBackupFromOutside, this, [this](QString filePath) { + emit m_pageController->goToPageHome(); + m_pageController->goToPageSettingsBackup(); + emit m_settingsController->importBackupFromOutside(filePath); + }); + + QTimer::singleShot(0, this, [this]() { AmneziaVPN::toggleScreenshots(m_settings->isScreenshotsEnabled()); }); + + connect(m_settings.get(), &Settings::screenshotsEnabledChanged, [](bool enabled) { AmneziaVPN::toggleScreenshots(enabled); }); +#endif + +#ifndef Q_OS_ANDROID + m_notificationHandler.reset(NotificationHandler::create(nullptr)); + + connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, m_notificationHandler.get(), + &NotificationHandler::setConnectionState); + + connect(m_notificationHandler.get(), &NotificationHandler::raiseRequested, m_pageController.get(), &PageController::raiseMainWindow); + connect(m_notificationHandler.get(), &NotificationHandler::connectRequested, m_connectionController.get(), + static_cast(&ConnectionController::openConnection)); + connect(m_notificationHandler.get(), &NotificationHandler::disconnectRequested, m_connectionController.get(), + &ConnectionController::closeConnection); + connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(), &NotificationHandler::onTranslationsUpdated); +#endif m_engine->addImportPath("qrc:/ui/qml/Modules/"); m_engine->load(url); - - m_coreController->setQmlRoot(); + m_systemController->setQmlRoot(m_engine->rootObjects().value(0)); bool enabled = m_settings->isSaveLogs(); #ifndef Q_OS_ANDROID @@ -93,13 +168,13 @@ void AmneziaApplication::init() #endif Logger::setServiceLogsEnabled(enabled); -#ifdef Q_OS_WIN //TODO +#ifdef Q_OS_WIN if (m_parser.isSet("a")) - m_coreController->pageController()->showOnStartup(); + m_pageController->showOnStartup(); else - emit m_coreController->pageController()->raiseMainWindow(); + emit m_pageController->raiseMainWindow(); #else - m_coreController->pageController()->showOnStartup(); + m_pageController->showOnStartup(); #endif // Android TextArea clipboard workaround @@ -156,6 +231,33 @@ void AmneziaApplication::loadFonts() QFontDatabase::addApplicationFont(":/fonts/pt-root-ui_vf.ttf"); } +void AmneziaApplication::loadTranslator() +{ + auto locale = m_settings->getAppLanguage(); + m_translator.reset(new QTranslator()); + updateTranslator(locale); +} + +void AmneziaApplication::updateTranslator(const QLocale &locale) +{ + if (!m_translator->isEmpty()) { + QCoreApplication::removeTranslator(m_translator.get()); + } + + QString strFileName = QString(":/translations/amneziavpn") + QLatin1String("_") + locale.name() + ".qm"; + if (m_translator->load(strFileName)) { + if (QCoreApplication::installTranslator(m_translator.get())) { + m_settings->setAppLanguage(locale); + } + } else { + m_settings->setAppLanguage(QLocale::English); + } + + m_engine->retranslate(); + + emit translationsUpdated(); +} + bool AmneziaApplication::parseCommands() { m_parser.setApplicationDescription(APPLICATION_NAME); @@ -180,20 +282,19 @@ bool AmneziaApplication::parseCommands() } #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) -void AmneziaApplication::startLocalServer() -{ +void AmneziaApplication::startLocalServer() { const QString serverName("AmneziaVPNInstance"); QLocalServer::removeServer(serverName); - QLocalServer *server = new QLocalServer(this); + QLocalServer* server = new QLocalServer(this); server->listen(serverName); QObject::connect(server, &QLocalServer::newConnection, this, [server, this]() { if (server) { - QLocalSocket *clientConnection = server->nextPendingConnection(); + QLocalSocket* clientConnection = server->nextPendingConnection(); clientConnection->deleteLater(); } - emit m_coreController->pageController()->raiseMainWindow(); //TODO + emit m_pageController->raiseMainWindow(); }); } #endif @@ -203,12 +304,163 @@ QQmlApplicationEngine *AmneziaApplication::qmlEngine() const return m_engine; } -QNetworkAccessManager *AmneziaApplication::networkManager() +void AmneziaApplication::initModels() { - return m_nam; + m_containersModel.reset(new ContainersModel(this)); + m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get()); + + m_defaultServerContainersModel.reset(new ContainersModel(this)); + m_engine->rootContext()->setContextProperty("DefaultServerContainersModel", m_defaultServerContainersModel.get()); + + m_serversModel.reset(new ServersModel(m_settings, this)); + m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get()); + connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(), &ContainersModel::updateModel); + connect(m_serversModel.get(), &ServersModel::defaultServerContainersUpdated, m_defaultServerContainersModel.get(), + &ContainersModel::updateModel); + m_serversModel->resetModel(); + + m_languageModel.reset(new LanguageModel(m_settings, this)); + m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get()); + connect(m_languageModel.get(), &LanguageModel::updateTranslations, this, &AmneziaApplication::updateTranslator); + connect(this, &AmneziaApplication::translationsUpdated, m_languageModel.get(), &LanguageModel::translationsUpdated); + + m_sitesModel.reset(new SitesModel(m_settings, this)); + m_engine->rootContext()->setContextProperty("SitesModel", m_sitesModel.get()); + + m_appSplitTunnelingModel.reset(new AppSplitTunnelingModel(m_settings, this)); + m_engine->rootContext()->setContextProperty("AppSplitTunnelingModel", m_appSplitTunnelingModel.get()); + + m_protocolsModel.reset(new ProtocolsModel(m_settings, this)); + m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get()); + + m_openVpnConfigModel.reset(new OpenVpnConfigModel(this)); + m_engine->rootContext()->setContextProperty("OpenVpnConfigModel", m_openVpnConfigModel.get()); + + m_shadowSocksConfigModel.reset(new ShadowSocksConfigModel(this)); + m_engine->rootContext()->setContextProperty("ShadowSocksConfigModel", m_shadowSocksConfigModel.get()); + + m_cloakConfigModel.reset(new CloakConfigModel(this)); + m_engine->rootContext()->setContextProperty("CloakConfigModel", m_cloakConfigModel.get()); + + m_wireGuardConfigModel.reset(new WireGuardConfigModel(this)); + m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireGuardConfigModel.get()); + + m_awgConfigModel.reset(new AwgConfigModel(this)); + m_engine->rootContext()->setContextProperty("AwgConfigModel", m_awgConfigModel.get()); + + m_xrayConfigModel.reset(new XrayConfigModel(this)); + m_engine->rootContext()->setContextProperty("XrayConfigModel", m_xrayConfigModel.get()); + +#ifdef Q_OS_WINDOWS + m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this)); + m_engine->rootContext()->setContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel.get()); +#endif + + m_sftpConfigModel.reset(new SftpConfigModel(this)); + m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get()); + + m_socks5ConfigModel.reset(new Socks5ProxyConfigModel(this)); + m_engine->rootContext()->setContextProperty("Socks5ProxyConfigModel", m_socks5ConfigModel.get()); + + m_clientManagementModel.reset(new ClientManagementModel(m_settings, this)); + m_engine->rootContext()->setContextProperty("ClientManagementModel", m_clientManagementModel.get()); + connect(m_clientManagementModel.get(), &ClientManagementModel::adminConfigRevoked, m_serversModel.get(), + &ServersModel::clearCachedProfile); + + m_apiServicesModel.reset(new ApiServicesModel(this)); + m_engine->rootContext()->setContextProperty("ApiServicesModel", m_apiServicesModel.get()); + + m_apiCountryModel.reset(new ApiCountryModel(this)); + m_engine->rootContext()->setContextProperty("ApiCountryModel", m_apiCountryModel.get()); + connect(m_serversModel.get(), &ServersModel::updateApiLanguageModel, this, [this]() { + m_apiCountryModel->updateModel(m_serversModel->getProcessedServerData("apiAvailableCountries").toJsonArray(), + m_serversModel->getProcessedServerData("apiServerCountryCode").toString()); + }); + connect(m_serversModel.get(), &ServersModel::updateApiServicesModel, this, + [this]() { m_apiServicesModel->updateModel(m_serversModel->getProcessedServerData("apiConfig").toJsonObject()); }); } -QClipboard *AmneziaApplication::getClipboard() +void AmneziaApplication::initControllers() { - return this->clipboard(); + m_connectionController.reset( + new ConnectionController(m_serversModel, m_containersModel, m_clientManagementModel, m_vpnConnection, m_settings)); + m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get()); + + connect(m_connectionController.get(), qOverload(&ConnectionController::connectionErrorOccurred), this, + [this](const QString &errorMessage) { + emit m_pageController->showErrorMessage(errorMessage); + emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); + }); + + connect(m_connectionController.get(), qOverload(&ConnectionController::connectionErrorOccurred), this, + [this](ErrorCode errorCode) { + emit m_pageController->showErrorMessage(errorCode); + emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); + }); + + connect(m_connectionController.get(), &ConnectionController::connectButtonClicked, m_connectionController.get(), + &ConnectionController::toggleConnection, Qt::QueuedConnection); + + m_pageController.reset(new PageController(m_serversModel, m_settings)); + m_engine->rootContext()->setContextProperty("PageController", m_pageController.get()); + + m_focusController.reset(new FocusController(m_engine, this)); + m_engine->rootContext()->setContextProperty("FocusController", m_focusController.get()); + + m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, m_clientManagementModel, + m_apiServicesModel, m_settings)); + m_engine->rootContext()->setContextProperty("InstallController", m_installController.get()); + connect(m_installController.get(), &InstallController::passphraseRequestStarted, m_pageController.get(), + &PageController::showPassphraseRequestDrawer); + connect(m_pageController.get(), &PageController::passphraseRequestDrawerClosed, m_installController.get(), + &InstallController::setEncryptedPassphrase); + connect(m_installController.get(), &InstallController::currentContainerUpdated, m_connectionController.get(), + &ConnectionController::onCurrentContainerUpdated); + + connect(m_installController.get(), &InstallController::updateServerFromApiFinished, this, [this]() { + disconnect(m_reloadConfigErrorOccurredConnection); + emit m_connectionController->configFromApiUpdated(); + }); + + connect(m_connectionController.get(), &ConnectionController::updateApiConfigFromGateway, this, [this]() { + m_reloadConfigErrorOccurredConnection = connect( + m_installController.get(), qOverload(&InstallController::installationErrorOccurred), this, + [this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); }, + static_cast(Qt::AutoConnection || Qt::SingleShotConnection)); + m_installController->updateServiceFromApi(m_serversModel->getDefaultServerIndex(), "", ""); + }); + + connect(m_connectionController.get(), &ConnectionController::updateApiConfigFromTelegram, this, [this]() { + m_reloadConfigErrorOccurredConnection = connect( + m_installController.get(), qOverload(&InstallController::installationErrorOccurred), this, + [this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); }, + static_cast(Qt::AutoConnection || Qt::SingleShotConnection)); + m_serversModel->removeApiConfig(m_serversModel->getDefaultServerIndex()); + m_installController->updateServiceFromTelegram(m_serversModel->getDefaultServerIndex()); + }); + + connect(this, &AmneziaApplication::translationsUpdated, m_connectionController.get(), &ConnectionController::onTranslationsUpdated); + + m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings)); + m_engine->rootContext()->setContextProperty("ImportController", m_importController.get()); + + m_exportController.reset(new ExportController(m_serversModel, m_containersModel, m_clientManagementModel, m_settings)); + m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get()); + + m_settingsController.reset( + new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_sitesModel, m_appSplitTunnelingModel, m_settings)); + m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get()); + if (m_settingsController->isAutoConnectEnabled() && m_serversModel->getDefaultServerIndex() >= 0) { + QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); }); + } + connect(m_settingsController.get(), &SettingsController::amneziaDnsToggled, m_serversModel.get(), &ServersModel::toggleAmneziaDns); + + m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel)); + m_engine->rootContext()->setContextProperty("SitesController", m_sitesController.get()); + + m_appSplitTunnelingController.reset(new AppSplitTunnelingController(m_settings, m_appSplitTunnelingModel)); + m_engine->rootContext()->setContextProperty("AppSplitTunnelingController", m_appSplitTunnelingController.get()); + + m_systemController.reset(new SystemController(m_settings)); + m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get()); } diff --git a/client/amnezia_application.h b/client/amnezia_application.h index ea5f6f52..cfeac0d1 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -11,12 +11,44 @@ #else #include #endif -#include -#include "core/controllers/coreController.h" #include "settings.h" #include "vpnconnection.h" +#include "ui/controllers/connectionController.h" +#include "ui/controllers/exportController.h" +#include "ui/controllers/importController.h" +#include "ui/controllers/installController.h" +#include "ui/controllers/focusController.h" +#include "ui/controllers/pageController.h" +#include "ui/controllers/settingsController.h" +#include "ui/controllers/sitesController.h" +#include "ui/controllers/systemController.h" +#include "ui/controllers/appSplitTunnelingController.h" +#include "ui/models/containers_model.h" +#include "ui/models/languageModel.h" +#include "ui/models/protocols/cloakConfigModel.h" +#ifndef Q_OS_ANDROID + #include "ui/notificationhandler.h" +#endif +#ifdef Q_OS_WINDOWS + #include "ui/models/protocols/ikev2ConfigModel.h" +#endif +#include "ui/models/protocols/awgConfigModel.h" +#include "ui/models/protocols/openvpnConfigModel.h" +#include "ui/models/protocols/shadowsocksConfigModel.h" +#include "ui/models/protocols/wireguardConfigModel.h" +#include "ui/models/protocols/xrayConfigModel.h" +#include "ui/models/protocols_model.h" +#include "ui/models/servers_model.h" +#include "ui/models/services/sftpConfigModel.h" +#include "ui/models/services/socks5ProxyConfigModel.h" +#include "ui/models/sites_model.h" +#include "ui/models/clientManagementModel.h" +#include "ui/models/appSplitTunnelingModel.h" +#include "ui/models/apiServicesModel.h" +#include "ui/models/apiCountryModel.h" + #define amnApp (static_cast(QCoreApplication::instance())) #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) @@ -35,6 +67,8 @@ public: void init(); void registerTypes(); void loadFonts(); + void loadTranslator(); + void updateTranslator(const QLocale &locale); bool parseCommands(); #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) @@ -42,24 +76,68 @@ public: #endif QQmlApplicationEngine *qmlEngine() const; - QNetworkAccessManager *networkManager(); - QClipboard *getClipboard(); + QNetworkAccessManager *manager() { return m_nam; } + +signals: + void translationsUpdated(); private: + void initModels(); + void initControllers(); + QQmlApplicationEngine *m_engine {}; std::shared_ptr m_settings; - QScopedPointer m_coreController; - QSharedPointer m_containerProps; QSharedPointer m_protocolProps; + QSharedPointer m_translator; QCommandLineParser m_parser; + QSharedPointer m_containersModel; + QSharedPointer m_defaultServerContainersModel; + QSharedPointer m_serversModel; + QSharedPointer m_languageModel; + QSharedPointer m_protocolsModel; + QSharedPointer m_sitesModel; + QSharedPointer m_appSplitTunnelingModel; + QSharedPointer m_clientManagementModel; + QSharedPointer m_apiServicesModel; + QSharedPointer m_apiCountryModel; + + QScopedPointer m_openVpnConfigModel; + QScopedPointer m_shadowSocksConfigModel; + QScopedPointer m_cloakConfigModel; + QScopedPointer m_xrayConfigModel; + QScopedPointer m_wireGuardConfigModel; + QScopedPointer m_awgConfigModel; +#ifdef Q_OS_WINDOWS + QScopedPointer m_ikev2ConfigModel; +#endif + + QScopedPointer m_sftpConfigModel; + QScopedPointer m_socks5ConfigModel; + QSharedPointer m_vpnConnection; QThread m_vpnConnectionThread; +#ifndef Q_OS_ANDROID + QScopedPointer m_notificationHandler; +#endif + + QScopedPointer m_connectionController; + QScopedPointer m_focusController; + QScopedPointer m_pageController; + QScopedPointer m_installController; + QScopedPointer m_importController; + QScopedPointer m_exportController; + QScopedPointer m_settingsController; + QScopedPointer m_sitesController; + QScopedPointer m_systemController; + QScopedPointer m_appSplitTunnelingController; QNetworkAccessManager *m_nam; + + QMetaObject::Connection m_reloadConfigErrorOccurredConnection; }; #endif // AMNEZIA_APPLICATION_H diff --git a/client/android/AndroidManifest.xml b/client/android/AndroidManifest.xml index b28f754b..96f60f53 100644 --- a/client/android/AndroidManifest.xml +++ b/client/android/AndroidManifest.xml @@ -11,7 +11,7 @@ - +