From 0da63062d774b571de2ee5759f63efe107a85f2b Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Sat, 3 Dec 2022 15:23:52 +0300 Subject: [PATCH 1/6] bugfix: fixed transition to the "Installed services" page when importing a config that does not have installed containers --- client/ui/pages_logic/StartPageLogic.cpp | 8 -------- client/ui/pages_logic/ViewConfigLogic.cpp | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index 1e28d6cd..306db93b 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -166,14 +166,6 @@ bool StartPageLogic::importConnection(const QJsonObject &profile) 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; } diff --git a/client/ui/pages_logic/ViewConfigLogic.cpp b/client/ui/pages_logic/ViewConfigLogic.cpp index 17d8814e..1dfe9abe 100644 --- a/client/ui/pages_logic/ViewConfigLogic.cpp +++ b/client/ui/pages_logic/ViewConfigLogic.cpp @@ -61,7 +61,17 @@ void ViewConfigLogic::importConfig() m_settings->addServer(configJson()); 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); + } } From a9217810e75a00370dfb55eb654e1d9ba23ecd74 Mon Sep 17 00:00:00 2001 From: pokamest Date: Sun, 4 Dec 2022 21:54:22 +0100 Subject: [PATCH 2/6] Remove travis builds and tiny refactoring --- .travis.yml | 343 ------------------ client/client.pro | 4 +- .../windows/amneziavpn.rc} | 2 +- 3 files changed, 3 insertions(+), 346 deletions(-) delete mode 100644 .travis.yml rename client/{platform_win/vpnclient.rc => platforms/windows/amneziavpn.rc} (95%) diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9e16ef5f..00000000 --- a/.travis.yml +++ /dev/null @@ -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 - diff --git a/client/client.pro b/client/client.pro index bf9db7ed..7840ae6a 100644 --- a/client/client.pro +++ b/client/client.pro @@ -155,8 +155,8 @@ TRANSLATIONS = \ win32 { DEFINES += MVPN_WINDOWS - OTHER_FILES += platform_win/vpnclient.rc - RC_FILE = platform_win/vpnclient.rc + OTHER_FILES += platforms/windows/amneziavpn.rc + RC_FILE = platforms/windows/amneziavpn.rc HEADERS += \ protocols/ikev2_vpn_protocol_windows.h \ diff --git a/client/platform_win/vpnclient.rc b/client/platforms/windows/amneziavpn.rc similarity index 95% rename from client/platform_win/vpnclient.rc rename to client/platforms/windows/amneziavpn.rc index b12fbfcb..05365077 100644 --- a/client/platform_win/vpnclient.rc +++ b/client/platforms/windows/amneziavpn.rc @@ -1,7 +1,7 @@ #include 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_STR "2.0.0.0\0" From cad0dabe42a9800e931f41087e40848b86b5c56a Mon Sep 17 00:00:00 2001 From: Dmitriy Karpushin Date: Thu, 8 Dec 2022 11:51:28 +0300 Subject: [PATCH 3/6] Export/import of configuration filed on Android --- client/android/AndroidManifest.xml | 96 +++++++- client/android/res/xml/fileprovider.xml | 4 + .../src/org/amnezia/vpn/IPCContract.kt | 5 + .../android/src/org/amnezia/vpn/VPNService.kt | 75 ++++++ .../src/org/amnezia/vpn/VPNServiceBinder.kt | 233 +++++++++++------- .../src/org/amnezia/vpn/qt/VPNActivity.java | 37 --- .../src/org/amnezia/vpn/qt/VPNActivity.kt | 196 +++++++++++++++ client/client.pro | 10 + .../platforms/android/android_controller.cpp | 34 ++- client/platforms/android/android_controller.h | 10 +- .../qml/Pages/Share/PageShareProtoAmnezia.qml | 2 +- .../qml/Pages/Share/PageShareProtoCloak.qml | 2 +- .../qml/Pages/Share/PageShareProtoOpenVPN.qml | 2 +- .../Pages/Share/PageShareProtoWireGuard.qml | 2 +- client/ui/uilogic.cpp | 7 +- 15 files changed, 568 insertions(+), 147 deletions(-) create mode 100644 client/android/res/xml/fileprovider.xml create mode 100644 client/android/src/org/amnezia/vpn/IPCContract.kt delete mode 100644 client/android/src/org/amnezia/vpn/qt/VPNActivity.java create mode 100644 client/android/src/org/amnezia/vpn/qt/VPNActivity.kt diff --git a/client/android/AndroidManifest.xml b/client/android/AndroidManifest.xml index cb70759d..55cffe20 100644 --- a/client/android/AndroidManifest.xml +++ b/client/android/AndroidManifest.xml @@ -1,5 +1,10 @@ - + @@ -18,12 +23,72 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -79,10 +144,17 @@ - + + + + @@ -95,10 +167,24 @@ - + + + + + + + + diff --git a/client/android/res/xml/fileprovider.xml b/client/android/res/xml/fileprovider.xml new file mode 100644 index 00000000..426348c0 --- /dev/null +++ b/client/android/res/xml/fileprovider.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/client/android/src/org/amnezia/vpn/IPCContract.kt b/client/android/src/org/amnezia/vpn/IPCContract.kt new file mode 100644 index 00000000..4ae3596d --- /dev/null +++ b/client/android/src/org/amnezia/vpn/IPCContract.kt @@ -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" diff --git a/client/android/src/org/amnezia/vpn/VPNService.kt b/client/android/src/org/amnezia/vpn/VPNService.kt index a1f8550c..23e9ff0c 100644 --- a/client/android/src/org/amnezia/vpn/VPNService.kt +++ b/client/android/src/org/amnezia/vpn/VPNService.kt @@ -15,6 +15,8 @@ import android.os.* import android.system.ErrnoException import android.system.Os import android.system.OsConstants +import android.text.TextUtils +import androidx.core.content.FileProvider import com.wireguard.android.util.SharedLibraryLoader import com.wireguard.config.* import com.wireguard.crypto.Key @@ -151,6 +153,31 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface { private var flags = 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() { if (mAlreadyInitialised) { return @@ -188,6 +215,14 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface { */ override fun onBind(intent: Intent): IBinder { 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) { "shadowsocks" -> { when (intent.action) { @@ -840,4 +875,44 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface { 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()) + } + } } diff --git a/client/android/src/org/amnezia/vpn/VPNServiceBinder.kt b/client/android/src/org/amnezia/vpn/VPNServiceBinder.kt index d81d5077..640a0657 100644 --- a/client/android/src/org/amnezia/vpn/VPNServiceBinder.kt +++ b/client/android/src/org/amnezia/vpn/VPNServiceBinder.kt @@ -17,6 +17,7 @@ class VPNServiceBinder(service: VPNService) : Binder() { private val tag = "VPNServiceBinder" private var mListener: IBinder? = null private var mResumeConfig: JSONObject? = null + private var mImportedConfig: String? = null /** * The codes this Binder does accept in [onTransact] @@ -31,6 +32,7 @@ class VPNServiceBinder(service: VPNService) : Binder() { const val resumeActivate = 7 const val setNotificationText = 8 const val setFallBackNotification = 9 + const val shareConfig = 10 } /** @@ -70,101 +72,148 @@ class VPNServiceBinder(service: VPNService) : Binder() { return true } - ACTIONS.resumeActivate -> { - // [data] is empty - // 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?) { + ACTIONS.resumeActivate -> { + // [data] is empty + // Activate the current tunnel 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. + mResumeConfig?.let { this.mService.turnOn(it) } + } catch (e: Exception) { + Log.e(tag, "An Error occurred while enabling the VPN: ${e.localizedMessage}") } + return true } - /** - * 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 + 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()) + + //// + 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 + } + } +} diff --git a/client/android/src/org/amnezia/vpn/qt/VPNActivity.java b/client/android/src/org/amnezia/vpn/qt/VPNActivity.java deleted file mode 100644 index 11d99063..00000000 --- a/client/android/src/org/amnezia/vpn/qt/VPNActivity.java +++ /dev/null @@ -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(); -} diff --git a/client/android/src/org/amnezia/vpn/qt/VPNActivity.kt b/client/android/src/org/amnezia/vpn/qt/VPNActivity.kt new file mode 100644 index 00000000..c5b5107e --- /dev/null +++ b/client/android/src/org/amnezia/vpn/qt/VPNActivity.kt @@ -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, 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) + } +} diff --git a/client/client.pro b/client/client.pro index 7840ae6a..ca309455 100644 --- a/client/client.pro +++ b/client/client.pro @@ -263,9 +263,19 @@ android { android/gradlew.bat \ android/gradle.properties \ 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/Prefs.kt \ + android/src/org/amnezia/vpn/VpnLogger.kt \ android/src/org/amnezia/vpn/VpnService.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_PACKAGE_SOURCE_DIR = $$PWD/android diff --git a/client/platforms/android/android_controller.cpp b/client/platforms/android/android_controller.cpp index 6b2c1aa0..af30fe05 100644 --- a/client/platforms/android/android_controller.cpp +++ b/client/platforms/android/android_controller.cpp @@ -16,19 +16,21 @@ #include "android_controller.h" #include "core/errorstrings.h" +#include "ui/pages_logic/StartPageLogic.h" // Binder Codes for VPNServiceBinder // See also - VPNServiceBinder.kt // Actions that are Requestable const int ACTION_ACTIVATE = 1; 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_GET_LOG = 5; const int ACTION_REQUEST_CLEANUP_LOG = 6; const int ACTION_RESUME_ACTIVATE = 7; const int ACTION_SET_NOTIFICATION_TEXT = 8; const int ACTION_SET_NOTIFICATION_FALLBACK = 9; +const int ACTION_SHARE_CONFIG = 10; // Event Types that will be Dispatched after registration const int EVENT_INIT = 0; @@ -37,6 +39,7 @@ const int EVENT_DISCONNECTED = 2; const int EVENT_STATISTIC_UPDATE = 3; const int EVENT_BACKEND_LOGS = 4; const int EVENT_ACTIVATION_ERROR = 5; +const int EVENT_CONFIG_IMPORT = 6; namespace { AndroidController* s_instance = nullptr; @@ -57,10 +60,12 @@ AndroidController* AndroidController::instance() { return s_instance; } -bool AndroidController::initialize() +bool AndroidController::initialize(StartPageLogic *startPageLogic) { qDebug() << "Initializing"; + m_startPageLogic = startPageLogic; + // Hook in the native implementation for startActivityForResult into the JNI JNINativeMethod methods[]{{"startActivityForResult", "(Landroid/content/Intent;)V", @@ -148,6 +153,16 @@ void AndroidController::setNotificationText(const QString& title, 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 * switches into the Connected state without the app open @@ -187,6 +202,10 @@ void AndroidController::cleanupBackendLogs() { m_serviceBinder.transact(ACTION_REQUEST_CLEANUP_LOG, nullParcel, nullptr); } +void AndroidController::importConfig(const QString& data){ + m_startPageLogic->importConnectionFromCode(data); +} + void AndroidController::onServiceConnected( const QString& name, const QAndroidBinder& serviceBinder) { qDebug() << "Server " + name + " connected"; @@ -198,7 +217,7 @@ void AndroidController::onServiceConnected( // Send the Service our Binder to recive incoming Events QAndroidParcel binderParcel; 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) { @@ -279,7 +298,14 @@ bool AndroidController::VPNBinder::onTransact(int code, case EVENT_ACTIVATION_ERROR: qDebug() << "Transact: 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: qWarning() << "Transact: Invalid!"; break; diff --git a/client/platforms/android/android_controller.h b/client/platforms/android/android_controller.h index a4734414..c2a65381 100644 --- a/client/platforms/android/android_controller.h +++ b/client/platforms/android/android_controller.h @@ -4,11 +4,13 @@ #include #include +#include "ui/uilogic.h" +#include "ui/pages_logic/StartPageLogic.h" + #include "protocols/vpnprotocol.h" using namespace amnezia; - class AndroidController : public QObject, public QAndroidServiceConnection { Q_OBJECT @@ -19,7 +21,7 @@ public: virtual ~AndroidController() override = default; - bool initialize(); + bool initialize(StartPageLogic *startPageLogic); ErrorCode start(); void stop(); @@ -27,9 +29,11 @@ public: void checkStatus(); void setNotificationText(const QString& title, const QString& message, int timerSec); + void shareConfig(const QString& data, const QString& suggestedName); void setFallbackConnectedNotification(); void getBackendLogs(std::function&& callback); void cleanupBackendLogs(); + void importConfig(const QString& data); // from QAndroidServiceConnection void onServiceConnected(const QString& name, const QAndroidBinder& serviceBinder) override; @@ -58,6 +62,8 @@ private: //Protocol m_protocol; QJsonObject m_vpnConfig; + StartPageLogic *m_startPageLogic; + bool m_serviceConnected = false; std::function m_logCallback; diff --git a/client/ui/qml/Pages/Share/PageShareProtoAmnezia.qml b/client/ui/qml/Pages/Share/PageShareProtoAmnezia.qml index e4b0ff83..2afecbad 100644 --- a/client/ui/qml/Pages/Share/PageShareProtoAmnezia.qml +++ b/client/ui/qml/Pages/Share/PageShareProtoAmnezia.qml @@ -112,7 +112,7 @@ New encryption keys pair will be generated.") Layout.bottomMargin: 10 Layout.fillWidth: true Layout.preferredHeight: 40 - text: qsTr("Save to file") + text: Qt.platform.os === "android" ? qsTr("Share") : qsTr("Save to file") enabled: tfShareCode.textArea.length > 0 visible: tfShareCode.textArea.length > 0 diff --git a/client/ui/qml/Pages/Share/PageShareProtoCloak.qml b/client/ui/qml/Pages/Share/PageShareProtoCloak.qml index bd415c95..fe92c1e7 100644 --- a/client/ui/qml/Pages/Share/PageShareProtoCloak.qml +++ b/client/ui/qml/Pages/Share/PageShareProtoCloak.qml @@ -94,7 +94,7 @@ PageShareProtocolBase { Layout.fillWidth: true Layout.preferredHeight: 40 - text: qsTr("Save to file") + text: Qt.platform.os === "android" ? qsTr("Share") : qsTr("Save to file") enabled: tfShareCode.textArea.length > 0 visible: tfShareCode.textArea.length > 0 diff --git a/client/ui/qml/Pages/Share/PageShareProtoOpenVPN.qml b/client/ui/qml/Pages/Share/PageShareProtoOpenVPN.qml index 5ca587b7..ab4a9a3d 100644 --- a/client/ui/qml/Pages/Share/PageShareProtoOpenVPN.qml +++ b/client/ui/qml/Pages/Share/PageShareProtoOpenVPN.qml @@ -93,7 +93,7 @@ PageShareProtocolBase { Layout.preferredHeight: 40 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 visible: tfShareCode.textArea.length > 0 diff --git a/client/ui/qml/Pages/Share/PageShareProtoWireGuard.qml b/client/ui/qml/Pages/Share/PageShareProtoWireGuard.qml index f5746e20..336964ac 100644 --- a/client/ui/qml/Pages/Share/PageShareProtoWireGuard.qml +++ b/client/ui/qml/Pages/Share/PageShareProtoWireGuard.qml @@ -91,7 +91,7 @@ PageShareProtocolBase { Layout.preferredHeight: 40 Layout.fillWidth: true - text: qsTr("Save to file") + text: Qt.platform.os === "android" ? qsTr("Share") : qsTr("Save to file") enabled: tfShareCode.textArea.length > 0 visible: tfShareCode.textArea.length > 0 diff --git a/client/ui/uilogic.cpp b/client/ui/uilogic.cpp index e1468da7..1922a1ab 100644 --- a/client/ui/uilogic.cpp +++ b/client/ui/uilogic.cpp @@ -134,7 +134,7 @@ void UiLogic::initalizeUiLogic() pageLogic()->onConnectionStateChanged(VpnProtocol::Connected); } }); - if (!AndroidController::instance()->initialize()) { + if (!AndroidController::instance()->initialize(pageLogic())) { qCritical() << QString("Init failed") ; emit VpnProtocol::Error; return; @@ -595,8 +595,9 @@ void UiLogic::saveTextFile(const QString& desc, const QString& suggestedName, QS if (fileName.isEmpty()) return; if (!fileName.toString().endsWith(ext)) fileName = QUrl(fileName.toString() + ext); #elif defined Q_OS_ANDROID - fileName = QFileDialog::getSaveFileUrl(nullptr, suggestedName, - QUrl::fromLocalFile(docDir), "*" + ext); + qDebug() << "UiLogic::shareConfig" << data; + AndroidController::instance()->shareConfig(data, suggestedName); + return; #endif if (fileName.isEmpty()) return; From 814b66c04a58435f248bb22d99e0af39a22df36f Mon Sep 17 00:00:00 2001 From: dartsyms <12047225+dartsyms@users.noreply.github.com> Date: Mon, 12 Dec 2022 16:16:12 +0400 Subject: [PATCH 4/6] Various fixes for iOS (#126) * Readme update, solution for wireguard make in M1 machines, * import file and restore enabled. * xcode_patcher.rb fixed, Now no need to add openVPN framewrok in Embed frameworks manually. * Now xcode_patcher.rb will add OpenVPN Framework to Embed Frameworks in main target, instead of Network extension. * Update iosvpnprotocol.swift * Protocol wasn't detected because it is working on localized description of tunnel, fixed cases. * Code cleanup * Speed issue fixed for wireguard. * GetDeviceIp and bytes(speed of OpenVPN) fixed. *Device IP method wasn't working as expected, so I replaced. and for speed in OpenVPN we need to handle message seperately for bytes. *QR progress added with progressbar and text. --- .gitignore | 1 + README.md | 5 + client/3rd/ShadowSocks/ss_ios.xcconfig | 23 --- client/client.pro | 1 + client/constants.h | 18 +-- client/fastlane/report.xml | 58 ------- client/ios/app/Info.plist | 6 +- client/macos/networkextension/Info.plist | 2 +- client/platforms/ios/QtAppDelegate.mm | 12 +- client/platforms/ios/iostunnel.swift | 17 ++- client/platforms/ios/iosvpnprotocol.swift | 75 +++++---- client/scripts/apple_compile.sh | 31 +--- client/scripts/xcode_patcher.rb | 167 +++------------------ client/ui/pages_logic/AppSettingsLogic.cpp | 4 +- client/ui/pages_logic/StartPageLogic.cpp | 5 +- client/ui/qml/Pages/PageQrDecoderIos.qml | 20 ++- client/ui/uilogic.cpp | 2 - client/versionfull.pri | 4 +- client/vpnconnection.cpp | 51 ++++++- client/vpnconnection.h | 8 + client/xcode.xconfig | 2 +- 21 files changed, 189 insertions(+), 323 deletions(-) delete mode 100644 client/3rd/ShadowSocks/ss_ios.xcconfig delete mode 100644 client/fastlane/report.xml diff --git a/.gitignore b/.gitignore index 1b4e16b2..e2fdf13d 100644 --- a/.gitignore +++ b/.gitignore @@ -125,3 +125,4 @@ captures/ # Android Profiling *.hprof +client/3rd/ShadowSocks/ss_ios.xcconfig diff --git a/README.md b/README.md index 4d5cd364..884e2205 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,11 @@ Error 1 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`. +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 dependencies in parallel, and some dependencies end up being built after the ones that require them. In this case simply restart the build. diff --git a/client/3rd/ShadowSocks/ss_ios.xcconfig b/client/3rd/ShadowSocks/ss_ios.xcconfig deleted file mode 100644 index 8b67bd01..00000000 --- a/client/3rd/ShadowSocks/ss_ios.xcconfig +++ /dev/null @@ -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 diff --git a/client/client.pro b/client/client.pro index 7840ae6a..439ceffa 100644 --- a/client/client.pro +++ b/client/client.pro @@ -301,6 +301,7 @@ ios { LIBS += -framework Foundation LIBS += -framework StoreKit LIBS += -framework UserNotifications + LIBS += -framework AVFoundation DEFINES += MVPN_IOS diff --git a/client/constants.h b/client/constants.h index 9059eccc..90f5e6eb 100644 --- a/client/constants.h +++ b/client/constants.h @@ -107,21 +107,5 @@ constexpr const char* PLATFORM_NAME = 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 diff --git a/client/fastlane/report.xml b/client/fastlane/report.xml deleted file mode 100644 index e0cdc969..00000000 --- a/client/fastlane/report.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/client/ios/app/Info.plist b/client/ios/app/Info.plist index 20a28b2a..f5681a20 100644 --- a/client/ios/app/Info.plist +++ b/client/ios/app/Info.plist @@ -38,13 +38,15 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 2 + 7 ITSAppUsesNonExemptEncryption LSRequiresIPhoneOS + UIFileSharingEnabled + LSSupportsOpeningDocumentsInPlace - + NSCameraUsageDescription Amnezia VPN needs access to the camera for reading QR-codes. UILaunchStoryboardName diff --git a/client/macos/networkextension/Info.plist b/client/macos/networkextension/Info.plist index 08fc4d0a..96d82459 100644 --- a/client/macos/networkextension/Info.plist +++ b/client/macos/networkextension/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 2 + $(CURRENT_PROJECT_VERSION) ITSAppUsesNonExemptEncryption LSMinimumSystemVersion diff --git a/client/platforms/ios/QtAppDelegate.mm b/client/platforms/ios/QtAppDelegate.mm index f63bea35..e6ec8444 100644 --- a/client/platforms/ios/QtAppDelegate.mm +++ b/client/platforms/ios/QtAppDelegate.mm @@ -2,7 +2,9 @@ #include -@implementation QtAppDelegate +@implementation QtAppDelegate { + UIView *_screen; +} +(QtAppDelegate *)sharedQtAppDelegate { 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. // 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 @@ -44,6 +53,7 @@ - (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. + [_screen removeFromSuperview]; } - (void)applicationWillTerminate:(UIApplication *)application diff --git a/client/platforms/ios/iostunnel.swift b/client/platforms/ios/iostunnel.swift index 5209306d..6d87a18d 100644 --- a/client/platforms/ios/iostunnel.swift +++ b/client/platforms/ios/iostunnel.swift @@ -125,7 +125,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { case .wireguard: handleWireguardAppMessage(messageData, completionHandler: completionHandler) case .openvpn: - handleWireguardAppMessage(messageData, completionHandler: completionHandler) + handleOpenVPNAppMessage(messageData, completionHandler: completionHandler) case .shadowsocks: break // handleShadowSocksAppMessage(messageData, completionHandler: completionHandler) @@ -297,6 +297,21 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } } + private func handleOpenVPNAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) { + guard let completionHandler = completionHandler else { return } + if messageData.count == 1 && messageData[0] == 0 { + let bytesin = ovpnAdapter.transportStatistics.bytesIn + let strBytesin = "rx_bytes=" + String(bytesin); + + let bytesout = ovpnAdapter.transportStatistics.bytesOut + let strBytesout = "tx_bytes=" + String(bytesout); + + let strData = strBytesin + "\n" + strBytesout; + let data = Data(strData.utf8) + completionHandler(data) + } + } + /* private func handleShadowSocksAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) { guard let completionHandler = completionHandler else { return } diff --git a/client/platforms/ios/iosvpnprotocol.swift b/client/platforms/ios/iosvpnprotocol.swift index 2c028915..95505b21 100644 --- a/client/platforms/ios/iosvpnprotocol.swift +++ b/client/platforms/ios/iosvpnprotocol.swift @@ -388,7 +388,7 @@ public class IOSVpnProtocolImpl : NSObject { proto.providerBundleIdentifier = vpnBundleID tunnel!.protocolConfiguration = proto - tunnel!.localizedDescription = vpnName + tunnel!.localizedDescription = "Amnezia Wireguard" tunnel!.isEnabled = true tunnel!.saveToPreferences { [unowned self] saveError in @@ -527,8 +527,9 @@ public class IOSVpnProtocolImpl : NSObject { @objc func checkStatus(callback: @escaping (String, String, String) -> Void) { Logger.global?.log(message: "Check status") // assert(tunnel != nil) - + print("check status") let protoType = (tunnel!.localizedDescription ?? "").toTunnelType + print(protoType); switch protoType { case .wireguard: @@ -559,7 +560,7 @@ public class IOSVpnProtocolImpl : NSObject { print("server IP: \(serverIpv4Gateway)") - let deviceIpv4Address = getTunIPAddress() + let deviceIpv4Address = getWiFiAddress() print("device IP: \(serverIpv4Gateway)") if deviceIpv4Address == nil { callback("", "", "") @@ -610,8 +611,9 @@ public class IOSVpnProtocolImpl : NSObject { print("server IP: \(serverIpv4Gateway)") - let deviceIpv4Address = getTunIPAddress() - print("device IP: \(serverIpv4Gateway)") + + let deviceIpv4Address = getWiFiAddress() + print("device IP: \(deviceIpv4Address)") if deviceIpv4Address == nil { callback("", "", "") return @@ -690,38 +692,45 @@ public class IOSVpnProtocolImpl : NSObject { } } - private func getTunIPAddress() -> String? { - var address: String? = nil - var interfaces: UnsafeMutablePointer? = nil - var temp_addr: UnsafeMutablePointer? = nil - var success: Int = 0 - - // retrieve the current interfaces - returns 0 on success - success = Int(getifaddrs(&interfaces)) - if success == 0 { - // Loop through linked list of interfaces - temp_addr = interfaces - while temp_addr != nil { - if temp_addr?.pointee.ifa_addr == nil { - continue + func getWiFiAddress() -> String? { + var address : String? + + // Get list of all interfaces on the local machine: + var ifaddr : UnsafeMutablePointer? + guard getifaddrs(&ifaddr) == 0 else { return nil } + guard let firstAddr = ifaddr else { return nil } + + // For each interface ... + for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) { + 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 } + + } + enum TunnelType: String { case wireguard, openvpn, shadowsocks, empty } @@ -729,9 +738,9 @@ enum TunnelType: String { extension String { var toTunnelType: TunnelType { switch self { - case "wireguard": return .wireguard - case "openvpn": return .openvpn - case "shadowsocks": return .shadowsocks + case "Amnezia Wireguard": return .wireguard + case "Amnezia OpenVPN": return .openvpn + case "Amnezia ShadowSocks": return .shadowsocks default: return .empty } diff --git a/client/scripts/apple_compile.sh b/client/scripts/apple_compile.sh index fb44af30..403460fa 100755 --- a/client/scripts/apple_compile.sh +++ b/client/scripts/apple_compile.sh @@ -10,13 +10,11 @@ fi RELEASE=1 OS= NETWORKEXTENSION= -ADJUST_SDK_TOKEN= -ADJUST="CONFIG-=adjust" WORKINGDIR=`pwd` helpFunction() { print G "Usage:" - print N "\t$0 [-d|--debug] [-n|--networkextension] [-a|--adjusttoken ]" + print N "\t$0 [-d|--debug] [-n|--networkextension]" print N "" 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." @@ -26,7 +24,6 @@ helpFunction() { print G "Config variables:" print N "\tQT_MACOS_BIN=" print N "\tQT_IOS_BIN=" - print N "\tMVPN_IOS_ADJUST_TOKEN=" print N "" exit 0 } @@ -38,11 +35,6 @@ while [[ $# -gt 0 ]]; do key="$1" case $key in - -a | --adjusttoken) - ADJUST_SDK_TOKEN="$2" - shift - shift - ;; -d | --debug) RELEASE= shift @@ -97,11 +89,6 @@ if [[ "$OS" != "macos" ]] && [[ "$OS" != "ios" ]] && [[ "$OS" != "macostest" ]]; helpFunction 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 # Network-extension is the default for IOS NETWORKEXTENSION=1 @@ -150,7 +137,6 @@ MACOS_FLAGS=" QTPLUGIN+=qsvg CONFIG-=static CONFIG+=balrog - MVPN_MACOS=1 " MACOSTEST_FLAGS=" @@ -160,7 +146,6 @@ MACOSTEST_FLAGS=" " IOS_FLAGS=" - MVPN_IOS=1 Q_OS_IOS=1 " @@ -183,11 +168,6 @@ elif [ "$OS" = "macostest" ]; then PLATFORM=$MACOSTEST_FLAGS elif [ "$OS" = "ios" ]; then PLATFORM=$IOS_FLAGS - if [[ "$ADJUST_SDK_TOKEN" ]]; then - printn Y "ADJUST_SDK_TOKEN: " - print G "$ADJUST_SDK_TOKEN" - ADJUST="CONFIG+=adjust" - fi else killProcess "Why are we here?" fi @@ -249,7 +229,7 @@ else print Y "No Tun2Socks will be built" fi -print Y "Creating the xcode project via qmake..." +print Y "Creating the Xcode project via qmake..." $QMAKE \ VERSION=$SHORTVERSION \ BUILD_ID=$FULLVERSION \ @@ -258,11 +238,10 @@ $QMAKE \ $VPNMODE \ $WEMODE \ $PLATFORM \ - $ADJUST \ ./client.pro || killProcess "Compilation failed" 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." if command -v "sed" &>/dev/null; then @@ -270,6 +249,6 @@ print G "done." sed -i '' '/Original<\/string>/d' AmneziaVPN.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings fi -# print Y "Opening in XCode..." -# open AmneziaVPN.xcodeproj print G "All done!" +print Y "Opening project in Xcode..." +open AmneziaVPN.xcodeproj diff --git a/client/scripts/xcode_patcher.rb b/client/scripts/xcode_patcher.rb index 0a0550ca..6f9c4c41 100644 --- a/client/scripts/xcode_patcher.rb +++ b/client/scripts/xcode_patcher.rb @@ -9,7 +9,7 @@ class XCodeprojPatcher attr :target_main 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 setup_project open_target_main @@ -19,13 +19,7 @@ class XCodeprojPatcher group = @project.main_group.new_group('Configuration') @configFile = group.new_file('xcode.xconfig') - setup_target_main shortVersion, fullVersion, platform, networkExtension, configHash, adjust_sdk_token - -# if platform == 'macos' -# setup_target_loginitem shortVersion, fullVersion, configHash -# setup_target_nativemessaging shortVersion, fullVersion, configHash -# end - + setup_target_main shortVersion, fullVersion, platform, networkExtension, configHash if networkExtension setup_target_extension shortVersion, fullVersion, platform, configHash @@ -59,7 +53,7 @@ class XCodeprojPatcher 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| config.base_configuration_reference = @configFile @@ -72,10 +66,8 @@ class XCodeprojPatcher "$(PROJECT_DIR)/3rd", "$(PROJECT_DIR)/3rd/OpenVPNAdapter/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/CocoaAsyncSocket/build/Release-iphoneos", -# "${PROJECT_DIR}/3rd/CocoaLumberjack/build/Release-iphoneos", ] # Versions and names @@ -91,9 +83,6 @@ class XCodeprojPatcher config.build_settings['INFOPLIST_FILE'] ||= platform + '/app/Info.plist' if platform == 'ios' 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 config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'macos/app/app.entitlements' else @@ -104,7 +93,7 @@ class XCodeprojPatcher config.build_settings['ENABLE_BITCODE'] ||= 'NO' 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['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 = ""; if (platform == 'macos') @@ -173,96 +162,23 @@ class XCodeprojPatcher } end - if (platform == 'ios' && adjust_sdk_token != "") + if(platform == 'ios') + 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' } - framework_ref = frameworks_group.new_file('AdServices.framework') - build_file = frameworks_build_phase.add_file_reference(framework_ref) - build_file.settings = { 'ATTRIBUTES' => ['Weak'] } + embed_frameworks_build_phase = project.new(Xcodeproj::Project::Object::PBXCopyFilesBuildPhase) + embed_frameworks_build_phase.name = 'Embed Frameworks' + embed_frameworks_build_phase.symbol_dst_subfolder_spec = :frameworks + @target_main.build_phases << embed_frameworks_build_phase - framework_ref = frameworks_group.new_file('iAd.framework') - frameworks_build_phase.add_file_reference(framework_ref) + framework_ref = frameworks_group.new_file('3rd/OpenVPNAdapter/build/Release-iphoneos/OpenVPNAdapter.framework') + build_file = embed_frameworks_build_phase.add_file_reference(framework_ref) - # 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') - } + frameworks_build_phase.add_file_reference(framework_ref) + build_file.settings = { 'ATTRIBUTES' => ['CodeSignOnCopy', 'RemoveHeadersOnCopy'] } end + end def setup_target_extension(shortVersion, fullVersion, platform, configHash) @@ -288,12 +204,9 @@ class XCodeprojPatcher "$(PROJECT_DIR)/3rd/OpenVPNAdapter/build/Release-iphoneos", "$(PROJECT_DIR)/3rd/libleaf/lib", "$(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/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 config.build_settings['MARKETING_VERSION'] ||= shortVersion @@ -325,7 +238,7 @@ class XCodeprojPatcher "-framework", "OpenGLES", ] - config.build_settings['PATH'] = '${PATH}:/usr/local/go/bin' + config.build_settings['PATH'] = '${PATH}:/opt/local/bin:/usr/local/go/bin' end groupId = ""; @@ -379,17 +292,7 @@ class XCodeprojPatcher 'platforms/ios/iostunnel.swift', 'platforms/ios/ioslogger.swift', 'platforms/ios/iosinterface.swift', -# 'platforms/ios/ssprovider.swift', '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| file = group.new_file(filename) @target_extension.add_file_references([file]) @@ -402,40 +305,10 @@ class XCodeprojPatcher framework_ref = frameworks_group.new_file('libwg-go.a') 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') 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 container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy) container_proxy.container_portal = @project.root_object.uuid @@ -492,6 +365,7 @@ class XCodeprojPatcher framework_ref = frameworks_group.new_file('balrog/balrog.a') frameworks_build_phase.add_file_reference(framework_ref) + # This fails: @target_main.add_dependency target_balrog container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy) container_proxy.container_portal = @project.root_object.uuid @@ -599,7 +473,7 @@ class XCodeprojPatcher # other configs 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['SKIP_INSTALL'] = 'YES' @@ -708,7 +582,7 @@ class XCodeprojPatcher copy_nativeMessagingManifest.dst_path = 'Contents/Resources/utils' 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.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] } @@ -744,8 +618,7 @@ configFile.each { |line| platform = "macos" platform = "ios" if ARGV[3] == "ios" networkExtension = true if ARGV[4] == "1" -adjust_sdk_token = ARGV[5] 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 diff --git a/client/ui/pages_logic/AppSettingsLogic.cpp b/client/ui/pages_logic/AppSettingsLogic.cpp index b2907c3d..b22918b2 100644 --- a/client/ui/pages_logic/AppSettingsLogic.cpp +++ b/client/ui/pages_logic/AppSettingsLogic.cpp @@ -83,8 +83,8 @@ void AppSettingsLogic::onPushButtonBackupAppConfigClicked() void AppSettingsLogic::onPushButtonRestoreAppConfigClicked() { - QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open backup"), - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.backup"); + QString fileName = QFileDialog::getOpenFileName(Q_NULLPTR, tr("Open backup"), + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.backup"); if (fileName.isEmpty()) return; diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index 1e28d6cd..a5a0a38d 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -135,9 +135,8 @@ void StartPageLogic::onPushButtonImport() void StartPageLogic::onPushButtonImportOpenFile() { - QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open profile"), - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn"); - + QString fileName = QFileDialog::getOpenFileName(Q_NULLPTR, tr("Open profile"), + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), tr("*.vpn")); if (fileName.isEmpty()) return; QFile file(fileName); diff --git a/client/ui/qml/Pages/PageQrDecoderIos.qml b/client/ui/qml/Pages/PageQrDecoderIos.qml index 7dd077dd..0e796312 100644 --- a/client/ui/qml/Pages/PageQrDecoderIos.qml +++ b/client/ui/qml/Pages/PageQrDecoderIos.qml @@ -40,11 +40,29 @@ PageBase { id: loader anchors.top: caption.bottom - anchors.bottom: parent.bottom + anchors.bottom: progressColumn.top anchors.left: parent.left 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 { id: component diff --git a/client/ui/uilogic.cpp b/client/ui/uilogic.cpp index e1468da7..2d93d429 100644 --- a/client/ui/uilogic.cpp +++ b/client/ui/uilogic.cpp @@ -266,8 +266,6 @@ void UiLogic::onGotoCurrentProtocolsPage() emit goToPage(Page::ServerContainers); } - - //void UiLogic::showEvent(QShowEvent *event) //{ //#if defined Q_OS_MACX diff --git a/client/versionfull.pri b/client/versionfull.pri index 5fc93c79..5ee6310c 100644 --- a/client/versionfull.pri +++ b/client/versionfull.pri @@ -1,2 +1,2 @@ -# current build 1 -!defined(BUILDVERSION, var):BUILDVERSION = 2 \ No newline at end of file +# current build 6 +!defined(BUILDVERSION, var):BUILDVERSION = 7 \ No newline at end of file diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index 6e117ce4..6a981f0c 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -1,3 +1,4 @@ +#include "qtimer.h" #include #include #include @@ -34,7 +35,10 @@ VpnConnection::VpnConnection(std::shared_ptr settings, std::shared_ptr serverController, QObject* parent) : QObject(parent), m_settings(settings), 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) { - emit bytesChanged(receivedBytes, sentBytes); + emit bytesChanged(receivedBytes - m_receivedBytes, sentBytes - m_sentBytes); + + m_receivedBytes = receivedBytes; + m_sentBytes = sentBytes; + } void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState state) { + #ifdef AMNEZIA_DESKTOP if (IpcClient::Interface()) { if (state == VpnProtocol::Connected){ @@ -94,9 +103,35 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState sta } } #endif + +#ifdef Q_OS_IOS + + qDebug() << state; + if(state == VpnProtocol::Connected){ + m_isIOSConnected = true; + checkIOSStatus(); + }else{ + + m_isIOSConnected = false; + m_receivedBytes = 0; + m_sentBytes = 0; + } +#endif emit connectionStateChanged(state); } +void VpnConnection::checkIOSStatus() +{ + QTimer::singleShot(1000, [this]() { + + if(m_isIOSConnected){ + iosVpnProtocol->checkStatus(); + checkIOSStatus(); + } + + } ); +} + const QString &VpnConnection::remoteAddress() const { return m_remoteAddress; @@ -333,7 +368,10 @@ void VpnConnection::connectToVpn(int serverIndex, m_vpnProtocol.reset(androidVpnProtocol); #elif defined Q_OS_IOS 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()) { qDebug() << QString("Init failed") ; emit VpnProtocol::Error; @@ -384,12 +422,19 @@ void VpnConnection::disconnectFromVpn() VpnProtocol::VpnConnectionState VpnConnection::connectionState() { + + if (!m_vpnProtocol) return VpnProtocol::Disconnected; return m_vpnProtocol->connectionState(); + } bool VpnConnection::isConnected() const { +#ifdef Q_OS_IOS + +#endif + if (!m_vpnProtocol.data()) { return false; } diff --git a/client/vpnconnection.h b/client/vpnconnection.h index 18446e74..28c8ef0b 100644 --- a/client/vpnconnection.h +++ b/client/vpnconnection.h @@ -9,6 +9,7 @@ #include "protocols/vpnprotocol.h" #include "core/defs.h" #include "settings.h" +#include "protocols/ios_vpnprotocol.h" #ifdef AMNEZIA_DESKTOP #include "core/ipcclient.h" @@ -73,6 +74,7 @@ signals: protected slots: void onBytesChanged(quint64 receivedBytes, quint64 sentBytes); void onConnectionStateChanged(VpnProtocol::VpnConnectionState state); + void checkIOSStatus(); protected: QSharedPointer m_vpnProtocol; @@ -85,10 +87,16 @@ private: QJsonObject m_vpnConfiguration; QJsonObject m_routeMode; QString m_remoteAddress; + quint64 m_receivedBytes; + quint64 m_sentBytes; + bool m_isIOSConnected; //remove later move to isConnected, #ifdef AMNEZIA_DESKTOP IpcClient *m_IpcClient {nullptr}; #endif +#ifdef Q_OS_IOS + IOSVpnProtocol * iosVpnProtocol{nullptr}; +#endif }; #endif // VPNCONNECTION_H diff --git a/client/xcode.xconfig b/client/xcode.xconfig index 62778188..bbed6a13 100644 --- a/client/xcode.xconfig +++ b/client/xcode.xconfig @@ -2,4 +2,4 @@ DEVELOPMENT_TEAM = X7UJ388FXK GROUP_ID_IOS = group.org.amnezia.AmneziaVPN APP_ID_IOS = org.amnezia.AmneziaVPN -NETEXT_ID_IOS = org.amnezia.AmneziaVPN.network-extension +NETEXT_ID_IOS = org.amnezia.AmneziaVPN.network-extension \ No newline at end of file From f20f528a1140d1c203b5ca1b4ef3ba7c8b08cf81 Mon Sep 17 00:00:00 2001 From: Hamza ARBI <43709620+HamzArbi@users.noreply.github.com> Date: Mon, 12 Dec 2022 13:28:03 +0100 Subject: [PATCH 5/6] Server selection always in range (#130) * Server selection stays always in the list's range * Removed the usage of QZxing module from PageQrDecoder page * Fixed null spelling on qml instead of nil --- client/ui/pages_logic/ServerListLogic.cpp | 6 ++++++ client/ui/pages_logic/ServerListLogic.h | 6 ++++++ client/ui/qml/Pages/PageQrDecoder.qml | 4 ++-- client/ui/qml/Pages/PageQrDecoderIos.qml | 2 +- client/ui/qml/Pages/PageServerList.qml | 7 +++---- client/ui/qml/Pages/Protocols/PageProtoTorWebSite.qml | 1 - 6 files changed, 18 insertions(+), 8 deletions(-) diff --git a/client/ui/pages_logic/ServerListLogic.cpp b/client/ui/pages_logic/ServerListLogic.cpp index fe3f6512..42a629b3 100644 --- a/client/ui/pages_logic/ServerListLogic.cpp +++ b/client/ui/pages_logic/ServerListLogic.cpp @@ -15,6 +15,7 @@ void ServerListLogic::onServerListPushbuttonDefaultClicked(int index) { m_settings->setDefaultServer(index); uiLogic()->onUpdateAllPages(); + emit currServerIdxChanged(); } void ServerListLogic::onServerListPushbuttonSettingsClicked(int index) @@ -23,6 +24,11 @@ void ServerListLogic::onServerListPushbuttonSettingsClicked(int index) uiLogic()->goToPage(Page::ServerSettings); } +int ServerListLogic::currServerIdx() const +{ + return m_settings->defaultServerIndex(); +} + void ServerListLogic::onUpdatePage() { const QJsonArray &servers = m_settings->serversArray(); diff --git a/client/ui/pages_logic/ServerListLogic.h b/client/ui/pages_logic/ServerListLogic.h index 2671b97d..b4f47547 100644 --- a/client/ui/pages_logic/ServerListLogic.h +++ b/client/ui/pages_logic/ServerListLogic.h @@ -10,8 +10,11 @@ class ServerListLogic : public PageLogicBase Q_OBJECT READONLY_PROPERTY(QObject *, serverListModel) + Q_PROPERTY(int currServerIdx READ currServerIdx NOTIFY currServerIdxChanged) public: + int currServerIdx() const; + Q_INVOKABLE void onUpdatePage() override; Q_INVOKABLE void onServerListPushbuttonDefaultClicked(int index); Q_INVOKABLE void onServerListPushbuttonSettingsClicked(int index); @@ -20,5 +23,8 @@ public: explicit ServerListLogic(UiLogic *uiLogic, QObject *parent = nullptr); ~ServerListLogic() = default; +signals: + void currServerIdxChanged(); + }; #endif // SERVER_LIST_LOGIC_H diff --git a/client/ui/qml/Pages/PageQrDecoder.qml b/client/ui/qml/Pages/PageQrDecoder.qml index f432b742..61ce368f 100644 --- a/client/ui/qml/Pages/PageQrDecoder.qml +++ b/client/ui/qml/Pages/PageQrDecoder.qml @@ -26,7 +26,7 @@ PageBase { } Connections { - target: Qt.platform.os != "ios" ? QrDecoderLogic : nil + target: Qt.platform.os != "ios" ? QrDecoderLogic : null function onStartDecode() { console.debug("Starting QR decoder") loader.sourceComponent = component @@ -71,7 +71,7 @@ PageBase { anchors.right: parent.right autoOrientation: true fillMode: VideoOutput.PreserveAspectFit - filters: [ zxingFilter ] +// filters: [ zxingFilter ] Rectangle { diff --git a/client/ui/qml/Pages/PageQrDecoderIos.qml b/client/ui/qml/Pages/PageQrDecoderIos.qml index 0e796312..7e5783e8 100644 --- a/client/ui/qml/Pages/PageQrDecoderIos.qml +++ b/client/ui/qml/Pages/PageQrDecoderIos.qml @@ -25,7 +25,7 @@ PageBase { } Connections { - target: Qt.platform.os == "ios" ? QrDecoderLogic : nil + target: Qt.platform.os == "ios" ? QrDecoderLogic : null function onStartDecode() { console.debug("Starting QR decoder") loader.sourceComponent = component diff --git a/client/ui/qml/Pages/PageServerList.qml b/client/ui/qml/Pages/PageServerList.qml index 583de4b3..de6f90ab 100644 --- a/client/ui/qml/Pages/PageServerList.qml +++ b/client/ui/qml/Pages/PageServerList.qml @@ -42,6 +42,9 @@ PageBase { anchors.bottom: parent.bottom anchors.bottomMargin: 20 model: ServerListLogic.serverListModel + highlightRangeMode: ListView.ApplyRange + highlightMoveVelocity: -1 + currentIndex: ServerListLogic.currServerIdx spacing: 5 clip: true delegate: Item { @@ -55,10 +58,6 @@ PageBase { if (GC.isMobile()) { ServerListLogic.onServerListPushbuttonSettingsClicked(index) } - else { - listWidget_servers.currentIndex = index - } - mouse.accepted = false } onEntered: { diff --git a/client/ui/qml/Pages/Protocols/PageProtoTorWebSite.qml b/client/ui/qml/Pages/Protocols/PageProtoTorWebSite.qml index 1285e8bb..50f4bd4e 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoTorWebSite.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoTorWebSite.qml @@ -27,7 +27,6 @@ PageProtocolBase { anchors.top: caption.bottom anchors.left: root.left anchors.right: root.right - anchors.bottom: pb_save.top anchors.margins: 20 anchors.topMargin: 10 From 9c5e1faf46e11d8be81eac53ade7c5ed5e0f31dd Mon Sep 17 00:00:00 2001 From: pokamest Date: Mon, 12 Dec 2022 14:41:54 +0100 Subject: [PATCH 6/6] Build fixes --- README.md | 2 +- client/vpnconnection.cpp | 12 +++++------- client/vpnconnection.h | 6 ++++++ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 884e2205..4d5f993c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Amnezia 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. diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index 6a981f0c..286ffc8c 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -105,13 +105,11 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState sta #endif #ifdef Q_OS_IOS - - qDebug() << state; - if(state == VpnProtocol::Connected){ + if (state == VpnProtocol::Connected){ m_isIOSConnected = true; checkIOSStatus(); - }else{ - + } + else { m_isIOSConnected = false; m_receivedBytes = 0; m_sentBytes = 0; @@ -120,17 +118,17 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState sta 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 { diff --git a/client/vpnconnection.h b/client/vpnconnection.h index 28c8ef0b..c8ebdfad 100644 --- a/client/vpnconnection.h +++ b/client/vpnconnection.h @@ -9,7 +9,10 @@ #include "protocols/vpnprotocol.h" #include "core/defs.h" #include "settings.h" + +#ifdef Q_OS_IOS #include "protocols/ios_vpnprotocol.h" +#endif #ifdef AMNEZIA_DESKTOP #include "core/ipcclient.h" @@ -74,7 +77,10 @@ signals: protected slots: void onBytesChanged(quint64 receivedBytes, quint64 sentBytes); void onConnectionStateChanged(VpnProtocol::VpnConnectionState state); + +#ifdef Q_OS_IOS void checkIOSStatus(); +#endif protected: QSharedPointer m_vpnProtocol;