Merge branch 'qt_migration' into qmake-to-cmake-migration

This commit is contained in:
pokamest 2022-12-13 15:34:38 +01:00
commit 9c188e0acd
41 changed files with 778 additions and 833 deletions

1
.gitignore vendored
View file

@ -125,3 +125,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,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
} }
/** /**
@ -95,6 +97,16 @@ class VPNServiceBinder(service: VPNService) : Binder() {
obj.put("connected", mService.isUp) obj.put("connected", mService.isUp)
obj.put("time", mService.connectionTime) obj.put("time", mService.connectionTime)
dispatchEvent(EVENTS.init, obj.toString()) 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 return true
} }
@ -108,18 +120,36 @@ class VPNServiceBinder(service: VPNService) : Binder() {
dispatchEvent(EVENTS.backendLogs, Log.getContent()) dispatchEvent(EVENTS.backendLogs, Log.getContent())
return true return true
} }
ACTIONS.requestCleanupLog -> { ACTIONS.requestCleanupLog -> {
Log.clearFile() Log.clearFile()
return true return true
} }
ACTIONS.setNotificationText -> { ACTIONS.setNotificationText -> {
NotificationUtil.update(data) NotificationUtil.update(data)
return true return true
} }
ACTIONS.setFallBackNotification -> { ACTIONS.setFallBackNotification -> {
NotificationUtil.saveFallBackMessage(data, mService) NotificationUtil.saveFallBackMessage(data, mService)
return true 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 -> { IBinder.LAST_CALL_TRANSACTION -> {
Log.e(tag, "The OS Requested to shut down the VPN") Log.e(tag, "The OS Requested to shut down the VPN")
this.mService.turnOff() this.mService.turnOff()
@ -132,6 +162,7 @@ class VPNServiceBinder(service: VPNService) : Binder() {
return false return false
} }
} }
return false return false
} }
@ -166,5 +197,23 @@ class VPNServiceBinder(service: VPNService) : Binder() {
const val statisticUpdate = 3 const val statisticUpdate = 3
const val backendLogs = 4 const val backendLogs = 4
const val activationError = 5 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

@ -157,8 +157,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 \
@ -280,9 +280,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
@ -318,6 +328,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

@ -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,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

@ -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
}
if temp_addr?.pointee.ifa_addr.pointee.sa_family == UInt8(AF_INET) { // Check for IPv4 or IPv6 interface:
// Check if interface is en0 which is the wifi connection on the iPhone let addrFamily = interface.ifa_addr.pointee.sa_family
if let name = temp_addr?.pointee.ifa_name, ((String(utf8String: name)?.contains("tun")) != nil) { //if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) { // **ipv6 committed
// Get NSString from C String if addrFamily == UInt8(AF_INET){
if let value = temp_addr?.pointee.ifa_addr as? sockaddr_in {
address = String(utf8String: inet_ntoa(value.sin_addr)) // 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)
} }
} }
} }
temp_addr = temp_addr?.pointee.ifa_next freeifaddrs(ifaddr)
}
}
freeifaddrs(interfaces)
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,7 +83,7 @@ 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);
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()->goToPage(Page::Vpn);
emit uiLogic()->setStartPage(Page::Vpn); emit uiLogic()->setStartPage(Page::Vpn);
} }
}

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,9 +40,27 @@ PageBase {
id: loader id: loader
anchors.top: caption.bottom anchors.top: caption.bottom
anchors.bottom: progressColumn.top
anchors.left: parent.left
anchors.right: parent.right
}
Column{
height: 40
id: progressColumn
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right 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 {

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

@ -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