Merge branch 'qmake-to-cmake-migration' of github.com:amnezia-vpn/desktop-client into feature/qt6-libssh-support

This commit is contained in:
vladimir.kuznetsov 2022-12-18 09:17:35 +03:00
commit b0489aa61b
60 changed files with 945 additions and 1112 deletions

View file

@ -152,7 +152,6 @@ jobs:
export QT_MACOS_ROOT_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos" export QT_MACOS_ROOT_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos"
export QT_IOS_BIN=$QT_BIN_DIR export QT_IOS_BIN=$QT_BIN_DIR
export PATH=$PATH:~/go/bin export PATH=$PATH:~/go/bin
cd client
mkdir build-ios mkdir build-ios
$QT_IOS_BIN/qt-cmake . -B build-ios -GXcode -DQT_HOST_PATH=$QT_MACOS_ROOT_DIR $QT_IOS_BIN/qt-cmake . -B build-ios -GXcode -DQT_HOST_PATH=$QT_MACOS_ROOT_DIR

2
.gitignore vendored
View file

@ -23,6 +23,7 @@ qrc_*.cpp
ui_*.h ui_*.h
Makefile* Makefile*
*build-* *build-*
compile_commands.json
# fastlane # fastlane
client/fastlane/report.xml client/fastlane/report.xml
@ -125,3 +126,4 @@ captures/
# Android Profiling # Android Profiling
*.hprof *.hprof
client/3rd/ShadowSocks/ss_ios.xcconfig

View file

@ -1,343 +0,0 @@
branches:
only:
- master
- dev
- /\d+\.\d+/
jobs:
include:
- name: MacOS
os: osx
osx_image: xcode13.4
language: cpp
env:
- PATH=/usr/local/opt/ccache/libexec:$PATH
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/clang_64/bin
- QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
brew install p7zip ccache && \
python3 -m pip install --upgrade pip && \
python3 -m pip install -U aqtinstall requests py7zr && \
python3 -m pip show aqtinstall && \
python3 -m aqt install-qt mac desktop $QT_VERSION clang_64 -m all -O $HOME/Qt && \
python3 -m aqt install-tool mac desktop tools_ifw -O $HOME/Qt ; \
fi
script:
- bash deploy/build_macos.sh
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN.dmg"
on:
tags: true
branch: master
cache:
- ccache
- directories:
- $HOME/Qt
- $HOME/Library/Caches/Homebrew
# ------------------------------------------------------
- name: Windows_x64
os: windows
language: cpp
env:
- PATH=/c/Python39:/c/Python39/Scripts:$PATH
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR="c:\\Qt\\$QT_VERSION\\msvc2019_64\\bin"
- QIF_BIN_DIR="c:\\Qt\\Tools\\QtInstallerFramework\\${QIF_VERSION}\\bin"
- BUILD_ARCH=64
- MSVC_PATH_WIN="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community"
- MSVC_PATH="/C/Program Files (x86)/Microsoft Visual Studio/2019/Community"
install:
- if [ ! -f "$MSVC_PATH/VC/Auxiliary/Build/vcvars64.bat" ]; then choco install --ignorepackagecodes --no-progress -y visualstudio2019buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Component.VC.ATLMFC --includeRecommended --nocache --installPath $MSVC_PATH_WIN"; fi
- if [ ! -f /C/Qt/$QT_VERSION/msvc2019_64/bin/qmake ]; then choco install python --version 3.9.1; fi
- |
if [ ! -f /C/Qt/$QT_VERSION/msvc2019_64/bin/qmake ]; then \
python -m pip install --upgrade pip && \
pip3 install -U aqtinstall requests py7zr && \
pip3 show aqtinstall && \
aqt install-qt windows desktop $QT_VERSION win64_msvc2019_64 -m all -O /C/Qt && \
aqt install-tool windows desktop tools_ifw -O /C/Qt ; \
fi
- choco install ccache
script:
- echo set BUILD_ARCH=$BUILD_ARCH > winbuild.bat
- echo set QT_BIN_DIR="$QT_BIN_DIR" >> winbuild.bat
- echo set QIF_BIN_DIR="$QIF_BIN_DIR" >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\Common7\\Tools\\VsDevCmd.bat\" -arch=amd64" >> winbuild.bat
- echo call deploy\\build_windows.bat >> winbuild.bat
- cmd //c winbuild.bat
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN_x64.exe"
on:
tags: true
branch: master
cache:
directories:
- /C/Qt
- $MSVC_PATH
# ------------------------------------------------------
- name: Windows_x32
os: windows
language: cpp
env:
- PATH=/c/Python39:/c/Python39/Scripts:$PATH
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR="c:\\Qt\\${QT_VERSION}\\msvc2019\\bin"
- QIF_BIN_DIR="c:\\Qt\\Tools\\QtInstallerFramework\\${QIF_VERSION}\\bin"
- BUILD_ARCH=32
- MSVC_PATH_WIN="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community"
- MSVC_PATH="/C/Program Files (x86)/Microsoft Visual Studio/2019/Community"
install:
- if [ ! -f "$MSVC_PATH/VC/Auxiliary/Build/vcvars64.bat" ]; then choco install --ignorepackagecodes --no-progress -y visualstudio2019buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Component.VC.ATLMFC --includeRecommended --nocache --installPath $MSVC_PATH_WIN"; fi
- if [ ! -f /C/Qt/$QT_VERSION/msvc2019/bin/qmake ]; then choco install python --version 3.9.1; fi
- |
if [ ! -f /C/Qt/$QT_VERSION/msvc2019/bin/qmake ]; then \
python -m pip install --upgrade pip && \
pip3 install -U aqtinstall requests py7zr && \
pip3 show aqtinstall && \
aqt install-qt windows desktop $QT_VERSION win32_msvc2019 -m all -O /C/Qt && \
aqt install-tool windows desktop tools_ifw -O /C/Qt ; \
fi
- choco install ccache
script:
- echo set BUILD_ARCH=$BUILD_ARCH > winbuild.bat
- echo set QT_BIN_DIR="$QT_BIN_DIR" >> winbuild.bat
- echo set QIF_BIN_DIR="$QIF_BIN_DIR" >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\Common7\\Tools\\VsDevCmd.bat\"" >> winbuild.bat
- echo call deploy\\build_windows.bat >> winbuild.bat
- cmd //c winbuild.bat
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN_x32.exe"
on:
tags: true
branch: master
cache:
directories:
- /C/Qt
- $MSVC_PATH
# ------------------------------------------------------
- name: Linux
os: linux
language: cpp
dist: focal
addons:
apt:
packages:
- p7zip
- p7zip-full
- python3
- python3-pip
- libgl-dev
- mesa-common-dev
- libpulse-dev
- libxcb-*
- libxkbcommon-x11-0
env:
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/gcc_64/bin
- QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
python3 -m pip install --user $(whoami) --upgrade pip && \
export PATH=$HOME/.local/bin:$PATH && \
python3 -m pip install -U aqtinstall requests py7zr && \
python3 -m pip show aqtinstall && \
python3 -m aqt install-qt linux desktop $QT_VERSION gcc_64 -m all -O $HOME/Qt && \
python3 -m aqt install-tool linux desktop tools_ifw -O $HOME/Qt ; \
fi
script:
- bash deploy/build_linux.sh
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN.bundle"
on:
tags: true
branch: master
cache:
- ccache
- directories:
- $HOME/Qt
- $HOME/.ccache
# ------------------------------------------------------
- name: Android
os: linux
language: cpp
dist: focal
env:
- QT_VERSION=5.15.2
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/android/bin
- ANDROID_API_VERSION=android-21
- ANDROID_HOME=$HOME/sdk
- ANDROID_SDK_ROOT=$ANDROID_HOME
- LOCAL_ANDROID_HOME=$ANDROID_HOME
- LOCAL_ANDROID_SDK_ROOT=$ANDROID_HOME
- NDK_VERSION=21d
- ANDROID_NDK_PLATFORM=android-21
- ANDROID_NDK_HOME=$HOME/android-ndk-r${NDK_VERSION}
- ANDROID_NDK_ROOT=$ANDROID_NDK_HOME
- ANDROID_NDK_HOST=linux-x86_64
- LOCAL_ANDROID_NDK_HOME=$ANDROID_NDK_HOME
- LOCAL_ANDROID_NDK_HOST_PLATFORM=$ANDROID_NDK_HOST
- JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
- TERM=dumb
addons:
apt:
packages:
- p7zip
- python3
- python3-pip
- openjdk-8-jdk
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
python3 -m pip install -U aqtinstall requests py7zr && \
python3 -m pip show aqtinstall && \
python3 -m aqt install-qt linux android $QT_VERSION -m all -O $HOME/Qt ; \
fi
- |
if [ ! -f $ANDROID_SDK_ROOT/tools/bin/sdkmanager ]; then \
echo "Download Android SDK" && \
wget https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip -qO $HOME/sdk.zip > /dev/null && \
unzip -q -d $ANDROID_SDK_ROOT $HOME/sdk.zip && \
echo "Download tools" && \
yes | $ANDROID_SDK_ROOT/tools/bin/sdkmanager --licenses > /dev/null 2>&1 && \
$ANDROID_SDK_ROOT/tools/bin/sdkmanager --install "cmdline-tools;latest" "platform-tools" "platforms;android-30" "build-tools;30.0.2" > /dev/null 2>&1 || exit 1 ; \
fi
- |
if [ ! -f $ANDROID_NDK_ROOT/ndk-build ]; then \
wget https://dl.google.com/android/repository/android-ndk-r${NDK_VERSION}-linux-x86_64.zip -qO $HOME/ndk.zip &&
unzip -q -d $HOME $HOME/ndk.zip ; \
fi
script:
- bash deploy/build_android.sh
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN.aab"
on:
tags: true
branch: master
cache:
- ccache
- directories:
- $HOME/Qt
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- $HOME/.android/build-cache
- $ANDROID_NDK_HOME
- $ANDROID_SDK_ROOT
# ------------------------------------------------------
- name: iOS
os: osx
osx_image: xcode13.4
language: cpp
env:
- PATH=/usr/local/opt/ccache/libexec:~/go/bin:$PATH
- QT_VERSION=5.15.2
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/ios/bin
- QT_IOS_BIN=$QT_BIN_DIR
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
brew install p7zip ccache && \
python3 -m pip install --upgrade pip && \
python3 -m pip install -U aqtinstall requests py7zr && \
python3 -m pip show aqtinstall && \
python3 -m aqt install-qt mac ios $QT_VERSION -m all -O $HOME/Qt ; \
fi
- brew install golang
- go install golang.org/x/mobile/cmd/gomobile@latest
- gomobile init
script:
- bash deploy/build_ios.sh
after_script:
- ccache --show-stats
cache:
- ccache
- directories:
- $HOME/Qt
- $HOME/Library/Caches/Homebrew
before_cache:
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then brew cleanup; fi
# Cache only .git files under "/usr/local/Homebrew" so "brew update" does not take 5min every build
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then find /usr/local/Homebrew \! -regex ".+\.git.+" -delete; fi

View file

@ -1,7 +1,7 @@
# Amnezia VPN # Amnezia VPN
## _The best client for self-hosted VPN_ ## _The best client for self-hosted VPN_
[![Build Status](https://travis-ci.com/amnezia-vpn/desktop-client.svg?branch=master)](https://travis-ci.com/amnezia-vpn/desktop-client) [![Build Status](https://github.com/amnezia-vpn/desktop-client/actions/workflows/deploy.yml/badge.svg?branch=dev)]
Amnezia is a VPN client with the key feature of deploying your own VPN server on you virtual server. Amnezia is a VPN client with the key feature of deploying your own VPN server on you virtual server.
@ -87,6 +87,11 @@ Error 1
Add a user defined variable to both AmneziaVPN and WireGuardNetworkExtension targets' build settings with Add a user defined variable to both AmneziaVPN and WireGuardNetworkExtension targets' build settings with
key `PATH` and value `${PATH}/path/to/bin/folder/with/go/executable`, e.g. `${PATH}:/usr/local/go/bin`. key `PATH` and value `${PATH}/path/to/bin/folder/with/go/executable`, e.g. `${PATH}:/usr/local/go/bin`.
if above error still persists on you M1 Mac, then most proably you need to install arch based cmake
```
arch -arm64 brew install cmake
```
Build might fail with "source files not found" error the first time you try it, because modern XCode build system compiles Build might fail with "source files not found" error the first time you try it, because modern XCode build system compiles
dependencies in parallel, and some dependencies end up being built after the ones that dependencies in parallel, and some dependencies end up being built after the ones that
require them. In this case simply restart the build. require them. In this case simply restart the build.

View file

@ -1,23 +0,0 @@
SUPPORTED_PLATFORMS = iphoneos
TARGETED_DEVICE_FAMILY = 1,2
HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/ShadowSocks
//HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/ShadowSocks $(SRCROOT)/ShadowSocks/libcares/include $(SRCROOT)/ShadowSocks/libev/arm64/include $(SRCROOT)/ShadowSocks/libsodium/include $(SRCROOT)/ShadowSocks/mbedtls/include $(SRCROOT)/ShadowSocks/pcre/arm64/include $(SRCROOT)/ShadowSocks/shadowsocks-libev/include
//CLANG_CXX_LANGUAGE_STANDARD = gnu++14
//CLANG_CXX_LIBRARY = libc++
////////////////////////////////////////////////////////////////////////////////
//
// iOS-specific settings
//
IPHONEOS_DEPLOYMENT_TARGET = 9.3
SDKROOT[arch=arm64] = iphoneos
SDKROOT[arch=armv7] = iphoneos
SDKROOT[arch=armv7s] = iphoneos
VALID_ARCHS[sdk=iphoneos*] = arm64
PROJECT_TEMP_DIR = /Users/sanchez/work/vied/ios/vpn/desktop-client-bkp/client/3rd/ShadowSocks/build/ShadowSocks.build
CONFIGURATION_BUILD_DIR = /Users/sanchez/work/vied/ios/vpn/desktop-client-bkp/client/3rd/ShadowSocks/build/Release-iphoneos
BUILT_PRODUCTS_DIR = /Users/sanchez/work/vied/ios/vpn/desktop-client-bkp/client/3rd/ShadowSocks/build/Release-iphoneos

View file

@ -1,9 +1,9 @@
cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR)
set(PROJECT AmneziaVPN) set(PROJECT AmneziaVPN)
project(${PROJECT} VERSION 2.0.10) project(${PROJECT} VERSION 2.1.2)
set(BUILD_ID 2) set(BUILD_ID 1)
set(QT_BUILD_TOOLS_WHEN_CROSS_COMPILING ON) SET(QT_BUILD_TOOLS_WHEN_CROSS_COMPILING ON)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.17) if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.17)
@ -30,8 +30,11 @@ set(LIBS ${LIBS}
Qt6::Core5Compat Qt6::Core5Compat
) )
qt_standard_project_setup()
if(IOS) if(IOS)
execute_process(COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/scripts/openvpn.sh) execute_process(COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/scripts/openvpn.sh args
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
endif() endif()
set(IS_CI ${CI}) set(IS_CI ${CI})
@ -43,87 +46,12 @@ if(IS_CI)
endif() endif()
endif() endif()
include(${CMAKE_CURRENT_LIST_DIR}/3rd/QtSsh/src/ssh/qssh.cmake) include(${CMAKE_CURRENT_LIST_DIR}/cmake/3rdparty.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/3rd/QtSsh/src/botan/botan.cmake)
if(NOT IOS AND NOT ANDROID)
include(${CMAKE_CURRENT_LIST_DIR}/3rd/SingleApplication/singleapplication.cmake)
endif()
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/3rd/SortFilterProxyModel)
set(LIBS ${LIBS} SortFilterProxyModel)
include(${CMAKE_CURRENT_LIST_DIR}/3rd/qrcodegen/qrcodegen.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/3rd/QSimpleCrypto/QSimpleCrypto.cmake)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/3rd/zlib)
if(WIN32)
set(ZLIB_LIBRARY $<IF:$<CONFIG:Debug>,zlibd,zlib>)
else()
set(ZLIB_LIBRARY z)
endif()
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/3rd/zlib" "${CMAKE_CURRENT_BINARY_DIR}/3rd/zlib")
link_directories(${CMAKE_CURRENT_BINARY_DIR}/3rd/zlib)
link_libraries(${ZLIB_LIBRARY})
if(NOT LINUX)
set(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/3rd/OpenSSL")
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include")
set(OPENSSL_LIBRARIES_DIR "${OPENSSL_ROOT_DIR}/lib")
set(OPENSSL_LIBRARIES "ssl" "crypto")
set(OPENSSL_PATH "${CMAKE_CURRENT_LIST_DIR}/3rd/OpenSSL")
if(WIN32)
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_PATH}/lib/windows/x86_64/libssl.lib")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_PATH}/lib/windows/x86_64/libcrypto.lib")
else()
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_PATH}/lib/windows/x86/libssl.lib")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_PATH}/lib/windows/x86/libcrypto.lib")
endif()
elseif(APPLE AND NOT IOS)
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_PATH}/lib/macos/x86_64/libssl.a")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_PATH}/lib/macos/x86_64/libcrypto.a")
elseif(IOS)
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_LIBRARIES_DIR}/libcrypto.a")
set(OPENSSL_SSL_LIBRARY "${OPENSSL_LIBRARIES_DIR}/libssl.a")
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_PATH}/lib/ios/iphone/libssl.a")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_PATH}/lib/ios/iphone/libcrypto.a")
endif()
file(COPY ${OPENSSL_LIB_SSL_PATH} ${OPENSSL_LIB_CRYPTO_PATH}
DESTINATION ${OPENSSL_LIBRARIES_DIR})
file(COPY "${OPENSSL_PATH}/include"
DESTINATION ${OPENSSL_ROOT_DIR})
endif()
set(OPENSSL_USE_STATIC_LIBS TRUE)
find_package(OpenSSL REQUIRED)
set(LIBS ${LIBS}
OpenSSL::Crypto
OpenSSL::SSL
)
set(WITH_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/3rd/libssh)
add_compile_definitions(_WINSOCKAPI_)
set(LIBS ${LIBS} ssh)
set(BUILD_WITH_QT6 ON)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/3rd/qtkeychain)
set(LIBS ${LIBS} qt6keychain)
include_directories( include_directories(
${CMAKE_CURRENT_LIST_DIR}/3rd/QSimpleCrypto/include
${CMAKE_CURRENT_LIST_DIR}/3rd/OpenSSL/include
${CMAKE_CURRENT_LIST_DIR}/../ipc ${CMAKE_CURRENT_LIST_DIR}/../ipc
${CMAKE_CURRENT_LIST_DIR}/3rd/qtkeychain
${CMAKE_CURRENT_LIST_DIR}/3rd/libssh/include
${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/3rd/qtkeychain
${CMAKE_CURRENT_BINARY_DIR}/3rd/libssh/include
) )
set(HEADERS ${HEADERS} set(HEADERS ${HEADERS}
@ -215,7 +143,7 @@ if(WIN32)
) )
set(RESOURCES ${RESOURCES} set(RESOURCES ${RESOURCES}
${CMAKE_CURRENT_LIST_DIR}/platform_win/vpnclient.rc ${CMAKE_CURRENT_LIST_DIR}/platforms/windows/amneziavpn.rc
) )
set(LIBS ${LIBS} set(LIBS ${LIBS}
@ -334,6 +262,8 @@ endif()
if(IOS) if(IOS)
message("Client iOS build") message("Client iOS build")
find_package(Qt6 REQUIRED COMPONENTS ShaderTools) find_package(Qt6 REQUIRED COMPONENTS ShaderTools)
set(LIBS ${LIBS} Qt6::ShaderTools) set(LIBS ${LIBS} Qt6::ShaderTools)
@ -379,6 +309,7 @@ endif()
if(CMAKE_OSX_SYSROOT STREQUAL "iphoneos") if(CMAKE_OSX_SYSROOT STREQUAL "iphoneos")
message("Building for iPhone OS") message("Building for iPhone OS")
set(CMAKE_OSX_DEPLOYMENT_TARGET 13.0) set(CMAKE_OSX_DEPLOYMENT_TARGET 13.0)
endif() endif()
qt_add_executable(${PROJECT} ${SOURCES} ${HEADERS} ${RESOURCES} ${QRC}) qt_add_executable(${PROJECT} ${SOURCES} ${HEADERS} ${RESOURCES} ${QRC})
@ -391,14 +322,14 @@ if(IOS)
enable_language(OBJC) enable_language(OBJC)
enable_language(OBJCXX) enable_language(OBJCXX)
enable_language(Swift) enable_language(Swift)
include(src/cmake/osxtools.cmake) include(cmake/osxtools.cmake)
# set(CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY TRUE) # set(CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY TRUE)
set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")
set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon") set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon")
set_target_properties(${PROJECT} PROPERTIES XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION) set_target_properties(${PROJECT} PROPERTIES XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION)
set(CMAKE_XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks") set(CMAKE_XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../../Frameworks")
set(CMAKE_XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS ${CMAKE_CURRENT_LIST_DIR}/3rd/OpenVPNAdapter/build/Release-iphoneos) set(CMAKE_XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS ${CMAKE_CURRENT_LIST_DIR}/3rd/OpenVPNAdapter/build/Release-iphoneos)
@ -418,7 +349,7 @@ if(IOS)
set_target_properties(${PROJECT} PROPERTIES set_target_properties(${PROJECT} PROPERTIES
XCODE_ATTRIBUTE_SWIFT_VERSION "5.0" XCODE_ATTRIBUTE_SWIFT_VERSION "5.0"
XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES" XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES"
XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_SOURCE_DIR}/platforms/ios/WireGuard-Bridging-Header.h" XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_LIST_DIR}/platforms/ios/WireGuard-Bridging-Header.h"
XCODE_ATTRIBUTE_SWIFT_PRECOMPILE_BRIDGING_HEADER "NO" XCODE_ATTRIBUTE_SWIFT_PRECOMPILE_BRIDGING_HEADER "NO"
XCODE_ATTRIBUTE_SWIFT_OPTIMIZATION_LEVEL "-Onone" XCODE_ATTRIBUTE_SWIFT_OPTIMIZATION_LEVEL "-Onone"
XCODE_ATTRIBUTE_SWIFT_OBJC_INTERFACE_HEADER_NAME "AmneziaVPN-Swift.h" XCODE_ATTRIBUTE_SWIFT_OBJC_INTERFACE_HEADER_NAME "AmneziaVPN-Swift.h"
@ -427,7 +358,7 @@ if(IOS)
set_target_properties(${PROJECT} PROPERTIES set_target_properties(${PROJECT} PROPERTIES
OUTPUT_NAME "AmneziaVPN" OUTPUT_NAME "AmneziaVPN"
MACOSX_BUNDLE ON MACOSX_BUNDLE ON
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/ios/app/Info.plist.in MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_LIST_DIR}/ios/app/Info.plist.in
MACOSX_BUNDLE_BUNDLE_NAME "AmneziaVPN" MACOSX_BUNDLE_BUNDLE_NAME "AmneziaVPN"
MACOSX_BUNDLE_BUNDLE_VERSION "${BUILD_ID}" MACOSX_BUNDLE_BUNDLE_VERSION "${BUILD_ID}"
MACOSX_BUNDLE_COPYRIGHT "MPL-2.0" MACOSX_BUNDLE_COPYRIGHT "MPL-2.0"
@ -436,12 +367,14 @@ if(IOS)
MACOSX_BUNDLE_LONG_VERSION_STRING "${CMAKE_PROJECT_VERSION}-${BUILD_ID}" MACOSX_BUNDLE_LONG_VERSION_STRING "${CMAKE_PROJECT_VERSION}-${BUILD_ID}"
MACOSX_BUNDLE_SHORT_VERSION_STRING "${CMAKE_PROJECT_VERSION}" MACOSX_BUNDLE_SHORT_VERSION_STRING "${CMAKE_PROJECT_VERSION}"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}"
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/ios/app/main.entitlements" XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_LIST_DIR}/ios/app/main.entitlements"
XCODE_ATTRIBUTE_MARKETING_VERSION "${CMAKE_PROJECT_VERSION}" XCODE_ATTRIBUTE_MARKETING_VERSION "${CMAKE_PROJECT_VERSION}"
XCODE_GENERATE_SCHEME TRUE XCODE_GENERATE_SCHEME TRUE
MACOSX_BUNDLE_ICON_FILE "AppIcon"
) )
target_include_directories(${PROJECT} PRIVATE ${CMAKE_SOURCE_DIR}) target_include_directories(${PROJECT} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_compile_options(${PROJECT} PRIVATE target_compile_options(${PROJECT} PRIVATE
-DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\" -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\"
@ -450,20 +383,20 @@ if(IOS)
target_sources(${PROJECT} PRIVATE target_sources(${PROJECT} PRIVATE
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/Shared/Keychain.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/Shared/Keychain.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/IPAddressRange.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/IPAddressRange.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/InterfaceConfiguration.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/InterfaceConfiguration.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/Shared/Model/NETunnelProviderProtocol+Extension.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/Shared/Model/NETunnelProviderProtocol+Extension.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/TunnelConfiguration.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/TunnelConfiguration.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/Endpoint.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/Endpoint.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/Shared/Model/String+ArrayConversion.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/Shared/Model/String+ArrayConversion.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/PeerConfiguration.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/PeerConfiguration.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/DNSServer.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/DNSServer.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardApp/LocalizationHelper.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/WireGuardApp/LocalizationHelper.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/Shared/FileManager+Extension.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/Shared/FileManager+Extension.swift
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKitC/x25519.c ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/WireGuardKitC/x25519.c
${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/PrivateKey.swift ${CMAKE_CURRENT_LIST_DIR}/3rd/wireguard-apple/Sources/WireGuardKit/PrivateKey.swift
) )
target_sources(${PROJECT} PRIVATE target_sources(${PROJECT} PRIVATE
@ -472,29 +405,33 @@ if(IOS)
) )
target_sources(${PROJECT} PRIVATE target_sources(${PROJECT} PRIVATE
${CMAKE_SOURCE_DIR}/ios/app/launch.png ${CMAKE_CURRENT_LIST_DIR}/ios/app/launch.png
${CMAKE_SOURCE_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard ${CMAKE_CURRENT_LIST_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard
) )
set_source_files_properties( set_source_files_properties(
${CMAKE_SOURCE_DIR}/ios/app/launch.png ${CMAKE_CURRENT_LIST_DIR}/ios/app/launch.png
${CMAKE_SOURCE_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard ${CMAKE_CURRENT_LIST_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard
PROPERTIES MACOSX_PACKAGE_LOCATION "Resources" PROPERTIES MACOSX_PACKAGE_LOCATION "Resources"
) )
target_sources(${PROJECT} PRIVATE ${CMAKE_SOURCE_DIR}/ios/Media.xcassets) target_sources(${PROJECT} PRIVATE
set_source_files_properties(Media.xcassets PROPERTIES ${CMAKE_CURRENT_LIST_DIR}/ios/Media.xcassets
MACOSX_PACKAGE_LOCATION Resources
) )
set_source_files_properties(
${CMAKE_CURRENT_LIST_DIR}/ios/Media.xcassets
PROPERTIES MACOSX_PACKAGE_LOCATION "Resources"
)
add_subdirectory(ios/networkextension) add_subdirectory(ios/networkextension)
add_dependencies(${PROJECT} networkextension) add_dependencies(${PROJECT} networkextension)
set_target_properties(${PROJECT} PROPERTIES XCODE_EMBED_APP_EXTENSIONS networkextension) set_target_properties(${PROJECT} PROPERTIES XCODE_EMBED_APP_EXTENSIONS networkextension)
set_property(TARGET "networkextension" PROPERTY XCODE_EMBED_FRAMEWORKS set_property(TARGET ${PROJECT} PROPERTY XCODE_EMBED_FRAMEWORKS
"${CMAKE_CURRENT_LIST_DIR}/3rd/OpenVPNAdapter/build/Release-iphoneos/OpenVPNAdapter.framework" "${CMAKE_CURRENT_LIST_DIR}/3rd/OpenVPNAdapter/build/Release-iphoneos/OpenVPNAdapter.framework"
) )
set_target_properties(networkextension PROPERTIES XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON) set_target_properties(${PROJECT} PROPERTIES XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON)
set_target_properties(networkextension PROPERTIES XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION) set_target_properties(${PROJECT} PROPERTIES XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION)
endif() endif()
if(ANDROID) if(ANDROID)
@ -509,9 +446,19 @@ if(ANDROID)
${CMAKE_CURRENT_LIST_DIR}/android/gradlew.bat ${CMAKE_CURRENT_LIST_DIR}/android/gradlew.bat
${CMAKE_CURRENT_LIST_DIR}/android/gradle.properties ${CMAKE_CURRENT_LIST_DIR}/android/gradle.properties
${CMAKE_CURRENT_LIST_DIR}/android/res/values/libs.xml ${CMAKE_CURRENT_LIST_DIR}/android/res/values/libs.xml
${CMAKE_CURRENT_LIST_DIR}/android/res/xml/fileprovider.xml
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/AuthHelper.java
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/IPCContract.kt
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/NotificationUtil.kt
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/OpenVPNThreadv3.kt ${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/OpenVPNThreadv3.kt
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/Prefs.kt
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/VpnLogger.kt
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/VpnService.kt ${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/VpnService.kt
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/VpnServiceBinder.kt ${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/VpnServiceBinder.kt
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/AmneziaApp.kt
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/PackageManagerHelper.java
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNActivity.kt
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNApplication.java
${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt ${CMAKE_CURRENT_LIST_DIR}/android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
) )
@ -563,6 +510,7 @@ elseif(APPLE AND NOT IOS)
set(DEPLOY_ARTIFACT_PATH "macos") set(DEPLOY_ARTIFACT_PATH "macos")
endif() endif()
if(NOT IOS)
add_custom_command( add_custom_command(
TARGET ${PROJECT} POST_BUILD TARGET ${PROJECT} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E $<IF:$<CONFIG:Debug>,copy_directory,true> COMMAND ${CMAKE_COMMAND} -E $<IF:$<CONFIG:Debug>,copy_directory,true>
@ -570,3 +518,4 @@ add_custom_command(
$<TARGET_FILE_DIR:${PROJECT}> $<TARGET_FILE_DIR:${PROJECT}>
COMMAND_EXPAND_LISTS COMMAND_EXPAND_LISTS
) )
endif()

View file

@ -1,5 +1,10 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<manifest package="org.amnezia.vpn" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:installLocation="auto"> <manifest
package="org.amnezia.vpn"
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionName="-- %%INSERT_VERSION_NAME%% --"
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
@ -18,12 +23,72 @@
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<application android:name=".qt.AmneziaApp" android:hardwareAccelerated="true" android:label="-- %%INSERT_APP_NAME%% --" android:extractNativeLibs="true" android:icon="@drawable/icon"> <application
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name=".qt.VPNActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleInstance" android:taskAffinity="" android:theme="@style/splashScreenTheme"> android:name=".qt.AmneziaApp"
android:hardwareAccelerated="true"
android:label="-- %%INSERT_APP_NAME%% --"
android:extractNativeLibs="true"
android:icon="@drawable/icon">
<activity
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:name=".qt.VPNActivity"
android:label="-- %%INSERT_APP_NAME%% --"
android:screenOrientation="unspecified"
android:launchMode="singleInstance"
android:taskAffinity=""
android:theme="@style/splashScreenTheme">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
<intent-filter android:label="AmneziaVPN">
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file"/>
<data android:scheme="content"/>
<data android:mimeType= "*/*"/>
<data android:host="*"/>
<data android:pathPattern=".*\\.vpn"/>
<data android:pathPattern=".*\\..*\\.vpn"/>
<data android:pathPattern=".*\\..*\\..*\\.vpn"/>
<data android:pathPattern=".*\\..*\\..*\\..*\\.vpn"/>
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.vpn"/>
</intent-filter>
<intent-filter android:label="AmneziaVPN">
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file"/>
<data android:scheme="content"/>
<data android:mimeType= "*/*"/>
<data android:host="*"/>
<data android:pathPattern=".*\\.cfg"/>
<data android:pathPattern=".*\\..*\\.cfg"/>
<data android:pathPattern=".*\\..*\\..*\\.cfg"/>
<data android:pathPattern=".*\\..*\\..*\\..*\\.cfg"/>
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.cfg"/>
</intent-filter>
<intent-filter android:label="AmneziaVPN">
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file"/>
<data android:scheme="content"/>
<data android:mimeType= "*/*"/>
<data android:host="*"/>
<data android:pathPattern=".*\\.conf"/>
<data android:pathPattern=".*\\..*\\.conf"/>
<data android:pathPattern=".*\\..*\\..*\\.conf"/>
<data android:pathPattern=".*\\..*\\..*\\..*\\.conf"/>
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.conf"/>
</intent-filter>
<!-- Application arguments --> <!-- Application arguments -->
<!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ --> <!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ -->
<!-- Application arguments --> <!-- Application arguments -->
@ -79,10 +144,17 @@
<!-- extract android style --> <!-- extract android style -->
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splashscreen"/> <meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splashscreen"/>
</activity> </activity>
<service android:name=".VPNService" android:permission="android.permission.BIND_VPN_SERVICE" android:process=":QtOnlyProcess">
<service
android:name=".VPNService"
android:permission="android.permission.BIND_VPN_SERVICE"
android:process=":QtOnlyProcess"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.net.VpnService"/> <action android:name="android.net.VpnService"/>
</intent-filter> </intent-filter>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/> <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/> <meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/> <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
@ -95,10 +167,24 @@
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/> <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/> <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
</service> </service>
<service android:name="org.amnezia.vpn.qt.VPNPermissionHelper" android:permission="android.permission.BIND_VPN_SERVICE">
<service
android:name=".qt.VPNPermissionHelper"
android:permission="android.permission.BIND_VPN_SERVICE"
android:exported="true">
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/> <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
</service> </service>
<!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices --> <!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="org.amnezia.vpn.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/fileprovider"/>
</provider>
</application> </application>
</manifest> </manifest>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path name="cache" path="/" />
</paths>

View file

@ -0,0 +1,5 @@
package org.amnezia.vpn
const val IMPORT_COMMAND_CODE = 1
const val IMPORT_ACTION_CODE = "import_action"
const val IMPORT_CONFIG_KEY = "CONFIG_DATA_KEY"

View file

@ -15,6 +15,8 @@ import android.os.*
import android.system.ErrnoException import android.system.ErrnoException
import android.system.Os import android.system.Os
import android.system.OsConstants import android.system.OsConstants
import android.text.TextUtils
import androidx.core.content.FileProvider
import com.wireguard.android.util.SharedLibraryLoader import com.wireguard.android.util.SharedLibraryLoader
import com.wireguard.config.* import com.wireguard.config.*
import com.wireguard.crypto.Key import com.wireguard.crypto.Key
@ -151,6 +153,31 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
private var flags = 0 private var flags = 0
private var startId = 0 private var startId = 0
private lateinit var mMessenger: Messenger
internal class ExternalConfigImportHandler(
context: Context,
private val serviceBinder: VPNServiceBinder,
private val applicationContext: Context = context.applicationContext
) : Handler() {
override fun handleMessage(msg: Message) {
when (msg.what) {
IMPORT_COMMAND_CODE -> {
val data = msg.data.getString(IMPORT_CONFIG_KEY)
if (data != null) {
serviceBinder.importConfig(data)
}
}
else -> {
super.handleMessage(msg)
}
}
}
}
fun init() { fun init() {
if (mAlreadyInitialised) { if (mAlreadyInitialised) {
return return
@ -188,6 +215,14 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
*/ */
override fun onBind(intent: Intent): IBinder { override fun onBind(intent: Intent): IBinder {
Log.v(tag, "Aman: onBind....................") Log.v(tag, "Aman: onBind....................")
if (intent.action != null && intent.action == IMPORT_ACTION_CODE) {
Log.v(tag, "Service bind for import of config")
mMessenger = Messenger(ExternalConfigImportHandler(this, mBinder))
return mMessenger.binder
}
Log.v(tag, "Regular service bind")
when (mProtocol) { when (mProtocol) {
"shadowsocks" -> { "shadowsocks" -> {
when (intent.action) { when (intent.action) {
@ -840,4 +875,44 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
override fun close() = Os.close(fd) override fun close() = Os.close(fd)
} }
fun saveAsFile(configContent: String?, suggestedFileName: String): String {
val rootDirPath = cacheDir.absolutePath
val rootDir = File(rootDirPath)
if (!rootDir.exists()) {
rootDir.mkdirs()
}
val fileName = if (!TextUtils.isEmpty(suggestedFileName)) suggestedFileName else "amnezia.cfg"
val file = File(rootDir, fileName)
try {
file.bufferedWriter().use { out -> out.write(configContent) }
return file.toString()
} catch (e: Exception) {
e.printStackTrace()
}
return ""
}
fun shareFile(attachmentFile: String?) {
try {
val intent = Intent(Intent.ACTION_SEND)
intent.type = "text/*"
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val file = File(attachmentFile)
val uri = FileProvider.getUriForFile(this, "${BuildConfig.APPLICATION_ID}.fileprovider", file)
intent.putExtra(Intent.EXTRA_STREAM, uri)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val createChooser = Intent.createChooser(intent, "Config sharing")
createChooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(createChooser)
} catch (e: Exception) {
Log.i(tag, e.message.toString())
}
}
} }

View file

@ -17,6 +17,7 @@ class VPNServiceBinder(service: VPNService) : Binder() {
private val tag = "VPNServiceBinder" private val tag = "VPNServiceBinder"
private var mListener: IBinder? = null private var mListener: IBinder? = null
private var mResumeConfig: JSONObject? = null private var mResumeConfig: JSONObject? = null
private var mImportedConfig: String? = null
/** /**
* The codes this Binder does accept in [onTransact] * The codes this Binder does accept in [onTransact]
@ -31,6 +32,7 @@ class VPNServiceBinder(service: VPNService) : Binder() {
const val resumeActivate = 7 const val resumeActivate = 7
const val setNotificationText = 8 const val setNotificationText = 8
const val setFallBackNotification = 9 const val setFallBackNotification = 9
const val shareConfig = 10
} }
/** /**
@ -70,101 +72,148 @@ class VPNServiceBinder(service: VPNService) : Binder() {
return true return true
} }
ACTIONS.resumeActivate -> { ACTIONS.resumeActivate -> {
// [data] is empty // [data] is empty
// Activate the current tunnel // Activate the current tunnel
try {
mResumeConfig?.let { this.mService.turnOn(it) }
} catch (e: Exception) {
Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}")
}
return true
}
ACTIONS.deactivate -> {
// [data] here is empty
this.mService.turnOff()
return true
}
ACTIONS.registerEventListener -> {
// [data] contains the Binder that we need to dispatch the Events
val binder = data.readStrongBinder()
mListener = binder
val obj = JSONObject()
obj.put("connected", mService.isUp)
obj.put("time", mService.connectionTime)
dispatchEvent(EVENTS.init, obj.toString())
return true
}
ACTIONS.requestStatistic -> {
dispatchEvent(EVENTS.statisticUpdate, mService.status.toString())
return true
}
ACTIONS.requestGetLog -> {
// Grabs all the Logs and dispatch new Log Event
dispatchEvent(EVENTS.backendLogs, Log.getContent())
return true
}
ACTIONS.requestCleanupLog -> {
Log.clearFile()
return true
}
ACTIONS.setNotificationText -> {
NotificationUtil.update(data)
return true
}
ACTIONS.setFallBackNotification -> {
NotificationUtil.saveFallBackMessage(data, mService)
return true
}
IBinder.LAST_CALL_TRANSACTION -> {
Log.e(tag, "The OS Requested to shut down the VPN")
this.mService.turnOff()
return true
}
else -> {
Log.e(tag, "Received invalid bind request \t Code -> $code")
// If we're hitting this there is probably something wrong in the client.
return false
}
}
return false
}
/**
* Dispatches an Event to all registered Binders
* [code] the Event that happened - see [EVENTS]
* To register an Eventhandler use [onTransact] with
* [ACTIONS.registerEventListener]
*/
fun dispatchEvent(code: Int, payload: String?) {
try { try {
mListener?.let { mResumeConfig?.let { this.mService.turnOn(it) }
if (it.isBinderAlive) { } catch (e: Exception) {
val data = Parcel.obtain() Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}")
data.writeByteArray(payload?.toByteArray(charset("UTF-8")))
it.transact(code, data, Parcel.obtain(), 0)
}
}
} catch (e: DeadObjectException) {
// If the QT Process is killed (not just inactive)
// we cant access isBinderAlive, so nothing to do here.
} }
return true
} }
/** ACTIONS.deactivate -> {
* The codes we Are Using in case of [dispatchEvent] // [data] here is empty
*/ this.mService.turnOff()
object EVENTS { return true
const val init = 0 }
const val connected = 1
const val disconnected = 2 ACTIONS.registerEventListener -> {
const val statisticUpdate = 3 // [data] contains the Binder that we need to dispatch the Events
const val backendLogs = 4 val binder = data.readStrongBinder()
const val activationError = 5 mListener = binder
val obj = JSONObject()
obj.put("connected", mService.isUp)
obj.put("time", mService.connectionTime)
dispatchEvent(EVENTS.init, obj.toString())
////
if (mImportedConfig != null) {
Log.i(tag, "register: config not null")
dispatchEvent(EVENTS.configImport, mImportedConfig)
mImportedConfig = null
} else {
Log.i(tag, "register: config is null")
}
return true
}
ACTIONS.requestStatistic -> {
dispatchEvent(EVENTS.statisticUpdate, mService.status.toString())
return true
}
ACTIONS.requestGetLog -> {
// Grabs all the Logs and dispatch new Log Event
dispatchEvent(EVENTS.backendLogs, Log.getContent())
return true
}
ACTIONS.requestCleanupLog -> {
Log.clearFile()
return true
}
ACTIONS.setNotificationText -> {
NotificationUtil.update(data)
return true
}
ACTIONS.setFallBackNotification -> {
NotificationUtil.saveFallBackMessage(data, mService)
return true
}
ACTIONS.shareConfig -> {
val byteArray = data.createByteArray()
val json = byteArray?.let { String(it) }
val config = JSONObject(json)
val configContent = config.getString("data")
val suggestedName = config.getString("suggestedName")
val filePath = mService.saveAsFile(configContent, suggestedName)
Log.i(tag, "save file: $filePath")
mService.shareFile(filePath)
return true
}
IBinder.LAST_CALL_TRANSACTION -> {
Log.e(tag, "The OS Requested to shut down the VPN")
this.mService.turnOff()
return true
}
else -> {
Log.e(tag, "Received invalid bind request \t Code -> $code")
// If we're hitting this there is probably something wrong in the client.
return false
} }
} }
return false
}
/**
* Dispatches an Event to all registered Binders
* [code] the Event that happened - see [EVENTS]
* To register an Eventhandler use [onTransact] with
* [ACTIONS.registerEventListener]
*/
fun dispatchEvent(code: Int, payload: String?) {
try {
mListener?.let {
if (it.isBinderAlive) {
val data = Parcel.obtain()
data.writeByteArray(payload?.toByteArray(charset("UTF-8")))
it.transact(code, data, Parcel.obtain(), 0)
}
}
} catch (e: DeadObjectException) {
// If the QT Process is killed (not just inactive)
// we cant access isBinderAlive, so nothing to do here.
}
}
/**
* The codes we Are Using in case of [dispatchEvent]
*/
object EVENTS {
const val init = 0
const val connected = 1
const val disconnected = 2
const val statisticUpdate = 3
const val backendLogs = 4
const val activationError = 5
const val configImport = 6
}
fun importConfig(config: String) {
val obj = JSONObject()
obj.put("config", config)
val resultString = obj.toString()
Log.i(tag, "Transact import config request")
if (mListener != null) {
Log.i(tag, "binder alive")
dispatchEvent(EVENTS.configImport, resultString)
} else {
Log.i(tag, "binder NOT alive")
mImportedConfig = resultString
}
}
}

View file

@ -1,37 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.amnezia.vpn.qt;
import android.view.KeyEvent;
public class VPNActivity extends org.qtproject.qt5.android.bindings.QtActivity {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
onBackPressed();
return true;
}
return super.onKeyDown(keyCode, event);
}
// TODO finalize
// https://github.com/mozilla-mobile/mozilla-vpn-client/blob/6acff5dd9f072380a04c3fa12e9f3c98dbdd7a26/src/platforms/android/androidvpnactivity.h
@Override
public void onBackPressed() {
// super.onBackPressed();
try {
if (!handleBackButton()) {
// Move the activity into paused state if back button was pressed
moveTaskToBack(true);
// finish();
}
} catch (Exception e) {
}
}
// Returns true if MVPN has handled the back button
native boolean handleBackButton();
}

View file

@ -0,0 +1,196 @@
package org.amnezia.vpn.qt;
import android.Manifest
import android.content.ComponentName
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.net.Uri
import android.os.*
import android.provider.MediaStore
import android.util.Log
import android.view.KeyEvent
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import org.amnezia.vpn.VPNService
import org.amnezia.vpn.VPNServiceBinder
import org.amnezia.vpn.IMPORT_COMMAND_CODE
import org.amnezia.vpn.IMPORT_ACTION_CODE
import org.amnezia.vpn.IMPORT_CONFIG_KEY
import org.qtproject.qt5.android.bindings.QtActivity
import java.io.*
class VPNActivity : org.qtproject.qt5.android.bindings.QtActivity() {
private var configString: String? = null
private var vpnServiceBinder: Messenger? = null
private var isBound = false
private val TAG = "VPNActivity"
private val STORAGE_PERMISSION_CODE = 42
override fun onCreate(savedInstanceState: Bundle?) {
val newIntent = intent
val newIntentAction = newIntent.action
if (newIntent != null && newIntentAction != null) {
configString = processIntent(newIntent, newIntentAction)
}
super.onCreate(savedInstanceState)
}
override fun onNewIntent(newIntent: Intent) {
intent = newIntent
val newIntentAction = newIntent.action
if (newIntent != null && newIntentAction != null && newIntentAction != Intent.ACTION_MAIN) {
if (isReadStorageAllowed()) {
configString = processIntent(newIntent, newIntentAction)
} else {
requestStoragePermission()
}
}
super.onNewIntent(intent)
}
override fun onResume() {
super.onResume()
if (configString != null && !isBound) {
bindVpnService()
}
}
override fun onPause() {
if (vpnServiceBinder != null && isBound) {
unbindService(connection)
isBound = false
}
super.onPause()
}
private fun isReadStorageAllowed(): Boolean {
val permissionStatus = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
return permissionStatus == PackageManager.PERMISSION_GRANTED
}
private fun requestStoragePermission() {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), STORAGE_PERMISSION_CODE)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String?>, grantResults: IntArray) {
if (requestCode == STORAGE_PERMISSION_CODE) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Storage read permission granted")
if (configString != null) {
bindVpnService()
}
} else {
Toast.makeText(this, "Oops you just denied the permission", Toast.LENGTH_LONG).show()
}
}
}
private fun bindVpnService() {
try {
val intent = Intent(this, VPNService::class.java)
intent.action = IMPORT_ACTION_CODE
bindService(intent, connection, Context.BIND_AUTO_CREATE)
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun processIntent(intent: Intent, action: String): String? {
val scheme = intent.scheme
if (scheme == null) {
return null
}
if (action.compareTo(Intent.ACTION_VIEW) == 0) {
val resolver = contentResolver
if (scheme.compareTo(ContentResolver.SCHEME_CONTENT) == 0) {
val uri = intent.data
val name: String? = getContentName(resolver, uri)
Log.d(TAG, "Content intent detected: " + action + " : " + intent.dataString + " : " + intent.type + " : " + name)
val input = resolver.openInputStream(uri!!)
return input?.bufferedReader()?.use(BufferedReader::readText)
} else if (scheme.compareTo(ContentResolver.SCHEME_FILE) == 0) {
val uri = intent.data
val name = uri!!.lastPathSegment
Log.d(TAG, "File intent detected: " + action + " : " + intent.dataString + " : " + intent.type + " : " + name)
val input = resolver.openInputStream(uri)
return input?.bufferedReader()?.use(BufferedReader::readText)
}
}
return null
}
private fun getContentName(resolver: ContentResolver?, uri: Uri?): String? {
val cursor = resolver!!.query(uri!!, null, null, null, null)
cursor.use {
cursor!!.moveToFirst()
val nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)
return if (nameIndex >= 0) {
return cursor.getString(nameIndex)
} else {
null
}
}
}
private var connection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, binder: IBinder) {
vpnServiceBinder = Messenger(binder)
if (configString != null) {
val msg: Message = Message.obtain(null, IMPORT_COMMAND_CODE, 0, 0)
val bundle = Bundle()
bundle.putString(IMPORT_CONFIG_KEY, configString!!)
msg.data = bundle
try {
vpnServiceBinder?.send(msg)
} catch (e: RemoteException) {
e.printStackTrace()
}
configString = null
}
isBound = true
}
override fun onServiceDisconnected(className: ComponentName) {
vpnServiceBinder = null
isBound = false
}
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && event.repeatCount == 0) {
onBackPressed()
return true
}
return super.onKeyDown(keyCode, event)
}
}

View file

@ -159,8 +159,8 @@ TRANSLATIONS = \
win32 { win32 {
DEFINES += MVPN_WINDOWS DEFINES += MVPN_WINDOWS
OTHER_FILES += platform_win/vpnclient.rc OTHER_FILES += platforms/windows/amneziavpn.rc
RC_FILE = platform_win/vpnclient.rc RC_FILE = platforms/windows/amneziavpn.rc
HEADERS += \ HEADERS += \
protocols/ikev2_vpn_protocol_windows.h \ protocols/ikev2_vpn_protocol_windows.h \
@ -284,9 +284,19 @@ android {
android/gradlew.bat \ android/gradlew.bat \
android/gradle.properties \ android/gradle.properties \
android/res/values/libs.xml \ android/res/values/libs.xml \
android/res/xml/fileprovider.xml \
android/src/org/amnezia/vpn/AuthHelper.java \
android/src/org/amnezia/vpn/IPCContract.kt \
android/src/org/amnezia/vpn/NotificationUtil.kt \
android/src/org/amnezia/vpn/OpenVPNThreadv3.kt \ android/src/org/amnezia/vpn/OpenVPNThreadv3.kt \
android/src/org/amnezia/vpn/Prefs.kt \
android/src/org/amnezia/vpn/VpnLogger.kt \
android/src/org/amnezia/vpn/VpnService.kt \ android/src/org/amnezia/vpn/VpnService.kt \
android/src/org/amnezia/vpn/VpnServiceBinder.kt \ android/src/org/amnezia/vpn/VpnServiceBinder.kt \
android/src/org/amnezia/vpn/qt/AmneziaApp.kt \
android/src/org/amnezia/vpn/qt/PackageManagerHelper.java \
android/src/org/amnezia/vpn/qt/VPNActivity.kt \
android/src/org/amnezia/vpn/qt/VPNApplication.java \
android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
@ -322,6 +332,7 @@ ios {
LIBS += -framework Foundation LIBS += -framework Foundation
LIBS += -framework StoreKit LIBS += -framework StoreKit
LIBS += -framework UserNotifications LIBS += -framework UserNotifications
LIBS += -framework AVFoundation
DEFINES += MVPN_IOS DEFINES += MVPN_IOS

View file

@ -0,0 +1,81 @@
set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
include(${CLIENT_ROOT_DIR}/3rd/QtSsh/src/ssh/qssh.cmake)
include(${CLIENT_ROOT_DIR}/3rd/QtSsh/src/botan/botan.cmake)
if(NOT IOS AND NOT ANDROID)
include(${CLIENT_ROOT_DIR}/3rd/SingleApplication/singleapplication.cmake)
endif()
add_subdirectory(${CLIENT_ROOT_DIR}/3rd/SortFilterProxyModel)
set(LIBS ${LIBS} SortFilterProxyModel)
include(${CLIENT_ROOT_DIR}/3rd/qrcodegen/qrcodegen.cmake)
include(${CLIENT_ROOT_DIR}/3rd/QSimpleCrypto/QSimpleCrypto.cmake)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
add_subdirectory(${CLIENT_ROOT_DIR}/3rd/zlib)
if(WIN32)
set(ZLIB_LIBRARY $<IF:$<CONFIG:Debug>,zlibd,zlib>)
else()
set(ZLIB_LIBRARY z)
endif()
set(ZLIB_INCLUDE_DIR "${CLIENT_ROOT_DIR}/3rd/zlib" "${CMAKE_CURRENT_BINARY_DIR}/3rd/zlib")
link_directories(${CMAKE_CURRENT_BINARY_DIR}/3rd/zlib)
link_libraries(${ZLIB_LIBRARY})
if(NOT LINUX)
set(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/3rd/OpenSSL")
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include")
set(OPENSSL_LIBRARIES_DIR "${OPENSSL_ROOT_DIR}/lib")
set(OPENSSL_LIBRARIES "ssl" "crypto")
set(OPENSSL_PATH "${CLIENT_ROOT_DIR}/3rd/OpenSSL")
if(WIN32)
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_PATH}/lib/windows/x86_64/libssl.lib")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_PATH}/lib/windows/x86_64/libcrypto.lib")
else()
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_PATH}/lib/windows/x86/libssl.lib")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_PATH}/lib/windows/x86/libcrypto.lib")
endif()
elseif(APPLE AND NOT IOS)
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_PATH}/lib/macos/x86_64/libssl.a")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_PATH}/lib/macos/x86_64/libcrypto.a")
elseif(IOS)
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_LIBRARIES_DIR}/libcrypto.a")
set(OPENSSL_SSL_LIBRARY "${OPENSSL_LIBRARIES_DIR}/libssl.a")
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_PATH}/lib/ios/iphone/libssl.a")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_PATH}/lib/ios/iphone/libcrypto.a")
endif()
file(COPY ${OPENSSL_LIB_SSL_PATH} ${OPENSSL_LIB_CRYPTO_PATH}
DESTINATION ${OPENSSL_LIBRARIES_DIR})
file(COPY "${OPENSSL_PATH}/include"
DESTINATION ${OPENSSL_ROOT_DIR})
endif()
set(OPENSSL_USE_STATIC_LIBS TRUE)
find_package(OpenSSL REQUIRED)
set(LIBS ${LIBS}
OpenSSL::Crypto
OpenSSL::SSL
)
set(WITH_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(${CLIENT_ROOT_DIR}/3rd/libssh)
add_compile_definitions(_WINSOCKAPI_)
set(LIBS ${LIBS} ssh)
set(BUILD_WITH_QT6 ON)
add_subdirectory(${CLIENT_ROOT_DIR}/3rd/qtkeychain)
set(LIBS ${LIBS} qt6keychain)
include_directories(
${CLIENT_ROOT_DIR}/3rd/QSimpleCrypto/include
${CLIENT_ROOT_DIR}/3rd/OpenSSL/include
${CLIENT_ROOT_DIR}/3rd/libssh/include
${CLIENT_ROOT_DIR}/3rd/qtkeychain
${CMAKE_CURRENT_BINARY_DIR}/3rd/qtkeychain
${CMAKE_CURRENT_BINARY_DIR}/3rd/libssh/include
)

View file

@ -2,6 +2,8 @@ if(NOT APPLE)
message(FATAL_ERROR "OSX Tools are only supported on Apple targets") message(FATAL_ERROR "OSX Tools are only supported on Apple targets")
endif() endif()
set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
if(CMAKE_COLOR_MAKEFILE) if(CMAKE_COLOR_MAKEFILE)
set(COMMENT_ECHO_COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --blue --bold) set(COMMENT_ECHO_COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --blue --bold)
else() else()
@ -80,7 +82,7 @@ function(osx_bundle_assetcatalog TARGET)
add_custom_command(TARGET ${TARGET} POST_BUILD add_custom_command(TARGET ${TARGET} POST_BUILD
COMMENT "Bundling asset catalog" COMMENT "Bundling asset catalog"
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/xcassets $<TARGET_BUNDLE_CONTENT_DIR:${TARGET}>/${XCASSETS_RESOURCE_DIR} COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/xcassets $<TARGET_BUNDLE_CONTENT_DIR:${TARGET}>/${XCASSETS_RESOURCE_DIR}
COMMAND ${CMAKE_SOURCE_DIR}/scripts/macos/merge_plist.py ${XCASSETS_GEN_PLIST} -o $<TARGET_BUNDLE_CONTENT_DIR:${TARGET}>/Info.plist COMMAND ${CLIENT_ROOT_DIR}/scripts/macos/merge_plist.py ${XCASSETS_GEN_PLIST} -o $<TARGET_BUNDLE_CONTENT_DIR:${TARGET}>/Info.plist
) )
target_sources(${TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/xcassets/Assets.car) target_sources(${TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/xcassets/Assets.car)
@ -125,7 +127,7 @@ function(osx_codesign_target TARGET)
get_target_property(CODESIGN_ENTITLEMENTS ${TARGET} XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS) get_target_property(CODESIGN_ENTITLEMENTS ${TARGET} XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS)
if(CODESIGN_ENTITLEMENTS) if(CODESIGN_ENTITLEMENTS)
add_custom_command(TARGET ${TARGET} POST_BUILD add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_SOURCE_DIR}/scripts/utils/make_template.py ${CODESIGN_ENTITLEMENTS} COMMAND ${CLIENT_ROOT_DIR}/scripts/utils/make_template.py ${CODESIGN_ENTITLEMENTS}
-k PRODUCT_BUNDLE_IDENTIFIER=$<TARGET_PROPERTY:${TARGET},XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER> -k PRODUCT_BUNDLE_IDENTIFIER=$<TARGET_PROPERTY:${TARGET},XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER>
-k DEVELOPMENT_TEAM=$<TARGET_PROPERTY:${TARGET},XCODE_ATTRIBUTE_DEVELOPMENT_TEAM> -k DEVELOPMENT_TEAM=$<TARGET_PROPERTY:${TARGET},XCODE_ATTRIBUTE_DEVELOPMENT_TEAM>
-o ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_codesign.entitlements -o ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_codesign.entitlements

View file

@ -107,21 +107,5 @@ constexpr const char* PLATFORM_NAME =
constexpr const char* PLACEHOLDER_USER_DNS = "127.0.0.1"; constexpr const char* PLACEHOLDER_USER_DNS = "127.0.0.1";
#if defined(MVPN_ADJUST) };
// These are the two auto-generated token from the Adjust dashboard for the
// "Subscription Completed" event. We have two since in the Adjust dashboard we
// have defined two apps for iOS and Android with a event token each.
constexpr const char* ADJUST_SUBSCRIPTION_COMPLETED =
# if defined(MVPN_IOS)
"jl72xm"
# elif defined(MVPN_ANDROID)
"o1mn9m"
# else
""
# endif
;
#endif
}; // namespace Constants
#endif // CONSTANTS_H #endif // CONSTANTS_H

View file

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>AmneziaVPN-service</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/AmneziaVPN.app/Contents/MacOS/AmneziaVPN-service</string>
</array>
<key>KeepAlive</key>
<true/>
<key>Sockets</key>
<dict>
<key>Listeners</key>
<dict>
<key>SockServiceName</key>
<string>5959</string>
<key>SockType</key>
<string>stream</string>
<key>SockFamily</key>
<string>IPv4</string>
</dict>
</dict>
</dict>
</plist>

Binary file not shown.

Binary file not shown.

View file

@ -1,35 +0,0 @@
#!/bin/bash
APP_NAME=AmneziaVPN
PLIST_NAME=$APP_NAME.plist
LAUNCH_DAEMONS_PLIST_NAME=/Library/LaunchDaemons/$PLIST_NAME
LOG_FOLDER=/var/log/$APP_NAME
LOG_FILE="$LOG_FOLDER/post-install.log"
APP_PATH=/Applications/$APP_NAME.app
if launchctl list "$APP_NAME-service" &> /dev/null; then
launchctl unload $LAUNCH_DAEMONS_PLIST_NAME
rm -f $LAUNCH_DAEMONS_PLIST_NAME
fi
tar xzf $APP_PATH/$APP_NAME.tar.gz -C $APP_PATH
rm -f $APP_PATH/$APP_NAME.tar.gz
sudo chmod -R a-w $APP_PATH/
sudo chown -R root $APP_PATH/
sudo chgrp -R wheel $APP_PATH/
rm -rf $LOG_FOLDER
mkdir -p $LOG_FOLDER
echo "`date` Script started" > $LOG_FILE
killall -9 $APP_NAME-service 2>> $LOG_FILE
mv -f $APP_PATH/$PLIST_NAME $LAUNCH_DAEMONS_PLIST_NAME 2>> $LOG_FILE
chown root:wheel $LAUNCH_DAEMONS_PLIST_NAME
launchctl load $LAUNCH_DAEMONS_PLIST_NAME
echo "`date` Service status: $?" >> $LOG_FILE
echo "`date` Script finished" >> $LOG_FILE
#rm -- "$0"

View file

@ -1,14 +0,0 @@
#!/bin/bash
APP_NAME=AmneziaVPN
PLIST_NAME=$APP_NAME.plist
LAUNCH_DAEMONS_PLIST_NAME=/Library/LaunchDaemons/$PLIST_NAME
if launchctl list "$APP_NAME-service" &> /dev/null; then
launchctl unload $LAUNCH_DAEMONS_PLIST_NAME
rm -f $LAUNCH_DAEMONS_PLIST_NAME
fi
rm -rf "$HOME/Library/Application Support/$APP_NAME"
rm -rf /var/log/$APP_NAME
rm -rf /Applications/$APP_NAME.app/Contents

Binary file not shown.

Binary file not shown.

View file

@ -1,74 +0,0 @@
#!/bin/bash
# Mac name-resolution updater based on @cl's script here:
# https://blog.netnerds.net/2011/10/openvpn-update-client-dns-on-mac-os-x-using-from-the-command-line/
# Openvpn envar parsing taken from the script in debian's openvpn package.
# Smushed together and improved by @andrewgdotcom.
# Parses DHCP options from openvpn to update resolv.conf
# To use set as 'up' and 'down' script in your openvpn *.conf:
# up /etc/openvpn/update-resolv-conf
# down /etc/openvpn/update-resolv-conf
[ "$script_type" ] || exit 0
[ "$dev" ] || exit 0
PATH=$PATH:/usr/sbin/
NMSRVRS=()
SRCHS=()
# Get adapter list
IFS=$'\n' read -d '' -ra adapters < <(networksetup -listallnetworkservices |grep -v denotes) || true
split_into_parts()
{
part1="$1"
part2="$2"
part3="$3"
}
update_all_dns()
{
for adapter in "${adapters[@]}"
do
echo updating dns for $adapter
# set dns server to the vpn dns server
if [[ "${SRCHS[@]}" ]]; then
networksetup -setsearchdomains "$adapter" "${SRCHS[@]}"
fi
if [[ "${NMSRVRS[@]}" ]]; then
networksetup -setdnsservers "$adapter" "${NMSRVRS[@]}"
fi
done
}
clear_all_dns()
{
for adapter in "${adapters[@]}"
do
echo updating dns for $adapter
networksetup -setdnsservers "$adapter" empty
networksetup -setsearchdomains "$adapter" empty
done
}
case "$script_type" in
up)
for optionvarname in ${!foreign_option_*} ; do
option="${!optionvarname}"
echo "$option"
split_into_parts $option
if [ "$part1" = "dhcp-option" ] ; then
if [ "$part2" = "DNS" ] ; then
NMSRVRS=(${NMSRVRS[@]} $part3)
elif [ "$part2" = "DOMAIN" ] ; then
SRCHS=(${SRCHS[@]} $part3)
fi
fi
done
update_all_dns
;;
down)
clear_all_dns
;;
esac

View file

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="fastlane.lanes">
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000215">
</testcase>
<testcase classname="fastlane.lanes" name="1: Switch to certificates lane" time="0.000162">
</testcase>
<testcase classname="fastlane.lanes" name="2: match" time="2.707099">
</testcase>
<testcase classname="fastlane.lanes" name="3: notification" time="0.226435">
</testcase>
<testcase classname="fastlane.lanes" name="4: clean_build_artifacts" time="0.000648">
</testcase>
<testcase classname="fastlane.lanes" name="5: build_app" time="259.546685">
</testcase>
<testcase classname="fastlane.lanes" name="6: testflight" time="84.84052">
</testcase>
<testcase classname="fastlane.lanes" name="7: get_version_number" time="0.114899">
</testcase>
<testcase classname="fastlane.lanes" name="8: get_build_number" time="1.332216">
</testcase>
<testcase classname="fastlane.lanes" name="9: increment_build_number" time="2.325473">
</testcase>
</testsuite>
</testsuites>

View file

@ -38,13 +38,15 @@
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string> <string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2</string> <string>7</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key> <key>LSSupportsOpeningDocumentsInPlace</key>
<false/> <true/>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>Amnezia VPN needs access to the camera for reading QR-codes.</string> <string>Amnezia VPN needs access to the camera for reading QR-codes.</string>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>

View file

@ -51,6 +51,10 @@
<true/> <true/>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>Amnezia VPN needs access to the camera for reading QR-codes.</string> <string>Amnezia VPN needs access to the camera for reading QR-codes.</string>
<key>CFBundleIcons</key>
<dict/>
<key>CFBundleIcons~ipad</key>
<dict/>
<key>UTImportedTypeDeclarations</key> <key>UTImportedTypeDeclarations</key>
<array> <array>
<dict> <dict>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 634 KiB

Before After
Before After

View file

@ -1,5 +1,7 @@
enable_language(Swift) enable_language(Swift)
set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
add_executable(networkextension) add_executable(networkextension)
set_target_properties(networkextension PROPERTIES set_target_properties(networkextension PROPERTIES
OUTPUT_NAME "AmneziaVPNNetworkExtension" OUTPUT_NAME "AmneziaVPNNetworkExtension"
@ -35,7 +37,7 @@ target_link_libraries(networkextension PRIVATE ${FW_UI_KIT})
target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\") target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1) target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1)
set(WG_APPLE_SOURCE_DIR ${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources) set(WG_APPLE_SOURCE_DIR ${CLIENT_ROOT_DIR}/3rd/wireguard-apple/Sources)
target_sources(networkextension PRIVATE target_sources(networkextension PRIVATE
${WG_APPLE_SOURCE_DIR}/WireGuardKit/WireGuardAdapter.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/WireGuardAdapter.swift
@ -57,15 +59,15 @@ target_sources(networkextension PRIVATE
${WG_APPLE_SOURCE_DIR}/WireGuardKit/Array+ConcurrentMap.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/Array+ConcurrentMap.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddress+AddrInfo.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddress+AddrInfo.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/PrivateKey.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/PrivateKey.swift
${CMAKE_SOURCE_DIR}/platforms/ios/iostunnel.swift ${CLIENT_ROOT_DIR}/platforms/ios/iostunnel.swift
${CMAKE_SOURCE_DIR}/platforms/ios/iosglue.mm ${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
${CMAKE_SOURCE_DIR}/platforms/ios/ioslogger.swift ${CLIENT_ROOT_DIR}/platforms/ios/ioslogger.swift
) )
## Build wireguard-go-version.h ## Build wireguard-go-version.h
execute_process( execute_process(
COMMAND go list -m golang.zx2c4.com/wireguard COMMAND go list -m golang.zx2c4.com/wireguard
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKitGo WORKING_DIRECTORY ${CLIENT_ROOT_DIR}/3rd/wireguard-apple/Sources/WireGuardKitGo
OUTPUT_VARIABLE WG_VERSION_FULL OUTPUT_VARIABLE WG_VERSION_FULL
) )
string(REGEX REPLACE ".*v\([0-9.]*\).*" "\\1" WG_VERSION_STRING 1.1.1) string(REGEX REPLACE ".*v\([0-9.]*\).*" "\\1" WG_VERSION_STRING 1.1.1)
@ -74,7 +76,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/wireguard-go-version.h.in
target_sources(networkextension PRIVATE target_sources(networkextension PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/wireguard-go-version.h) ${CMAKE_CURRENT_BINARY_DIR}/wireguard-go-version.h)
target_include_directories(networkextension PRIVATE ${CMAKE_SOURCE_DIR}) target_include_directories(networkextension PRIVATE ${CLIENT_ROOT_DIR})
target_include_directories(networkextension PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(networkextension PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
## HACK: Build only the first architecture, this will break universal builds ## HACK: Build only the first architecture, this will break universal builds
@ -90,13 +92,13 @@ endif()
## TODO: The upstream makefile also makes an attempt to patch the golang runtime ## TODO: The upstream makefile also makes an attempt to patch the golang runtime
## to provide the boot-time clock instead of an uptime clock. We should probably ## to provide the boot-time clock instead of an uptime clock. We should probably
## make an attempt to do the same, somehow? ## make an attempt to do the same, somehow?
include(${CMAKE_SOURCE_DIR}/src/cmake/golang.cmake) include(${CLIENT_ROOT_DIR}/cmake/golang.cmake)
if(OSXARCH STREQUAL "x86_64") if(OSXARCH STREQUAL "x86_64")
set(GOARCH amd64) set(GOARCH amd64)
else() else()
set(GOARCH ${FIRST_OSX_ARCHITECTURE}) set(GOARCH ${FIRST_OSX_ARCHITECTURE})
endif() endif()
add_go_library(libwg-go ${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKitGo/api-apple.go add_go_library(libwg-go ${CLIENT_ROOT_DIR}/3rd/wireguard-apple/Sources/WireGuardKitGo/api-apple.go
GOOS ios GOOS ios
GOARCH ${GOARCH} GOARCH ${GOARCH}
CGO_CFLAGS -arch ${OSXARCH} CGO_CFLAGS -arch ${OSXARCH}

View file

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string> <string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>

View file

@ -19,19 +19,21 @@
#include "android_controller.h" #include "android_controller.h"
#include "core/errorstrings.h" #include "core/errorstrings.h"
#include "ui/pages_logic/StartPageLogic.h"
// Binder Codes for VPNServiceBinder // Binder Codes for VPNServiceBinder
// See also - VPNServiceBinder.kt // See also - VPNServiceBinder.kt
// Actions that are Requestable // Actions that are Requestable
const int ACTION_ACTIVATE = 1; const int ACTION_ACTIVATE = 1;
const int ACTION_DEACTIVATE = 2; const int ACTION_DEACTIVATE = 2;
const int ACTION_REGISTERLISTENER = 3; const int ACTION_REGISTER_LISTENER = 3;
const int ACTION_REQUEST_STATISTIC = 4; const int ACTION_REQUEST_STATISTIC = 4;
const int ACTION_REQUEST_GET_LOG = 5; const int ACTION_REQUEST_GET_LOG = 5;
const int ACTION_REQUEST_CLEANUP_LOG = 6; const int ACTION_REQUEST_CLEANUP_LOG = 6;
const int ACTION_RESUME_ACTIVATE = 7; const int ACTION_RESUME_ACTIVATE = 7;
const int ACTION_SET_NOTIFICATION_TEXT = 8; const int ACTION_SET_NOTIFICATION_TEXT = 8;
const int ACTION_SET_NOTIFICATION_FALLBACK = 9; const int ACTION_SET_NOTIFICATION_FALLBACK = 9;
const int ACTION_SHARE_CONFIG = 10;
// Event Types that will be Dispatched after registration // Event Types that will be Dispatched after registration
const int EVENT_INIT = 0; const int EVENT_INIT = 0;
@ -40,6 +42,7 @@ const int EVENT_DISCONNECTED = 2;
const int EVENT_STATISTIC_UPDATE = 3; const int EVENT_STATISTIC_UPDATE = 3;
const int EVENT_BACKEND_LOGS = 4; const int EVENT_BACKEND_LOGS = 4;
const int EVENT_ACTIVATION_ERROR = 5; const int EVENT_ACTIVATION_ERROR = 5;
const int EVENT_CONFIG_IMPORT = 6;
namespace { namespace {
AndroidController* s_instance = nullptr; AndroidController* s_instance = nullptr;
@ -60,10 +63,12 @@ AndroidController* AndroidController::instance() {
return s_instance; return s_instance;
} }
bool AndroidController::initialize() bool AndroidController::initialize(StartPageLogic *startPageLogic)
{ {
qDebug() << "Initializing"; qDebug() << "Initializing";
m_startPageLogic = startPageLogic;
// Hook in the native implementation for startActivityForResult into the JNI // Hook in the native implementation for startActivityForResult into the JNI
JNINativeMethod methods[]{{"startActivityForResult", JNINativeMethod methods[]{{"startActivityForResult",
"(Landroid/content/Intent;)V", "(Landroid/content/Intent;)V",
@ -151,6 +156,16 @@ void AndroidController::setNotificationText(const QString& title,
m_serviceBinder.transact(ACTION_SET_NOTIFICATION_TEXT, data, nullptr); m_serviceBinder.transact(ACTION_SET_NOTIFICATION_TEXT, data, nullptr);
} }
void AndroidController::shareConfig(const QString& configContent, const QString& suggestedName) {
QJsonObject rootObject;
rootObject["data"] = configContent;
rootObject["suggestedName"] = suggestedName;
QJsonDocument doc(rootObject);
QAndroidParcel parcel;
parcel.writeData(doc.toJson());
m_serviceBinder.transact(ACTION_SHARE_CONFIG, parcel, nullptr);
}
/* /*
* Sets fallback Notification text that should be shown in case the VPN * Sets fallback Notification text that should be shown in case the VPN
* switches into the Connected state without the app open * switches into the Connected state without the app open
@ -190,6 +205,10 @@ void AndroidController::cleanupBackendLogs() {
m_serviceBinder.transact(ACTION_REQUEST_CLEANUP_LOG, nullParcel, nullptr); m_serviceBinder.transact(ACTION_REQUEST_CLEANUP_LOG, nullParcel, nullptr);
} }
void AndroidController::importConfig(const QString& data){
m_startPageLogic->importConnectionFromCode(data);
}
void AndroidController::onServiceConnected( void AndroidController::onServiceConnected(
const QString& name, const QAndroidBinder& serviceBinder) { const QString& name, const QAndroidBinder& serviceBinder) {
qDebug() << "Server " + name + " connected"; qDebug() << "Server " + name + " connected";
@ -201,7 +220,7 @@ void AndroidController::onServiceConnected(
// Send the Service our Binder to recive incoming Events // Send the Service our Binder to recive incoming Events
QAndroidParcel binderParcel; QAndroidParcel binderParcel;
binderParcel.writeBinder(m_binder); binderParcel.writeBinder(m_binder);
m_serviceBinder.transact(ACTION_REGISTERLISTENER, binderParcel, nullptr); m_serviceBinder.transact(ACTION_REGISTER_LISTENER, binderParcel, nullptr);
} }
void AndroidController::onServiceDisconnected(const QString& name) { void AndroidController::onServiceDisconnected(const QString& name) {
@ -282,7 +301,14 @@ bool AndroidController::VPNBinder::onTransact(int code,
case EVENT_ACTIVATION_ERROR: case EVENT_ACTIVATION_ERROR:
qDebug() << "Transact: error"; qDebug() << "Transact: error";
emit m_controller->connectionStateChanged(VpnProtocol::Error); emit m_controller->connectionStateChanged(VpnProtocol::Error);
break;
case EVENT_CONFIG_IMPORT:
qDebug() << "Transact: config import";
doc = QJsonDocument::fromJson(data.readData());
buffer = doc.object()["config"].toString();
qDebug() << "Transact: config string" << buffer;
m_controller->importConfig(buffer);
break;
default: default:
qWarning() << "Transact: Invalid!"; qWarning() << "Transact: Invalid!";
break; break;

View file

@ -5,11 +5,13 @@
//#include <QAndroidServiceConnection> //#include <QAndroidServiceConnection>
#include <QtCore/private/qandroidextras_p.h> #include <QtCore/private/qandroidextras_p.h>
#include "ui/uilogic.h"
#include "ui/pages_logic/StartPageLogic.h"
#include "protocols/vpnprotocol.h" #include "protocols/vpnprotocol.h"
using namespace amnezia; using namespace amnezia;
class AndroidController : public QObject, public QAndroidServiceConnection class AndroidController : public QObject, public QAndroidServiceConnection
{ {
Q_OBJECT Q_OBJECT
@ -20,7 +22,7 @@ public:
virtual ~AndroidController() override = default; virtual ~AndroidController() override = default;
bool initialize(); bool initialize(StartPageLogic *startPageLogic);
ErrorCode start(); ErrorCode start();
void stop(); void stop();
@ -28,9 +30,11 @@ public:
void checkStatus(); void checkStatus();
void setNotificationText(const QString& title, const QString& message, int timerSec); void setNotificationText(const QString& title, const QString& message, int timerSec);
void shareConfig(const QString& data, const QString& suggestedName);
void setFallbackConnectedNotification(); void setFallbackConnectedNotification();
void getBackendLogs(std::function<void(const QString&)>&& callback); void getBackendLogs(std::function<void(const QString&)>&& callback);
void cleanupBackendLogs(); void cleanupBackendLogs();
void importConfig(const QString& data);
// from QAndroidServiceConnection // from QAndroidServiceConnection
void onServiceConnected(const QString& name, const QAndroidBinder& serviceBinder) override; void onServiceConnected(const QString& name, const QAndroidBinder& serviceBinder) override;
@ -59,6 +63,8 @@ private:
//Protocol m_protocol; //Protocol m_protocol;
QJsonObject m_vpnConfig; QJsonObject m_vpnConfig;
StartPageLogic *m_startPageLogic;
bool m_serviceConnected = false; bool m_serviceConnected = false;
std::function<void(const QString&)> m_logCallback; std::function<void(const QString&)> m_logCallback;

View file

@ -2,7 +2,9 @@
#include <QFile> #include <QFile>
@implementation QtAppDelegate @implementation QtAppDelegate {
UIView *_screen;
}
+(QtAppDelegate *)sharedQtAppDelegate { +(QtAppDelegate *)sharedQtAppDelegate {
static dispatch_once_t pred; static dispatch_once_t pred;
@ -26,6 +28,13 @@
{ {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
_screen = [UIScreen.mainScreen snapshotViewAfterScreenUpdates: false];
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle: UIBlurEffectStyleDark];
UIVisualEffectView *blurBackround = [[UIVisualEffectView alloc] initWithEffect: blurEffect];
[_screen addSubview: blurBackround];
blurBackround.frame = _screen.frame;
UIWindow *_window = UIApplication.sharedApplication.keyWindow;
[_window addSubview: _screen];
} }
- (void)applicationDidEnterBackground:(UIApplication *)application - (void)applicationDidEnterBackground:(UIApplication *)application
@ -44,6 +53,7 @@
- (void)applicationDidBecomeActive:(UIApplication *)application - (void)applicationDidBecomeActive:(UIApplication *)application
{ {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
[_screen removeFromSuperview];
} }
- (void)applicationWillTerminate:(UIApplication *)application - (void)applicationWillTerminate:(UIApplication *)application

View file

@ -388,7 +388,7 @@ public class IOSVpnProtocolImpl : NSObject {
proto.providerBundleIdentifier = vpnBundleID proto.providerBundleIdentifier = vpnBundleID
tunnel!.protocolConfiguration = proto tunnel!.protocolConfiguration = proto
tunnel!.localizedDescription = vpnName tunnel!.localizedDescription = "Amnezia Wireguard"
tunnel!.isEnabled = true tunnel!.isEnabled = true
tunnel!.saveToPreferences { [unowned self] saveError in tunnel!.saveToPreferences { [unowned self] saveError in
@ -527,8 +527,9 @@ public class IOSVpnProtocolImpl : NSObject {
@objc func checkStatus(callback: @escaping (String, String, String) -> Void) { @objc func checkStatus(callback: @escaping (String, String, String) -> Void) {
Logger.global?.log(message: "Check status") Logger.global?.log(message: "Check status")
// assert(tunnel != nil) // assert(tunnel != nil)
print("check status")
let protoType = (tunnel!.localizedDescription ?? "").toTunnelType let protoType = (tunnel!.localizedDescription ?? "").toTunnelType
print(protoType);
switch protoType { switch protoType {
case .wireguard: case .wireguard:
@ -559,7 +560,7 @@ public class IOSVpnProtocolImpl : NSObject {
print("server IP: \(serverIpv4Gateway)") print("server IP: \(serverIpv4Gateway)")
let deviceIpv4Address = getTunIPAddress() let deviceIpv4Address = getWiFiAddress()
print("device IP: \(serverIpv4Gateway)") print("device IP: \(serverIpv4Gateway)")
if deviceIpv4Address == nil { if deviceIpv4Address == nil {
callback("", "", "") callback("", "", "")
@ -610,8 +611,9 @@ public class IOSVpnProtocolImpl : NSObject {
print("server IP: \(serverIpv4Gateway)") print("server IP: \(serverIpv4Gateway)")
let deviceIpv4Address = getTunIPAddress()
print("device IP: \(serverIpv4Gateway)") let deviceIpv4Address = getWiFiAddress()
print("device IP: \(deviceIpv4Address)")
if deviceIpv4Address == nil { if deviceIpv4Address == nil {
callback("", "", "") callback("", "", "")
return return
@ -690,38 +692,45 @@ public class IOSVpnProtocolImpl : NSObject {
} }
} }
private func getTunIPAddress() -> String? { func getWiFiAddress() -> String? {
var address: String? = nil var address : String?
var interfaces: UnsafeMutablePointer<ifaddrs>? = nil
var temp_addr: UnsafeMutablePointer<ifaddrs>? = nil
var success: Int = 0
// retrieve the current interfaces - returns 0 on success // Get list of all interfaces on the local machine:
success = Int(getifaddrs(&interfaces)) var ifaddr : UnsafeMutablePointer<ifaddrs>?
if success == 0 { guard getifaddrs(&ifaddr) == 0 else { return nil }
// Loop through linked list of interfaces guard let firstAddr = ifaddr else { return nil }
temp_addr = interfaces
while temp_addr != nil { // For each interface ...
if temp_addr?.pointee.ifa_addr == nil { for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
continue let interface = ifptr.pointee
// Check for IPv4 or IPv6 interface:
let addrFamily = interface.ifa_addr.pointee.sa_family
//if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) { // **ipv6 committed
if addrFamily == UInt8(AF_INET){
// Check interface name:
let name = String(cString: interface.ifa_name)
if name == "en0" {
// Convert interface address to a human readable string:
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
&hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST)
address = String(cString: hostname)
} }
if temp_addr?.pointee.ifa_addr.pointee.sa_family == UInt8(AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if let name = temp_addr?.pointee.ifa_name, ((String(utf8String: name)?.contains("tun")) != nil) {
// Get NSString from C String
if let value = temp_addr?.pointee.ifa_addr as? sockaddr_in {
address = String(utf8String: inet_ntoa(value.sin_addr))
}
}
}
temp_addr = temp_addr?.pointee.ifa_next
} }
} }
freeifaddrs(interfaces) freeifaddrs(ifaddr)
return address return address
} }
} }
enum TunnelType: String { enum TunnelType: String {
case wireguard, openvpn, shadowsocks, empty case wireguard, openvpn, shadowsocks, empty
} }
@ -729,9 +738,9 @@ enum TunnelType: String {
extension String { extension String {
var toTunnelType: TunnelType { var toTunnelType: TunnelType {
switch self { switch self {
case "wireguard": return .wireguard case "Amnezia Wireguard": return .wireguard
case "openvpn": return .openvpn case "Amnezia OpenVPN": return .openvpn
case "shadowsocks": return .shadowsocks case "Amnezia ShadowSocks": return .shadowsocks
default: default:
return .empty return .empty
} }

View file

@ -1,7 +1,7 @@
#include <windows.h> #include <windows.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
IDI_ICON1 ICON "../images/app.ico" IDI_ICON1 ICON "../../images/app.ico"
#define VER_FILEVERSION 2,0,0,0 #define VER_FILEVERSION 2,0,0,0
#define VER_FILEVERSION_STR "2.0.0.0\0" #define VER_FILEVERSION_STR "2.0.0.0\0"

View file

@ -10,13 +10,11 @@ fi
RELEASE=1 RELEASE=1
OS= OS=
NETWORKEXTENSION= NETWORKEXTENSION=
ADJUST_SDK_TOKEN=
ADJUST="CONFIG-=adjust"
WORKINGDIR=`pwd` WORKINGDIR=`pwd`
helpFunction() { helpFunction() {
print G "Usage:" print G "Usage:"
print N "\t$0 <macos|ios|> [-d|--debug] [-n|--networkextension] [-a|--adjusttoken <adjust_token>]" print N "\t$0 <macos|ios|> [-d|--debug] [-n|--networkextension]"
print N "" print N ""
print N "By default, the project is compiled in release mode. Use -d or --debug for a debug build." print N "By default, the project is compiled in release mode. Use -d or --debug for a debug build."
print N "Use -n or --networkextension to force the network-extension component for MacOS too." print N "Use -n or --networkextension to force the network-extension component for MacOS too."
@ -26,7 +24,6 @@ helpFunction() {
print G "Config variables:" print G "Config variables:"
print N "\tQT_MACOS_BIN=</path/of/the/qt/bin/folder/for/macos>" print N "\tQT_MACOS_BIN=</path/of/the/qt/bin/folder/for/macos>"
print N "\tQT_IOS_BIN=</path/of/the/qt/bin/folder/for/ios>" print N "\tQT_IOS_BIN=</path/of/the/qt/bin/folder/for/ios>"
print N "\tMVPN_IOS_ADJUST_TOKEN=<token>"
print N "" print N ""
exit 0 exit 0
} }
@ -38,11 +35,6 @@ while [[ $# -gt 0 ]]; do
key="$1" key="$1"
case $key in case $key in
-a | --adjusttoken)
ADJUST_SDK_TOKEN="$2"
shift
shift
;;
-d | --debug) -d | --debug)
RELEASE= RELEASE=
shift shift
@ -97,11 +89,6 @@ if [[ "$OS" != "macos" ]] && [[ "$OS" != "ios" ]] && [[ "$OS" != "macostest" ]];
helpFunction helpFunction
fi fi
if ! [[ "$ADJUST_SDK_TOKEN" ]] && [[ "$MVPN_IOS_ADJUST_TOKEN" ]]; then
print Y "Using the MVPN_IOS_ADJUST_TOKEN value for the adjust token"
ADJUST_SDK_TOKEN=$MVPN_IOS_ADJUST_TOKEN
fi
if [[ "$OS" == "ios" ]]; then if [[ "$OS" == "ios" ]]; then
# Network-extension is the default for IOS # Network-extension is the default for IOS
NETWORKEXTENSION=1 NETWORKEXTENSION=1
@ -150,7 +137,6 @@ MACOS_FLAGS="
QTPLUGIN+=qsvg QTPLUGIN+=qsvg
CONFIG-=static CONFIG-=static
CONFIG+=balrog CONFIG+=balrog
MVPN_MACOS=1
" "
MACOSTEST_FLAGS=" MACOSTEST_FLAGS="
@ -160,7 +146,6 @@ MACOSTEST_FLAGS="
" "
IOS_FLAGS=" IOS_FLAGS="
MVPN_IOS=1
Q_OS_IOS=1 Q_OS_IOS=1
" "
@ -183,11 +168,6 @@ elif [ "$OS" = "macostest" ]; then
PLATFORM=$MACOSTEST_FLAGS PLATFORM=$MACOSTEST_FLAGS
elif [ "$OS" = "ios" ]; then elif [ "$OS" = "ios" ]; then
PLATFORM=$IOS_FLAGS PLATFORM=$IOS_FLAGS
if [[ "$ADJUST_SDK_TOKEN" ]]; then
printn Y "ADJUST_SDK_TOKEN: "
print G "$ADJUST_SDK_TOKEN"
ADJUST="CONFIG+=adjust"
fi
else else
killProcess "Why are we here?" killProcess "Why are we here?"
fi fi
@ -249,7 +229,7 @@ else
print Y "No Tun2Socks will be built" print Y "No Tun2Socks will be built"
fi fi
print Y "Creating the xcode project via qmake..." print Y "Creating the Xcode project via qmake..."
$QMAKE \ $QMAKE \
VERSION=$SHORTVERSION \ VERSION=$SHORTVERSION \
BUILD_ID=$FULLVERSION \ BUILD_ID=$FULLVERSION \
@ -258,11 +238,10 @@ $QMAKE \
$VPNMODE \ $VPNMODE \
$WEMODE \ $WEMODE \
$PLATFORM \ $PLATFORM \
$ADJUST \
./client.pro || killProcess "Compilation failed" ./client.pro || killProcess "Compilation failed"
print Y "Patching the xcode project..." print Y "Patching the xcode project..."
ruby scripts/xcode_patcher.rb "AmneziaVPN.xcodeproj" "$SHORTVERSION" "$FULLVERSION" "$OSRUBY" "$NETWORKEXTENSION" "$ADJUST_SDK_TOKEN" || killProcess "Failed to merge xcode with wireguard" ruby scripts/xcode_patcher.rb "AmneziaVPN.xcodeproj" "$SHORTVERSION" "$FULLVERSION" "$OSRUBY" "$NETWORKEXTENSION" || killProcess "Failed to merge xcode with wireguard"
print G "done." print G "done."
if command -v "sed" &>/dev/null; then if command -v "sed" &>/dev/null; then
@ -270,6 +249,6 @@ print G "done."
sed -i '' '/<string>Original<\/string>/d' AmneziaVPN.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings sed -i '' '/<string>Original<\/string>/d' AmneziaVPN.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
fi fi
print Y "Opening in XCode..."
open AmneziaVPN.xcodeproj
print G "All done!" print G "All done!"
print Y "Opening project in Xcode..."
open AmneziaVPN.xcodeproj

View file

@ -9,7 +9,7 @@ class XCodeprojPatcher
attr :target_main attr :target_main
attr :target_extension attr :target_extension
def run(file, shortVersion, fullVersion, platform, networkExtension, configHash, adjust_sdk_token) def run(file, shortVersion, fullVersion, platform, networkExtension, configHash)
open_project file open_project file
setup_project setup_project
open_target_main open_target_main
@ -19,13 +19,7 @@ class XCodeprojPatcher
group = @project.main_group.new_group('Configuration') group = @project.main_group.new_group('Configuration')
@configFile = group.new_file('xcode.xconfig') @configFile = group.new_file('xcode.xconfig')
setup_target_main shortVersion, fullVersion, platform, networkExtension, configHash, adjust_sdk_token setup_target_main shortVersion, fullVersion, platform, networkExtension, configHash
# if platform == 'macos'
# setup_target_loginitem shortVersion, fullVersion, configHash
# setup_target_nativemessaging shortVersion, fullVersion, configHash
# end
if networkExtension if networkExtension
setup_target_extension shortVersion, fullVersion, platform, configHash setup_target_extension shortVersion, fullVersion, platform, configHash
@ -59,7 +53,7 @@ class XCodeprojPatcher
end end
def setup_target_main(shortVersion, fullVersion, platform, networkExtension, configHash, adjust_sdk_token) def setup_target_main(shortVersion, fullVersion, platform, networkExtension, configHash)
@target_main.build_configurations.each do |config| @target_main.build_configurations.each do |config|
config.base_configuration_reference = @configFile config.base_configuration_reference = @configFile
@ -72,10 +66,8 @@ class XCodeprojPatcher
"$(PROJECT_DIR)/3rd", "$(PROJECT_DIR)/3rd",
"$(PROJECT_DIR)/3rd/OpenVPNAdapter/build/Release-iphoneos", "$(PROJECT_DIR)/3rd/OpenVPNAdapter/build/Release-iphoneos",
"$(PROJECT_DIR)/3rd/ShadowSocks/build/Release-iphoneos", "$(PROJECT_DIR)/3rd/ShadowSocks/build/Release-iphoneos",
# "$(PROJECT_DIR)/3rd/PacketProcessor/build/Release-iphoneos",
"$(PROJECT_DIR)/3rd/outline-go-tun2socks/build/ios", "$(PROJECT_DIR)/3rd/outline-go-tun2socks/build/ios",
"${PROJECT_DIR}/3rd/CocoaAsyncSocket/build/Release-iphoneos", "${PROJECT_DIR}/3rd/CocoaAsyncSocket/build/Release-iphoneos",
# "${PROJECT_DIR}/3rd/CocoaLumberjack/build/Release-iphoneos",
] ]
# Versions and names # Versions and names
@ -91,9 +83,6 @@ class XCodeprojPatcher
config.build_settings['INFOPLIST_FILE'] ||= platform + '/app/Info.plist' config.build_settings['INFOPLIST_FILE'] ||= platform + '/app/Info.plist'
if platform == 'ios' if platform == 'ios'
config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'ios/app/main.entitlements' config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'ios/app/main.entitlements'
if adjust_sdk_token != ""
config.build_settings['ADJUST_SDK_TOKEN'] = adjust_sdk_token
end
elsif networkExtension elsif networkExtension
config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'macos/app/app.entitlements' config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'macos/app/app.entitlements'
else else
@ -104,7 +93,7 @@ class XCodeprojPatcher
config.build_settings['ENABLE_BITCODE'] ||= 'NO' if platform == 'ios' config.build_settings['ENABLE_BITCODE'] ||= 'NO' if platform == 'ios'
config.build_settings['SDKROOT'] = 'iphoneos' if platform == 'ios' config.build_settings['SDKROOT'] = 'iphoneos' if platform == 'ios'
config.build_settings['SWIFT_PRECOMPILE_BRIDGING_HEADER'] = 'NO' if platform == 'ios' config.build_settings['SWIFT_PRECOMPILE_BRIDGING_HEADER'] = 'NO' if platform == 'ios'
config.build_settings['PATH'] = '${PATH}:/usr/local/go/bin:/usr/local/bin:/opt/homebrew/bin' config.build_settings['PATH'] = '${PATH}:/opt/local/bin:/usr/local/go/bin:/usr/local/bin:/opt/homebrew/bin'
groupId = ""; groupId = "";
if (platform == 'macos') if (platform == 'macos')
@ -173,96 +162,23 @@ class XCodeprojPatcher
} }
end end
if (platform == 'ios' && adjust_sdk_token != "") if(platform == 'ios')
frameworks_group = @project.groups.find { |group| group.display_name == 'Frameworks' } frameworks_group = @project.groups.find { |group| group.display_name == 'Frameworks' }
frameworks_build_phase = @target_main.build_phases.find { |build_phase| build_phase.to_s == 'FrameworksBuildPhase' } frameworks_build_phase = @target_main.build_phases.find { |build_phase| build_phase.to_s == 'FrameworksBuildPhase' }
framework_ref = frameworks_group.new_file('AdServices.framework') embed_frameworks_build_phase = project.new(Xcodeproj::Project::Object::PBXCopyFilesBuildPhase)
build_file = frameworks_build_phase.add_file_reference(framework_ref) embed_frameworks_build_phase.name = 'Embed Frameworks'
build_file.settings = { 'ATTRIBUTES' => ['Weak'] } embed_frameworks_build_phase.symbol_dst_subfolder_spec = :frameworks
@target_main.build_phases << embed_frameworks_build_phase
framework_ref = frameworks_group.new_file('3rd/OpenVPNAdapter/build/Release-iphoneos/OpenVPNAdapter.framework')
build_file = embed_frameworks_build_phase.add_file_reference(framework_ref)
framework_ref = frameworks_group.new_file('iAd.framework')
frameworks_build_phase.add_file_reference(framework_ref) frameworks_build_phase.add_file_reference(framework_ref)
build_file.settings = { 'ATTRIBUTES' => ['CodeSignOnCopy', 'RemoveHeadersOnCopy'] }
# Adjust SDK
group = @project.main_group.new_group('AdjustSDK')
[
'3rd/adjust-ios-sdk/Adjust/ADJActivityHandler.h',
'3rd/adjust-ios-sdk/Adjust/ADJActivityKind.h',
'3rd/adjust-ios-sdk/Adjust/ADJActivityPackage.h',
'3rd/adjust-ios-sdk/Adjust/ADJActivityState.h',
'3rd/adjust-ios-sdk/Adjust/ADJAdjustFactory.h',
'3rd/adjust-ios-sdk/Adjust/ADJAdRevenue.h',
'3rd/adjust-ios-sdk/Adjust/ADJAttribution.h',
'3rd/adjust-ios-sdk/Adjust/ADJAttributionHandler.h',
'3rd/adjust-ios-sdk/Adjust/ADJBackoffStrategy.h',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSData+ADJAdditions.h',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSNumber+ADJAdditions.h',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSString+ADJAdditions.h',
'3rd/adjust-ios-sdk/Adjust/ADJConfig.h',
'3rd/adjust-ios-sdk/Adjust/ADJEvent.h',
'3rd/adjust-ios-sdk/Adjust/ADJEventFailure.h',
'3rd/adjust-ios-sdk/Adjust/ADJEventSuccess.h',
'3rd/adjust-ios-sdk/Adjust/ADJLinkResolution.h',
'3rd/adjust-ios-sdk/Adjust/ADJLogger.h',
'3rd/adjust-ios-sdk/Adjust/ADJPackageBuilder.h',
'3rd/adjust-ios-sdk/Adjust/ADJPackageHandler.h',
'3rd/adjust-ios-sdk/Adjust/ADJPackageParams.h',
'3rd/adjust-ios-sdk/Adjust/ADJRequestHandler.h',
'3rd/adjust-ios-sdk/Adjust/ADJResponseData.h',
'3rd/adjust-ios-sdk/Adjust/ADJSdkClickHandler.h',
'3rd/adjust-ios-sdk/Adjust/ADJSessionFailure.h',
'3rd/adjust-ios-sdk/Adjust/ADJSessionParameters.h',
'3rd/adjust-ios-sdk/Adjust/ADJSessionSuccess.h',
'3rd/adjust-ios-sdk/Adjust/ADJSubscription.h',
'3rd/adjust-ios-sdk/Adjust/ADJThirdPartySharing.h',
'3rd/adjust-ios-sdk/Adjust/ADJTimerCycle.h',
'3rd/adjust-ios-sdk/Adjust/ADJTimerOnce.h',
'3rd/adjust-ios-sdk/Adjust/ADJUrlStrategy.h',
'3rd/adjust-ios-sdk/Adjust/ADJUserDefaults.h',
'3rd/adjust-ios-sdk/Adjust/Adjust.h',
'3rd/adjust-ios-sdk/Adjust/ADJUtil.h',
'3rd/adjust-ios-sdk/Adjust/ADJActivityHandler.m',
'3rd/adjust-ios-sdk/Adjust/ADJActivityKind.m',
'3rd/adjust-ios-sdk/Adjust/ADJActivityPackage.m',
'3rd/adjust-ios-sdk/Adjust/ADJActivityState.m',
'3rd/adjust-ios-sdk/Adjust/ADJAdjustFactory.m',
'3rd/adjust-ios-sdk/Adjust/ADJAdRevenue.m',
'3rd/adjust-ios-sdk/Adjust/ADJAttribution.m',
'3rd/adjust-ios-sdk/Adjust/ADJAttributionHandler.m',
'3rd/adjust-ios-sdk/Adjust/ADJBackoffStrategy.m',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSData+ADJAdditions.m',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSNumber+ADJAdditions.m',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSString+ADJAdditions.m',
'3rd/adjust-ios-sdk/Adjust/ADJConfig.m',
'3rd/adjust-ios-sdk/Adjust/ADJEvent.m',
'3rd/adjust-ios-sdk/Adjust/ADJEventFailure.m',
'3rd/adjust-ios-sdk/Adjust/ADJEventSuccess.m',
'3rd/adjust-ios-sdk/Adjust/ADJLinkResolution.m',
'3rd/adjust-ios-sdk/Adjust/ADJLogger.m',
'3rd/adjust-ios-sdk/Adjust/ADJPackageBuilder.m',
'3rd/adjust-ios-sdk/Adjust/ADJPackageHandler.m',
'3rd/adjust-ios-sdk/Adjust/ADJPackageParams.m',
'3rd/adjust-ios-sdk/Adjust/ADJRequestHandler.m',
'3rd/adjust-ios-sdk/Adjust/ADJResponseData.m',
'3rd/adjust-ios-sdk/Adjust/ADJSdkClickHandler.m',
'3rd/adjust-ios-sdk/Adjust/ADJSessionFailure.m',
'3rd/adjust-ios-sdk/Adjust/ADJSessionParameters.m',
'3rd/adjust-ios-sdk/Adjust/ADJSessionSuccess.m',
'3rd/adjust-ios-sdk/Adjust/ADJSubscription.m',
'3rd/adjust-ios-sdk/Adjust/ADJThirdPartySharing.m',
'3rd/adjust-ios-sdk/Adjust/ADJTimerCycle.m',
'3rd/adjust-ios-sdk/Adjust/ADJTimerOnce.m',
'3rd/adjust-ios-sdk/Adjust/ADJUrlStrategy.m',
'3rd/adjust-ios-sdk/Adjust/ADJUserDefaults.m',
'3rd/adjust-ios-sdk/Adjust/Adjust.m',
'3rd/adjust-ios-sdk/Adjust/ADJUtil.m',
].each { |filename|
file = group.new_file(filename)
file_reference = @target_main.add_file_references([file], '-fobjc-arc')
}
end end
end end
def setup_target_extension(shortVersion, fullVersion, platform, configHash) def setup_target_extension(shortVersion, fullVersion, platform, configHash)
@ -288,12 +204,9 @@ class XCodeprojPatcher
"$(PROJECT_DIR)/3rd/OpenVPNAdapter/build/Release-iphoneos", "$(PROJECT_DIR)/3rd/OpenVPNAdapter/build/Release-iphoneos",
"$(PROJECT_DIR)/3rd/libleaf/lib", "$(PROJECT_DIR)/3rd/libleaf/lib",
"$(PROJECT_DIR)/3rd/ShadowSocks/build/Release-iphoneos", "$(PROJECT_DIR)/3rd/ShadowSocks/build/Release-iphoneos",
# "$(PROJECT_DIR)/3rd/PacketProcessor/build/Release-iphoneos",
"$(PROJECT_DIR)/3rd/outline-go-tun2socks/build/ios", "$(PROJECT_DIR)/3rd/outline-go-tun2socks/build/ios",
"${PROJECT_DIR}/3rd/CocoaAsyncSocket/build/Release-iphoneos", "${PROJECT_DIR}/3rd/CocoaAsyncSocket/build/Release-iphoneos",
# "${PROJECT_DIR}/3rd/CocoaLumberjack/build/Release-iphoneos",
] ]
# config.build_settings['LIBRARY_SEARCH_PATHS'] = [config.build_settings['LIBRARY_SEARCH_PATHS'], "$(PROJECT_DIR)/3rd/libleaf/lib"]
# Versions and names # Versions and names
config.build_settings['MARKETING_VERSION'] ||= shortVersion config.build_settings['MARKETING_VERSION'] ||= shortVersion
@ -325,7 +238,7 @@ class XCodeprojPatcher
"-framework", "-framework",
"OpenGLES", "OpenGLES",
] ]
config.build_settings['PATH'] = '${PATH}:/usr/local/go/bin' config.build_settings['PATH'] = '${PATH}:/opt/local/bin:/usr/local/go/bin'
end end
groupId = ""; groupId = "";
@ -379,17 +292,7 @@ class XCodeprojPatcher
'platforms/ios/iostunnel.swift', 'platforms/ios/iostunnel.swift',
'platforms/ios/ioslogger.swift', 'platforms/ios/ioslogger.swift',
'platforms/ios/iosinterface.swift', 'platforms/ios/iosinterface.swift',
# 'platforms/ios/ssprovider.swift',
'platforms/ios/iosglue.mm', 'platforms/ios/iosglue.mm',
# 'platforms/ios/ssconnectivity.h',
# 'platforms/ios/ssconnectivity.m',
# 'platforms/ios/iosopenvpn2ssadapter.h',
# 'platforms/ios/iosopenvpn2ssadapter.m',
# 'platforms/ios/sspacket.h',
# 'platforms/ios/sspacket.m',
# 'platforms/ios/ssadapterpacketflow.h',
# 'platforms/ios/tun2ssprovider.swift',
# 'platforms/ios/tun2sockswriter.swift',
].each { |filename| ].each { |filename|
file = group.new_file(filename) file = group.new_file(filename)
@target_extension.add_file_references([file]) @target_extension.add_file_references([file])
@ -403,39 +306,9 @@ class XCodeprojPatcher
framework_ref = frameworks_group.new_file('libwg-go.a') framework_ref = frameworks_group.new_file('libwg-go.a')
frameworks_build_phase.add_file_reference(framework_ref) frameworks_build_phase.add_file_reference(framework_ref)
# framework_ref = frameworks_group.new_file('3rd/libleaf/lib/libleaf.a')
# frameworks_build_phase.add_file_reference(framework_ref)
framework_ref = frameworks_group.new_file('NetworkExtension.framework') framework_ref = frameworks_group.new_file('NetworkExtension.framework')
frameworks_build_phase.add_file_reference(framework_ref) frameworks_build_phase.add_file_reference(framework_ref)
# framework_ref = frameworks_group.new_file('3rd/OpenVPNAdapter/build/Release-iphoneos/LZ4.framework')
# frameworks_build_phase.add_file_reference(framework_ref)
#
# framework_ref = frameworks_group.new_file('3rd/OpenVPNAdapter/build/Release-iphoneos/mbedTLS.framework')
# frameworks_build_phase.add_file_reference(framework_ref)
#
# framework_ref = frameworks_group.new_file('3rd/OpenVPNAdapter/build/Release-iphoneos/OpenVPNClient.framework')
# frameworks_build_phase.add_file_reference(framework_ref)
framework_ref = frameworks_group.new_file('3rd/OpenVPNAdapter/build/Release-iphoneos/OpenVPNAdapter.framework')
frameworks_build_phase.add_file_reference(framework_ref)
# framework_ref = frameworks_group.new_file('3rd/ShadowSocks/build/Release-iphoneos/ShadowSocks.framework')
# frameworks_build_phase.add_file_reference(framework_ref)
#
# framework_ref = frameworks_group.new_file('3rd/CocoaAsyncSocket/build/Release-iphoneos/CocoaAsyncSocket.framework')
# frameworks_build_phase.add_file_reference(framework_ref)
#
# framework_ref = frameworks_group.new_file('3rd/outline-go-tun2socks/build/ios/Tun2socks.xcframework')
# frameworks_build_phase.add_file_reference(framework_ref)
# framework_ref = frameworks_group.new_file('3rd/CocoaLumberjack/build/Release-iphoneos/CocoaLumberjack.framework')
# frameworks_build_phase.add_file_reference(framework_ref)
# This fails: @target_main.add_dependency @target_extension # This fails: @target_main.add_dependency @target_extension
container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy) container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy)
container_proxy.container_portal = @project.root_object.uuid container_proxy.container_portal = @project.root_object.uuid
@ -492,6 +365,7 @@ class XCodeprojPatcher
framework_ref = frameworks_group.new_file('balrog/balrog.a') framework_ref = frameworks_group.new_file('balrog/balrog.a')
frameworks_build_phase.add_file_reference(framework_ref) frameworks_build_phase.add_file_reference(framework_ref)
# This fails: @target_main.add_dependency target_balrog # This fails: @target_main.add_dependency target_balrog
container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy) container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy)
container_proxy.container_portal = @project.root_object.uuid container_proxy.container_portal = @project.root_object.uuid
@ -599,7 +473,7 @@ class XCodeprojPatcher
# other configs # other configs
config.build_settings['INFOPLIST_FILE'] ||= 'macos/loginitem/Info.plist' config.build_settings['INFOPLIST_FILE'] ||= 'macos/loginitem/Info.plist'
config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'macos/loginitem/MozillaVPNLoginItem.entitlements' config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'macos/loginitem/MozillaVPNLoginItem.entitlements' #TODO need to check this
config.build_settings['CODE_SIGN_IDENTITY'] = 'Apple Development' config.build_settings['CODE_SIGN_IDENTITY'] = 'Apple Development'
config.build_settings['SKIP_INSTALL'] = 'YES' config.build_settings['SKIP_INSTALL'] = 'YES'
@ -708,7 +582,7 @@ class XCodeprojPatcher
copy_nativeMessagingManifest.dst_path = 'Contents/Resources/utils' copy_nativeMessagingManifest.dst_path = 'Contents/Resources/utils'
group = @project.main_group.new_group('WireGuardHelper') group = @project.main_group.new_group('WireGuardHelper')
file = group.new_file 'extension/app/manifests/macos/mozillavpn.json' file = group.new_file 'extension/app/manifests/macos/mozillavpn.json' #TODO Need to check this
nativeMessagingManifest_file = copy_nativeMessagingManifest.add_file_reference file nativeMessagingManifest_file = copy_nativeMessagingManifest.add_file_reference file
nativeMessagingManifest_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] } nativeMessagingManifest_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] }
@ -744,8 +618,7 @@ configFile.each { |line|
platform = "macos" platform = "macos"
platform = "ios" if ARGV[3] == "ios" platform = "ios" if ARGV[3] == "ios"
networkExtension = true if ARGV[4] == "1" networkExtension = true if ARGV[4] == "1"
adjust_sdk_token = ARGV[5]
r = XCodeprojPatcher.new r = XCodeprojPatcher.new
r.run ARGV[0], ARGV[1], ARGV[2], platform, networkExtension, config, adjust_sdk_token r.run ARGV[0], ARGV[1], ARGV[2], platform, networkExtension, config
exit 0 exit 0

View file

@ -83,8 +83,8 @@ void AppSettingsLogic::onPushButtonBackupAppConfigClicked()
void AppSettingsLogic::onPushButtonRestoreAppConfigClicked() void AppSettingsLogic::onPushButtonRestoreAppConfigClicked()
{ {
QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open backup"), QString fileName = QFileDialog::getOpenFileName(Q_NULLPTR, tr("Open backup"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.backup"); QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.backup");
if (fileName.isEmpty()) return; if (fileName.isEmpty()) return;

View file

@ -15,6 +15,7 @@ void ServerListLogic::onServerListPushbuttonDefaultClicked(int index)
{ {
m_settings->setDefaultServer(index); m_settings->setDefaultServer(index);
uiLogic()->onUpdateAllPages(); uiLogic()->onUpdateAllPages();
emit currServerIdxChanged();
} }
void ServerListLogic::onServerListPushbuttonSettingsClicked(int index) void ServerListLogic::onServerListPushbuttonSettingsClicked(int index)
@ -23,6 +24,11 @@ void ServerListLogic::onServerListPushbuttonSettingsClicked(int index)
uiLogic()->goToPage(Page::ServerSettings); uiLogic()->goToPage(Page::ServerSettings);
} }
int ServerListLogic::currServerIdx() const
{
return m_settings->defaultServerIndex();
}
void ServerListLogic::onUpdatePage() void ServerListLogic::onUpdatePage()
{ {
const QJsonArray &servers = m_settings->serversArray(); const QJsonArray &servers = m_settings->serversArray();

View file

@ -10,8 +10,11 @@ class ServerListLogic : public PageLogicBase
Q_OBJECT Q_OBJECT
READONLY_PROPERTY(QObject *, serverListModel) READONLY_PROPERTY(QObject *, serverListModel)
Q_PROPERTY(int currServerIdx READ currServerIdx NOTIFY currServerIdxChanged)
public: public:
int currServerIdx() const;
Q_INVOKABLE void onUpdatePage() override; Q_INVOKABLE void onUpdatePage() override;
Q_INVOKABLE void onServerListPushbuttonDefaultClicked(int index); Q_INVOKABLE void onServerListPushbuttonDefaultClicked(int index);
Q_INVOKABLE void onServerListPushbuttonSettingsClicked(int index); Q_INVOKABLE void onServerListPushbuttonSettingsClicked(int index);
@ -20,5 +23,8 @@ public:
explicit ServerListLogic(UiLogic *uiLogic, QObject *parent = nullptr); explicit ServerListLogic(UiLogic *uiLogic, QObject *parent = nullptr);
~ServerListLogic() = default; ~ServerListLogic() = default;
signals:
void currServerIdxChanged();
}; };
#endif // SERVER_LIST_LOGIC_H #endif // SERVER_LIST_LOGIC_H

View file

@ -135,9 +135,8 @@ void StartPageLogic::onPushButtonImport()
void StartPageLogic::onPushButtonImportOpenFile() void StartPageLogic::onPushButtonImportOpenFile()
{ {
QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open profile"), QString fileName = QFileDialog::getOpenFileName(Q_NULLPTR, tr("Open profile"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn"); QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), tr("*.vpn"));
if (fileName.isEmpty()) return; if (fileName.isEmpty()) return;
QFile file(fileName); QFile file(fileName);
@ -166,14 +165,6 @@ bool StartPageLogic::importConnection(const QJsonObject &profile)
return false; return false;
} }
if (!profile.contains(config_key::containers)) {
uiLogic()->selectedServerIndex = m_settings->defaultServerIndex();
uiLogic()->selectedDockerContainer = m_settings->defaultContainer(uiLogic()->selectedServerIndex);
uiLogic()->onUpdateAllPages();
emit uiLogic()->goToPage(Page::ServerContainers);
}
return true; return true;
} }

View file

@ -61,7 +61,17 @@ void ViewConfigLogic::importConfig()
m_settings->addServer(configJson()); m_settings->addServer(configJson());
m_settings->setDefaultServer(m_settings->serversCount() - 1); m_settings->setDefaultServer(m_settings->serversCount() - 1);
emit uiLogic()->goToPage(Page::Vpn);
emit uiLogic()->setStartPage(Page::Vpn); if (!configJson().contains(config_key::containers) || configJson().value(config_key::containers).toArray().isEmpty()) {
uiLogic()->selectedServerIndex = m_settings->defaultServerIndex();
uiLogic()->selectedDockerContainer = m_settings->defaultContainer(uiLogic()->selectedServerIndex);
uiLogic()->onUpdateAllPages();
emit uiLogic()->goToPage(Page::Vpn);
emit uiLogic()->setStartPage(Page::Vpn);
emit uiLogic()->goToPage(Page::ServerContainers);
} else {
emit uiLogic()->goToPage(Page::Vpn);
emit uiLogic()->setStartPage(Page::Vpn);
}
} }

View file

@ -11,8 +11,6 @@ Drawer {
signal containerSelected(int c_index) signal containerSelected(int c_index)
property int selectedIndex: -1 property int selectedIndex: -1
z: -3
y: 0 y: 0
x: 0 x: 0
edge: Qt.RightEdge edge: Qt.RightEdge
@ -117,6 +115,7 @@ Drawer {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
tb.currentIndex = index tb.currentIndex = index
tb_other.currentIndex = -1 tb_other.currentIndex = -1
@ -181,6 +180,7 @@ Drawer {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
tb_other.currentIndex = index tb_other.currentIndex = index
tb.currentIndex = -1 tb.currentIndex = -1

View file

@ -26,7 +26,7 @@ PageBase {
} }
Connections { Connections {
target: Qt.platform.os != "ios" ? QrDecoderLogic : nil target: Qt.platform.os != "ios" ? QrDecoderLogic : null
function onStartDecode() { function onStartDecode() {
console.debug("Starting QR decoder") console.debug("Starting QR decoder")
loader.sourceComponent = component loader.sourceComponent = component
@ -71,7 +71,7 @@ PageBase {
anchors.right: parent.right anchors.right: parent.right
autoOrientation: true autoOrientation: true
fillMode: VideoOutput.PreserveAspectFit fillMode: VideoOutput.PreserveAspectFit
filters: [ zxingFilter ] // filters: [ zxingFilter ]
Rectangle { Rectangle {

View file

@ -40,11 +40,29 @@ PageBase {
id: loader id: loader
anchors.top: caption.bottom anchors.top: caption.bottom
anchors.bottom: parent.bottom anchors.bottom: progressColumn.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
} }
Column{
height: 40
id: progressColumn
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
ProgressBar {
id: progress
anchors.left: parent.left
anchors.right: parent.right
value: QrDecoderLogic.totalChunksCount === 0? 0 : (QrDecoderLogic.receivedChunksCount/QrDecoderLogic.totalChunksCount)
}
Text {
id: chunksCount
text: "Progress: " + QrDecoderLogic.receivedChunksCount +"/"+QrDecoderLogic.totalChunksCount
}
}
Component { Component {
id: component id: component

View file

@ -45,7 +45,7 @@ PageBase {
pageLoader.focus = true pageLoader.focus = true
} }
onContainerSelected: { onContainerSelected: function(c_index) {
var containerProto = ContainerProps.defaultProtocol(c_index) var containerProto = ContainerProps.defaultProtocol(c_index)

View file

@ -42,6 +42,9 @@ PageBase {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: 20 anchors.bottomMargin: 20
model: ServerListLogic.serverListModel model: ServerListLogic.serverListModel
highlightRangeMode: ListView.ApplyRange
highlightMoveVelocity: -1
currentIndex: ServerListLogic.currServerIdx
spacing: 5 spacing: 5
clip: true clip: true
delegate: Item { delegate: Item {
@ -55,10 +58,6 @@ PageBase {
if (GC.isMobile()) { if (GC.isMobile()) {
ServerListLogic.onServerListPushbuttonSettingsClicked(index) ServerListLogic.onServerListPushbuttonSettingsClicked(index)
} }
else {
listWidget_servers.currentIndex = index
}
mouse.accepted = false mouse.accepted = false
} }
onEntered: { onEntered: {

View file

@ -27,7 +27,6 @@ PageProtocolBase {
anchors.top: caption.bottom anchors.top: caption.bottom
anchors.left: root.left anchors.left: root.left
anchors.right: root.right anchors.right: root.right
anchors.bottom: pb_save.top
anchors.margins: 20 anchors.margins: 20
anchors.topMargin: 10 anchors.topMargin: 10

View file

@ -112,7 +112,7 @@ New encryption keys pair will be generated.")
Layout.bottomMargin: 10 Layout.bottomMargin: 10
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 40 Layout.preferredHeight: 40
text: qsTr("Save to file") text: Qt.platform.os === "android" ? qsTr("Share") : qsTr("Save to file")
enabled: tfShareCode.textArea.length > 0 enabled: tfShareCode.textArea.length > 0
visible: tfShareCode.textArea.length > 0 visible: tfShareCode.textArea.length > 0

View file

@ -94,7 +94,7 @@ PageShareProtocolBase {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 40 Layout.preferredHeight: 40
text: qsTr("Save to file") text: Qt.platform.os === "android" ? qsTr("Share") : qsTr("Save to file")
enabled: tfShareCode.textArea.length > 0 enabled: tfShareCode.textArea.length > 0
visible: tfShareCode.textArea.length > 0 visible: tfShareCode.textArea.length > 0

View file

@ -93,7 +93,7 @@ PageShareProtocolBase {
Layout.preferredHeight: 40 Layout.preferredHeight: 40
width: parent.width - 60 width: parent.width - 60
text: qsTr("Save to file") text: Qt.platform.os === "android" ? qsTr("Share") : qsTr("Save to file")
enabled: tfShareCode.textArea.length > 0 enabled: tfShareCode.textArea.length > 0
visible: tfShareCode.textArea.length > 0 visible: tfShareCode.textArea.length > 0

View file

@ -91,7 +91,7 @@ PageShareProtocolBase {
Layout.preferredHeight: 40 Layout.preferredHeight: 40
Layout.fillWidth: true Layout.fillWidth: true
text: qsTr("Save to file") text: Qt.platform.os === "android" ? qsTr("Share") : qsTr("Save to file")
enabled: tfShareCode.textArea.length > 0 enabled: tfShareCode.textArea.length > 0
visible: tfShareCode.textArea.length > 0 visible: tfShareCode.textArea.length > 0

View file

@ -285,7 +285,6 @@ Window {
Drawer { Drawer {
id: drawer_log id: drawer_log
z: -3
y: 0 y: 0
x: 0 x: 0
edge: Qt.BottomEdge edge: Qt.BottomEdge

View file

@ -135,7 +135,7 @@ void UiLogic::initalizeUiLogic()
pageLogic<VpnLogic>()->onConnectionStateChanged(VpnProtocol::Connected); pageLogic<VpnLogic>()->onConnectionStateChanged(VpnProtocol::Connected);
} }
}); });
if (!AndroidController::instance()->initialize()) { if (!AndroidController::instance()->initialize(pageLogic<StartPageLogic>())) {
qCritical() << QString("Init failed") ; qCritical() << QString("Init failed") ;
emit VpnProtocol::Error; emit VpnProtocol::Error;
return; return;
@ -267,8 +267,6 @@ void UiLogic::onGotoCurrentProtocolsPage()
emit goToPage(Page::ServerContainers); emit goToPage(Page::ServerContainers);
} }
//void UiLogic::showEvent(QShowEvent *event) //void UiLogic::showEvent(QShowEvent *event)
//{ //{
//#if defined Q_OS_MACX //#if defined Q_OS_MACX
@ -596,8 +594,9 @@ void UiLogic::saveTextFile(const QString& desc, const QString& suggestedName, QS
if (fileName.isEmpty()) return; if (fileName.isEmpty()) return;
if (!fileName.toString().endsWith(ext)) fileName = QUrl(fileName.toString() + ext); if (!fileName.toString().endsWith(ext)) fileName = QUrl(fileName.toString() + ext);
#elif defined Q_OS_ANDROID #elif defined Q_OS_ANDROID
fileName = QFileDialog::getSaveFileUrl(nullptr, suggestedName, qDebug() << "UiLogic::shareConfig" << data;
QUrl::fromLocalFile(docDir), "*" + ext); AndroidController::instance()->shareConfig(data, suggestedName);
return;
#endif #endif
if (fileName.isEmpty()) return; if (fileName.isEmpty()) return;

View file

@ -1,2 +1,2 @@
# current build 1 # current build 6
!defined(BUILDVERSION, var):BUILDVERSION = 2 !defined(BUILDVERSION, var):BUILDVERSION = 7

View file

@ -1,3 +1,4 @@
#include "qtimer.h"
#include <QApplication> #include <QApplication>
#include <QDebug> #include <QDebug>
#include <QFile> #include <QFile>
@ -34,7 +35,10 @@ VpnConnection::VpnConnection(std::shared_ptr<Settings> settings,
std::shared_ptr<ServerController> serverController, QObject* parent) : QObject(parent), std::shared_ptr<ServerController> serverController, QObject* parent) : QObject(parent),
m_settings(settings), m_settings(settings),
m_configurator(configurator), m_configurator(configurator),
m_serverController(serverController) m_serverController(serverController),
m_receivedBytes(0),
m_sentBytes(0),
m_isIOSConnected(false)
{ {
} }
@ -48,11 +52,16 @@ VpnConnection::~VpnConnection()
void VpnConnection::onBytesChanged(quint64 receivedBytes, quint64 sentBytes) void VpnConnection::onBytesChanged(quint64 receivedBytes, quint64 sentBytes)
{ {
emit bytesChanged(receivedBytes, sentBytes); emit bytesChanged(receivedBytes - m_receivedBytes, sentBytes - m_sentBytes);
m_receivedBytes = receivedBytes;
m_sentBytes = sentBytes;
} }
void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState state) void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState state)
{ {
#ifdef AMNEZIA_DESKTOP #ifdef AMNEZIA_DESKTOP
if (IpcClient::Interface()) { if (IpcClient::Interface()) {
if (state == VpnProtocol::Connected){ if (state == VpnProtocol::Connected){
@ -94,9 +103,33 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState sta
} }
} }
#endif #endif
#ifdef Q_OS_IOS
if (state == VpnProtocol::Connected){
m_isIOSConnected = true;
checkIOSStatus();
}
else {
m_isIOSConnected = false;
m_receivedBytes = 0;
m_sentBytes = 0;
}
#endif
emit connectionStateChanged(state); emit connectionStateChanged(state);
} }
#ifdef Q_OS_IOS
void VpnConnection::checkIOSStatus()
{
QTimer::singleShot(1000, [this]() {
if(m_isIOSConnected){
iosVpnProtocol->checkStatus();
checkIOSStatus();
}
} );
}
#endif
const QString &VpnConnection::remoteAddress() const const QString &VpnConnection::remoteAddress() const
{ {
return m_remoteAddress; return m_remoteAddress;
@ -333,7 +366,10 @@ void VpnConnection::connectToVpn(int serverIndex,
m_vpnProtocol.reset(androidVpnProtocol); m_vpnProtocol.reset(androidVpnProtocol);
#elif defined Q_OS_IOS #elif defined Q_OS_IOS
Proto proto = ContainerProps::defaultProtocol(container); Proto proto = ContainerProps::defaultProtocol(container);
IOSVpnProtocol *iosVpnProtocol = new IOSVpnProtocol(proto, m_vpnConfiguration); //if (iosVpnProtocol==NULL) {
iosVpnProtocol = new IOSVpnProtocol(proto, m_vpnConfiguration);
//}
// IOSVpnProtocol *iosVpnProtocol = new IOSVpnProtocol(proto, m_vpnConfiguration);
if (!iosVpnProtocol->initialize()) { if (!iosVpnProtocol->initialize()) {
qDebug() << QString("Init failed") ; qDebug() << QString("Init failed") ;
emit VpnProtocol::Error; emit VpnProtocol::Error;
@ -384,12 +420,19 @@ void VpnConnection::disconnectFromVpn()
VpnProtocol::VpnConnectionState VpnConnection::connectionState() VpnProtocol::VpnConnectionState VpnConnection::connectionState()
{ {
if (!m_vpnProtocol) return VpnProtocol::Disconnected; if (!m_vpnProtocol) return VpnProtocol::Disconnected;
return m_vpnProtocol->connectionState(); return m_vpnProtocol->connectionState();
} }
bool VpnConnection::isConnected() const bool VpnConnection::isConnected() const
{ {
#ifdef Q_OS_IOS
#endif
if (!m_vpnProtocol.data()) { if (!m_vpnProtocol.data()) {
return false; return false;
} }

View file

@ -10,6 +10,10 @@
#include "core/defs.h" #include "core/defs.h"
#include "settings.h" #include "settings.h"
#ifdef Q_OS_IOS
#include "protocols/ios_vpnprotocol.h"
#endif
#ifdef AMNEZIA_DESKTOP #ifdef AMNEZIA_DESKTOP
#include "core/ipcclient.h" #include "core/ipcclient.h"
#endif #endif
@ -74,6 +78,10 @@ protected slots:
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes); void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
void onConnectionStateChanged(VpnProtocol::VpnConnectionState state); void onConnectionStateChanged(VpnProtocol::VpnConnectionState state);
#ifdef Q_OS_IOS
void checkIOSStatus();
#endif
protected: protected:
QSharedPointer<VpnProtocol> m_vpnProtocol; QSharedPointer<VpnProtocol> m_vpnProtocol;
@ -85,10 +93,16 @@ private:
QJsonObject m_vpnConfiguration; QJsonObject m_vpnConfiguration;
QJsonObject m_routeMode; QJsonObject m_routeMode;
QString m_remoteAddress; QString m_remoteAddress;
quint64 m_receivedBytes;
quint64 m_sentBytes;
bool m_isIOSConnected; //remove later move to isConnected,
#ifdef AMNEZIA_DESKTOP #ifdef AMNEZIA_DESKTOP
IpcClient *m_IpcClient {nullptr}; IpcClient *m_IpcClient {nullptr};
#endif #endif
#ifdef Q_OS_IOS
IOSVpnProtocol * iosVpnProtocol{nullptr};
#endif
}; };
#endif // VPNCONNECTION_H #endif // VPNCONNECTION_H