Compare commits

...

411 Commits

Author SHA1 Message Date
pokamest b9ee600fa8 Version bump 4.2.1.0 2024-01-20 18:29:38 +00:00
pokamest 407b2e8bf7 Merge pull request #517 from amnezia-vpn/dev
Release 4.2.1.0
2024-01-20 09:40:31 -08:00
pokamest f9123e7b71 Merge pull request #516 from amnezia-vpn/bugfix/easy-setup-default-container
fixed easy setup default container selection
2024-01-20 09:18:57 -08:00
pokamest 0f9ed4e69c Merge pull request #515 from amnezia-vpn/fix/android-wg
set wg PresharedKey parameter as optional
2024-01-20 09:16:16 -08:00
vladimir.kuznetsov 9dfc95bac0 fixed easy setup default container selection 2024-01-20 23:28:20 +07:00
albexk 9b7914538f set wg PresharedKey parameter as optional 2024-01-20 18:43:26 +03:00
pokamest 85c9cd260d Merge pull request #514 from amnezia-vpn/fix/android-camera
Hide "QR-code" button from config import menu for Android devices wit…
2024-01-20 07:42:55 -08:00
pokamest 73751cc049 Merge pull request #513 from amnezia-vpn/bugfix/issue499
Fix import of some native WG configs
2024-01-20 07:27:54 -08:00
albexk 2b61c48303 Hide "QR-code" button from config import menu for Android devices without camera 2024-01-20 18:20:06 +03:00
Mykola Baibuz 47b03f2bf4 PSK paramater is not mandatory 2024-01-20 08:44:48 -05:00
albexk 3e02dfef63 Refactoring Android logging (#511)
Refactoring Android logging
2024-01-20 13:40:12 +00:00
Mykola Baibuz 4176d0130a Fix import of some native WG configs 2024-01-20 08:35:24 -05:00
pokamest f6175c2c69 Merge pull request #512 from amnezia-vpn/fix/line-ending
Fix amnezia_application line-ending
2024-01-20 05:04:22 -08:00
albexk b8b423ca19 Fix amnezia_application line-ending 2024-01-20 16:02:35 +03:00
pokamest 3253de9384 Merge pull request #509 from amnezia-vpn/featute/amneziawg-apple
Change to amneziawg-apple
2024-01-19 02:17:02 -08:00
Igor Sorokin 51070635a5 Change to amneziawg-apple 2024-01-19 03:27:44 +03:00
pokamest 9b533f1ba6 Merge pull request #507 from amnezia-vpn/linux-installer
Improve Linux installer
2024-01-18 09:39:00 -08:00
tiaga 9371dd405e Improve Linux installer
Pack installer to a .tar archive in order to save executable bit for `AmneziaVPN_Linux_Installer.bin`.
2024-01-19 00:16:19 +07:00
pokamest 27d8108e55 Merge pull request #501 from amnezia-vpn/feature/api-spit-tunneling
for servers received via api, ignore the split tunneling settings
2024-01-18 08:51:12 -08:00
pokamest 820a3f0b77 Merge pull request #506 from amnezia-vpn/bugfix/client-management-ss-cloak
fixed append/rename/revoke client for cloak and ss on client management panel
2024-01-18 07:09:14 -08:00
pokamest 3d61b20271 Merge pull request #505 from amnezia-vpn/fix/readme
Update README.md
2024-01-18 07:03:08 -08:00
vladimir.kuznetsov eec81f8124 fixed append/rename/revoke client for cloak and ss on client management panel 2024-01-18 21:29:56 +07:00
Igor Sorokin d7fbddb97f Update README.md 2024-01-18 17:13:04 +03:00
pokamest 9170cb0318 Merge pull request #498 from amnezia-vpn/sort-installer-containers-first
show installed protocols first in protocols tab
2024-01-18 05:57:16 -08:00
pokamest 76dec6fa9c Merge pull request #504 from amnezia-vpn/feature/android-deploy
Add Android App Bundle build and upload
2024-01-18 05:56:50 -08:00
pokamest 4e3edcfc0a Merge pull request #503 from amnezia-vpn/fix/ipv6
Fix IPv6 problem
2024-01-18 05:56:07 -08:00
albexk ad21d7ab64 Add Android App Bundle build and upload
Up upload-artifact action to version 4
2024-01-18 16:06:37 +03:00
Igor Sorokin f576eb509d Fix IPv6 problem 2024-01-18 15:25:36 +03:00
vladimir.kuznetsov 33e229d0b2 added blocking of the page with dns settings for servers received by API 2024-01-17 23:38:20 +07:00
pokamest 78420d617b Merge pull request #502 from amnezia-vpn/fix/android-clipboard
Fix/android clipboard
2024-01-17 07:24:24 -08:00
albexk 2552e33d64 Add Android TextArea clipboard workaround 2024-01-17 17:46:54 +03:00
albexk 301141c755 Remove Android TextField workaround
It has been fixed in Qt 6.5.3, 6.6.0
2024-01-17 17:43:54 +03:00
vladimir.kuznetsov fac57ac89a for servers received via api, ignore the split tunneling settings 2024-01-17 11:28:57 +07:00
pokamest da5ad0a845 Merge pull request #500 from amnezia-vpn/fix/android-keyboard
Restore previous Android keyboard behavior
2024-01-16 05:50:28 -08:00
albexk 60aeefe1c2 Restore previous Android keyboard behaviour
There is a Qt bug related to this behaviour: https://bugreports.qt.io/browse/QTBUG-41170
2024-01-16 15:06:34 +03:00
Morteza Sherafati d527f6a5ce show installed protocols first in protocols tab 2024-01-15 20:18:10 +00:00
pokamest 2802b42747 Merge pull request #491 from amnezia-vpn/bugfix/current-processed-server-selection
fixed current processed server selection after import/install new server
2024-01-15 05:43:34 -08:00
pokamest 9c30b0f034 Merge pull request #496 from amnezia-vpn/dev
Release 4.2.0.1
2024-01-15 05:35:29 -05:00
pokamest 66c5d2f0a8 Updated submodule qtkeychain 2024-01-15 10:06:20 +00:00
pokamest 6dbf4ac62c Release 4.2.0.1 2024-01-15 09:28:48 +00:00
pokamest ae2872830b Updated submodule qtkeychain 2024-01-15 09:20:13 +00:00
pokamest 6f4a3587e4 Merge pull request #495 from amnezia-vpn/feature/update-awg-core
Update AWG core (v0.1.8)
2024-01-14 17:33:10 -05:00
Mykola Baibuz 145f51906e Update AWG core (v0.1.8) 2024-01-14 21:58:53 +02:00
pokamest 12e72bc74b Merge pull request #481 from amnezia-vpn/refactoring/android
Refactor Android open file method
2024-01-13 06:46:25 -05:00
vladimir.kuznetsov 88cd5825d3 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD 2024-01-11 20:26:06 +07:00
pokamest ecdad2a315 Merge branch 'dev' into refactoring/android 2024-01-11 13:01:03 +00:00
pokamest 0398ddd6a2 Merge pull request #488 from amnezia-vpn/bugfix/split-tunnel-reset-on-app-reset
bugfix/split-tunnel-reset-on-app-reset
2024-01-11 07:58:04 -05:00
pokamest 50ea4d3b0f Merge pull request #453 from amnezia-vpn/bugfix/windows-crush-on-utf8-symbolos
added conversion using the system locale
2024-01-11 07:51:22 -05:00
pokamest 77be8169f2 Merge pull request #493 from amnezia-vpn/bugfix/secureqsettings-deadlock-2
now value and setValue of secureQSettings are always called in the main thread
2024-01-11 07:48:42 -05:00
lunardunno 7a435f76b6 ArchLinux_support (#463)
Arch linux support (#464)
2024-01-10 20:15:14 +00:00
pokamest 42949e0dea Merge pull request #492 from amnezia-vpn/bugfix/append-client
fixed insert rows count in appendClient function
2024-01-10 12:42:07 -05:00
pokamest 26db423232 Merge pull request #489 from amnezia-vpn/bugfix/remote-links-on-site
added the ability to change the site link via a translation file
2024-01-10 12:40:19 -05:00
vladimir.kuznetsov 645cf52803 now value and setValue of secureQSettings are always called in the main thread 2024-01-10 23:05:22 +07:00
vladimir.kuznetsov 673b8ad5b2 fixed insert rows count in appendClient function 2024-01-10 11:55:32 +07:00
vladimir.kuznetsov 2a03834bb2 fixed current processed server selection after import/install new server 2024-01-09 00:25:18 +07:00
lunardunno c1b6149e49 Improve servercontroller.cpp for Ubuntu (#482)
Improve servercontroller.cpp for Ubuntu, CentOS, snd Fedora
2024-01-06 16:41:06 +00:00
vladimir.kuznetsov 0690d86e52 added the ability to change the site link via a translation file 2024-01-06 20:42:43 +07:00
vladimir.kuznetsov bb8a11d110 added reset routeMode when resetting application settings 2024-01-06 20:38:41 +07:00
pokamest 4f7ba4c9a8 Merge pull request #483 from amnezia-vpn/persian_translation
full persian translation
2023-12-30 09:11:08 -05:00
Morteza Sherafati aa41e4d915 full persian translation 2023-12-30 11:12:54 +00:00
pokamest bb43b5451f Merge pull request #478 from amnezia-vpn/bugfix/macos-dns-resolve
Fix resolv-update script for MacOS (OpenVPN DNS)
2023-12-28 14:52:28 -05:00
vladimir.kuznetsov 69dd415ab5 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into bugfix/windows-crush-on-utf8-symbolos 2023-12-28 14:47:19 +07:00
albexk e605f549bd Merge branch 'dev' into refactoring/android 2023-12-26 18:23:53 +03:00
albexk a961932b2e Refactor AndroidUtils 2023-12-26 17:41:49 +03:00
albexk e8cc80f046 Refactor Android open file method
Fix some bugs with mimetype filters when the Qt mimetype database does not match the Android database
2023-12-26 16:30:33 +03:00
vladimir.kuznetsov 67f29ac483 added conversion using the system locale 2023-12-26 13:36:21 +07:00
pokamest c9bde5cdc0 Merge pull request #479 from amnezia-vpn/feature/client-management-migrations
added migration from version 3 of client management to version 4
2023-12-25 22:00:13 -05:00
pokamest e878911819 Merge pull request #472 from amnezia-vpn/ksznak
Update amneziavpn_ru.ts
2023-12-25 13:36:03 -05:00
pokamest f1a0b7f0ef Merge pull request #473 from amnezia-vpn/bugfix/new-client-on-connection
fixed hang after creating configuration on connection
2023-12-25 12:21:44 -05:00
KsZnak 3e0a5104e7 Update amneziavpn_ru.ts 2023-12-25 19:18:23 +02:00
vladimir.kuznetsov 8f53d563a4 moved the client table for cloak and ss to the openvpn folder 2023-12-25 22:49:24 +07:00
pokamest 414740ffb7 Merge pull request #467 from amnezia-vpn/feature/full-access-last-config
full access config no longer contains the last_config field
2023-12-25 10:29:16 -05:00
albexk 7437d47d92 Remove unnecessary permission RECEIVE_BOOT_COMPLETED 2023-12-25 15:16:22 +03:00
vladimir.kuznetsov a68f19d72f added migration from version 3 of client management to version 4 2023-12-24 21:13:09 +07:00
Mykola Baibuz 8d3e21d46a Fix resolv-update script for MacOS (OpenVPN DNS)
script from https://github.com/andrewgdotcom/openvpn-mac-dns
2023-12-23 23:14:02 +02:00
pokamest 5ad54bfdc1 Merge pull request #452 from amnezia-vpn/refactoring/android
Android refactoring
2023-12-23 13:48:26 -05:00
pokamest 12fbc7d258 Merge pull request #474 from amnezia-vpn/bugfix/ss-in-cloak-container
returned shadowsocks to cloak container
2023-12-22 15:04:21 +00:00
albexk 164b7e2551 Merge branch 'dev' into refactoring/android 2023-12-22 15:38:29 +03:00
albexk eafac491d8 Add a stub for errors coming from Android
These errors are related to VPN connection errors
2023-12-22 15:35:24 +03:00
pokamest 3cfb6e968d Merge pull request #475 from amnezia-vpn/bugfix/default-server-full-access-sharing
added selection of a default server for full access sharing
2023-12-22 12:21:59 +00:00
albexk 375825125f Fix cloak config 2023-12-22 15:11:48 +03:00
vladimir.kuznetsov a8520e7545 added selection of a default server for full access sharing 2023-12-22 13:43:46 +07:00
vladimir.kuznetsov ac154cdd83 returned shadowsocks to cloak container 2023-12-22 13:08:53 +07:00
vladimir.kuznetsov 9290775ab5 added removal of last_config when revoke admin config on client management panel 2023-12-21 23:34:27 +07:00
pokamest d14e8cdee4 Merge pull request #460 from amnezia-vpn/bugfix/minor-ui-fixes
added an empty string check for the server name and user name change fields
2023-12-21 15:55:33 +00:00
vladimir.kuznetsov 7aac9f9d0e fixed hang after creating configuration on connection
- config created on connection is displayed as admin (platform name) on the client management page
- added config creation time on the client management page
2023-12-21 17:47:34 +07:00
KsZnak 41aaac7d32 Update amneziavpn_ru.ts 2023-12-20 20:16:35 +02:00
albexk c8d2399db9 Merge branch 'dev' into refactoring/android 2023-12-20 20:47:19 +03:00
KsZnak f37c8e5fd4 Update amneziavpn_ru.ts 2023-12-20 19:14:15 +02:00
pokamest 9f5025c10b Merge pull request #471 from amnezia-vpn/bugfix/macos_deploy_fix
build_macos.sh fix
2023-12-20 17:13:37 +00:00
pokamest c27d999c41 build_macos.sh fix 2023-12-20 08:39:43 -08:00
pokamest 9681bea237 Update ts files 2023-12-20 12:14:06 +00:00
pokamest 8905d6352c Merge pull request #465 from amnezia-vpn/persian_translation
added persian translation file and menu item
2023-12-20 12:07:51 +00:00
vladimir.kuznetsov 8599b20678 full access config no longer contains the last_config field 2023-12-18 13:17:39 +07:00
Morteza Sherafati 491f09a51b added persian translation file and menu item 2023-12-17 18:37:07 +00:00
pokamest 0f1519a21f Merge pull request #462 from amnezia-vpn/bugfix/service-containers-search
fixed server search for sftp, dns and tor containers
2023-12-17 16:53:52 +00:00
vladimir.kuznetsov b892156092 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD 2023-12-16 09:23:44 +07:00
vladimir.kuznetsov 7b1b8dc749 fixed server search for sftp, dns and tor containers 2023-12-15 13:58:30 +07:00
albexk 6d0167dcf3 Get back the ability to open configuration files
Doesn't work in all applications because some applications pass an abstract URI instead of the file path in the 'content' scheme
2023-12-14 22:10:22 +03:00
albexk 0c2d661e1c Disable ShadowSocks support on Android 2023-12-14 21:08:45 +03:00
albexk 95d1440d6f Some minor refactoring 2023-12-14 18:01:55 +03:00
albexk 0cabf60dc4 Fixes and refactoring in file saving and import functions 2023-12-14 18:00:58 +03:00
albexk 836ca1cc6b Switch to Qt fileprovider introduced in 6.6 2023-12-14 17:59:03 +03:00
pokamest be799daafe Merge pull request #431 from amnezia-vpn/re_second_adaptation_to_diff_os
Improve install_docker.sh
2023-12-14 05:27:29 -08:00
pokamest ad9d674a03 Merge pull request #368 from amnezia-vpn/feature/import-config-from-cloud
API support
2023-12-14 04:15:38 -08:00
vladimir.kuznetsov f52c3c430f added notification after config revokation 2023-12-14 11:03:27 +07:00
vladimir.kuznetsov a91ab0e910 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD 2023-12-13 14:21:51 +07:00
vladimir.kuznetsov 39d1f1677f fixed description update, after changing the default protocol 2023-12-13 14:14:37 +07:00
albexk b0dcae3586 Disable global split tunneling if a non-default route exists in the Wireguard configuration 2023-12-12 22:48:18 +03:00
vladimir.kuznetsov ed6351f8f1 added an empty string check for the server name and user name change fields 2023-12-12 17:15:10 +03:00
pokamest e486a2fb26 Merge pull request #443 from amnezia-vpn/feature/cancel-installation-button
added a button to cancel installation if the package manager on the server is busy
2023-12-12 05:17:40 -08:00
albexk 195bdb947e Refactor import config
Remove the path filter, as the content path may not contain a filename.
Disable import when viewing files.
Config can be imported from:
- shared file
- shared text
- vpn:// link
2023-12-11 22:56:01 +03:00
albexk 1576aed1ea Add network state listening and reconnection
Vpn reconnects when the default network is changed
2023-12-11 15:16:50 +03:00
vladimir.kuznetsov e66fbc3289 added default container installation, after downloading the config from the api 2023-12-11 13:42:42 +07:00
vladimir.kuznetsov b4c89ad58f Reworked the interaction between models. Now only serversModel directly interacts with server config 2023-12-08 13:50:03 +07:00
albexk 8cc5846808 Fix application hangs in disconnection state 2023-12-07 22:43:33 +03:00
albexk 2eaaf01ca1 Up AGP to version 8.2.0 2023-12-07 19:28:41 +03:00
albexk 67694c0f96 Fix abort error: 'Pure virtual function called!' 2023-12-06 18:25:11 +03:00
albexk 163e5b2c52 Fix for Qt Creator 2023-12-06 18:25:11 +03:00
albexk 508f1d3a42 Add service bind timeout 2023-12-06 18:24:52 +03:00
albexk d2207a5255 Up Gradle to version 8.5 2023-12-06 13:38:36 +03:00
albexk bf03f5c9ae Fix for Qt Creator 2023-12-05 23:53:49 +03:00
albexk 656223f57d Fix rebinding to the service 2023-12-05 16:57:53 +03:00
albexk dc6e3ec53b Add passing the VPN connection status when rebinding to the service 2023-12-05 16:10:29 +03:00
albexk 5835a756ce Add onError callback to handle errors in protocol threads 2023-12-05 13:56:01 +03:00
vladimir.kuznetsov f3f98a50ed fixed include path of servercontroller 2023-12-05 17:49:11 +07:00
vladimir.kuznetsov 0f4bb78712 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD 2023-12-05 17:38:53 +07:00
vladimir.kuznetsov c4014518cb renamed CloudController to ApiController 2023-12-05 17:38:38 +07:00
vladimir.kuznetsov 3605f62feb added support for the updated api 2023-12-05 17:28:14 +07:00
albexk 5c3e253067 Fix service description in AndroidManifest.xml 2023-12-05 13:09:28 +03:00
albexk 8d43cee52e Remove shadowsocks code 2023-12-04 18:45:53 +03:00
albexk 1e64413904 Fix disconnect bug 2023-12-04 18:23:08 +03:00
pokamest 6fd1ea26ee Merge pull request #438 from amnezia-vpn/bugfix/app-is-running-win11
fixed appProcessIsRunning() for win11
2023-12-01 03:24:49 -08:00
vladimir.kuznetsov e619fd4af9 replaced loader with PageSetupWizardInstalling when updating container settings 2023-12-01 14:16:27 +07:00
albexk e7658f9859 Add split tunneling 2023-12-01 00:12:50 +03:00
vladimir.kuznetsov 3defb09da9 added a button to cancel installation if the package manager on the server is busy 2023-11-30 19:21:57 +07:00
vladimir.kuznetsov a672434909 changed tasklist | findstr на tasklist 2023-11-30 07:13:43 +03:00
pokamest dd233f77fc Merge pull request #432 from amnezia-vpn/feature/client-management
added client management
2023-11-29 07:04:56 -08:00
vladimir.kuznetsov 02efd9c217 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/client-management 2023-11-29 17:26:26 +03:00
albexk 20f3c0388a Add sending statistics 2023-11-29 17:08:53 +03:00
albexk ef530780bd Fixes in AmneziaVpnService 2023-11-29 17:01:21 +03:00
albexk d7ec611ff4 Fix bugs in awg and wireguard protocols 2023-11-29 16:55:17 +03:00
pokamest b897e7102e Merge pull request #437 from amnezia-vpn/bugfix/minor-ui-fixes
Bugfix/minor UI fixes
2023-11-29 05:34:30 -08:00
pokamest 1cc5c5384e Merge pull request #407 from amnezia-vpn/feature/ss-and-cloak-native-configs
added native config generation for ss and cloak
2023-11-29 05:28:33 -08:00
vladimir.kuznetsov db602ac65b fixed ss string generation 2023-11-29 10:57:47 +07:00
albexk eaa209bc3a Add OpenVpn over Cloak module 2023-11-28 22:27:00 +03:00
albexk 51d4aea9e2 Add OpenVpn module 2023-11-28 20:07:39 +03:00
albexk 9738ada946 ProtocolApi refactoring, move network classes to NetworkUtils.kt 2023-11-28 19:47:22 +03:00
albexk 8ec105bee0 Move Log class to org.amnezia.vpn.util package 2023-11-28 19:07:32 +03:00
tiaga 4fd0852bb3 Improve install_docker.sh
- add delays before and after Docker activation
- cancel installation if `sudo` wasn't found
2023-11-27 21:47:54 +07:00
vladimir.kuznetsov a53e904f7b fixed appProcessIsRunning() for win11 2023-11-27 13:56:52 +07:00
vladimir.kuznetsov 2d22b52b5d limited client name length 2023-11-27 13:42:08 +07:00
vladimir.kuznetsov 426ac49f6f fixed "auto-connect" option 2023-11-27 12:46:59 +07:00
vladimir.kuznetsov c164814abd fixed default server setting after importing 2023-11-27 10:59:48 +07:00
vladimir.kuznetsov 3084892ed8 added selection of default server and container on the sharing page 2023-11-26 21:15:58 +07:00
albexk 9297f877c4 Add AWG module 2023-11-26 13:07:31 +03:00
vladimir.kuznetsov 1bf808c9ee fixed qr code generation for native configs 2023-11-25 13:02:02 +07:00
albexk 91f44fb394 Up Qt to version 6.6.1 2023-11-24 22:22:15 +03:00
albexk 385a52f676 Vpn service refactoring 2023-11-24 21:51:09 +03:00
albexk 8ef16781eb Remove old wireguard code 2023-11-24 21:49:54 +03:00
albexk ad5ea1ca44 Add IpcMessenger class 2023-11-24 17:10:08 +03:00
albexk 0ba5d754d5 Android Activity refactoring 2023-11-23 21:20:31 +03:00
albexk ccdcfdce8a Remove VPNPermissionHelper class 2023-11-23 16:49:32 +03:00
albexk 712fb4d0d3 Add Wireguard module 2023-11-23 16:45:15 +03:00
albexk de65a03998 Add ProtocolApi module 2023-11-23 16:03:52 +03:00
albexk 6d6710db4a Prefs refactoring 2023-11-23 14:19:51 +03:00
albexk c34c3e51ea Remove 'https://jitpack.io' repository 2023-11-23 14:13:38 +03:00
vladimir.kuznetsov 5dc3b64e0b added search bar for client management page 2023-11-23 14:54:49 +07:00
vladimir.kuznetsov e8ceeb6e20 added full access sharing 2023-11-23 00:04:06 +07:00
pokamest d38c7ce6a5 Error codes cleanup 2023-11-22 13:57:05 +00:00
albexk e625543b94 CameraActivity refactoring 2023-11-21 23:35:26 +03:00
albexk 679bd4e4c9 Get rid of AppCompat theme 2023-11-21 21:31:49 +03:00
vladimir.kuznetsov c6a312845a added client management 2023-11-21 20:31:53 +07:00
pokamest ef0530ec6b Merge pull request #420 from amnezia-vpn/adaptation_to_different_os
Improve logic of install_docker.sh
2023-11-17 11:51:58 -08:00
albexk 2c98a90d60 Move icons to mipmap folders 2023-11-17 15:30:13 +03:00
albexk b90fad6664 Android activity and AndroidController class refactoring 2023-11-17 15:10:11 +03:00
albexk 5a5ea4a018 Android project restructuring 2023-11-16 20:16:28 +03:00
albexk bc68c487ee Update to qt 6.6.0 2023-11-16 19:49:36 +03:00
albexk 617cdf14ad Log class refactoring 2023-11-16 15:30:44 +03:00
albexk f1c970461f Create utils module, move Log class there
BuildConfig class is now only created in the utils module
2023-11-16 15:15:02 +03:00
albexk 2fde47a86f Move qt binding java code to a separate module 2023-11-15 22:10:44 +03:00
albexk 4e5f2f44b6 Detach shadowsocks module 2023-11-15 22:08:00 +03:00
pokamest e8a2e54d05 Typo fix 2023-11-15 12:51:39 +00:00
albexk d77f3ecee8 Fix build error 2023-11-15 15:48:40 +03:00
albexk 06776ebe8f Fix errors 2023-11-14 23:19:46 +03:00
albexk e1eec55f62 Refactoring build
Move to gradle kotlin DSL
Use gradle version catalog
All android build parameters are set via cmake files
Use gradle abi split to build APKs
Improve local development in the android project folder
2023-11-14 23:18:59 +03:00
albexk fcabf08e74 Update gradle, fix gradlew.bat crlf 2023-11-14 23:13:14 +03:00
pokamest b4694313a0 Merge pull request #426 from amnezia-vpn/ios-build
Change Qt mirror for builds
2023-11-14 09:54:54 -08:00
tiaga abb2cae1f8 Change Qt mirror for builds
Use UC Berkeley mirror for installing Qt during a build. In addition, don't trigger builds on a tag push.
2023-11-14 23:39:15 +07:00
pokamest b0004fd9dc Version bump 2023-11-14 12:50:52 +00:00
tiaga 362a82f944 Improve logic of install_docker.sh
- check packages update only when it's required
- avoid `dnf/yum update` for RHEL-based systems
2023-11-14 16:57:16 +07:00
pokamest 19fe61ed29 Merge pull request #423 from amnezia-vpn/r2
Upload new versions to R2
2023-11-13 09:34:30 -08:00
tiaga 72de38b4fb Upload new versions to R2
A new GitHub Actions workflow for a tagged commit which uploads installers for a desktop version to Cloudflare R2.
2023-11-10 23:19:00 +07:00
pokamest 02c0f96e5e Merge pull request #418 from amnezia-vpn/feature/split-tunnel-dns-forwad
Use DNS over VPN for ForwardSites mode split tunnel
2023-11-07 06:35:43 -08:00
vladimir.kuznetsov aee82282ac Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/import-config-from-cloud 2023-11-06 14:10:43 +03:00
vladimir.kuznetsov 8497aeeb91 removed the debugging code 2023-11-06 14:10:31 +03:00
Mykola Baibuz 5e9f688000 Use DNS over VPN for ForwardSites mode split tunnel
This feature was in previous version of Split Tunnel
2023-11-04 15:28:59 -04:00
pokamest 6a7e346695 Merge pull request #416 from amnezia-vpn/bugfix/openvpn-exclude-route
Fix Split tunnel exclude sites mode for OpenVPN and Cloak. Windows.
2023-11-04 06:09:01 -07:00
Mykola Baibuz 071738116e Update Windows OpenVPN binary
This binary builded with ENABLE_DEBUG flag. This flag needed for ROUTE_GATEWAY varible output in log.
2023-11-03 17:29:40 -04:00
pokamest 147726ecb0 Merge branch 'dev' into feature/import-config-from-cloud 2023-11-01 21:42:07 +00:00
pokamest ae4ee6431d Merge pull request #409 from useribs/patch-2
Update servercontroller.cpp, replace 2 calls (shred ; rm)  with one
2023-11-01 12:23:14 -07:00
vladimir.kuznetsov 9cfcb714ae added native config generation for ss and cloak 2023-11-01 21:29:58 +05:00
pokamest d1ccde2a4b Merge pull request #396 from amnezia-vpn/bugfix/server-config-sync
bugfix/server config sync
2023-11-01 07:15:10 -07:00
useribs 4848091203 Update servercontroller.cpp, replace 2 calls (shred ; rm) with one (shred -u) 2023-10-30 20:09:13 +03:00
pokamest 282f159311 Merge pull request #402 from amnezia-vpn/bugfix/description_dns
Update DNS description
2023-10-29 09:07:42 -07:00
lunardunno 4ef8c77a2d Update DNS description 2023-10-29 17:56:10 +04:00
pokamest 08c1cf2439 Merge pull request #382 from amnezia-vpn/feature/split-tunnel-mobile
Split tunnel for missed Protocol/OS
2023-10-29 06:26:07 -07:00
Mykola Baibuz 2fc33875bb Bump version 2023-10-27 15:38:24 -04:00
Mykola Baibuz 9e92e4b5ff Merge branch 'dev' into feature/split-tunnel-mobile 2023-10-27 15:37:28 -04:00
pokamest 7f2cf70bf5 Merge pull request #393 from amnezia-vpn/bugfix/return-after-installation
fixed page return after installation
2023-10-26 12:40:39 -07:00
pokamest 40725d4155 Merge pull request #397 from amnezia-vpn/dev
Release 4.0.8
2023-10-26 11:45:11 -07:00
vladimir.kuznetsov 8164026891 fixed server config update, after container config change 2023-10-26 23:37:51 +05:00
Mykola Baibuz 0e23b3a1ac Allow traffic to Amezia DNS for all OS 2023-10-25 22:19:07 +03:00
Mykola Baibuz 1739d4861e Allow acces to Amnezia DNS when used only for selected sites 2023-10-25 21:50:35 +03:00
Mykola Baibuz a6b6e7850d Allow traffic for excluded route on Windows kill switch 2023-10-24 23:07:07 +03:00
Mykola Baibuz 3e9dea6f07 Remove some not implemented notification 2023-10-24 13:37:40 +03:00
Mykola Baibuz 1b37ca805f Cleanup debug stuff 2023-10-24 11:10:16 +03:00
Mykola Baibuz c772f56da7 Fixes after merge 2023-10-24 11:00:40 +03:00
Mykola Baibuz bc183e39bb Merge branch 'feature/split-tunnel-mobile' of github.com:amnezia-vpn/amnezia-client into feature/split-tunnel-mobile 2023-10-24 00:35:58 +03:00
Mykola Baibuz 306d4f70a8 Update NE Sources 2023-10-24 00:33:35 +03:00
Mykola Baibuz a386d39495 iOS Cloak/OVPN SplitTunnel 2023-10-24 00:28:41 +03:00
Mykola Baibuz 22b14dff5f iOS AWG/WG split tunnel 2023-10-23 22:42:02 +03:00
pokamest e749cc7578 Update amneziavpn_ru.ts
Typo fix
2023-10-23 20:32:28 +01:00
vladimir.kuznetsov 3e03002ead added getting cloud config for cloak 2023-10-23 23:55:01 +05:00
vladimir.kuznetsov 4ae9cddcce fixed a typo in the serverController include 2023-10-23 23:53:46 +05:00
vladimir.kuznetsov 16724645ce Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/import-config-from-cloud 2023-10-23 21:40:18 +05:00
vladimir.kuznetsov 6a12cad1c9 fixed page return after installation 2023-10-23 21:33:07 +05:00
Mykola Baibuz c15665803d Merge branch 'dev' into feature/split-tunnel-mobile 2023-10-22 15:26:20 -04:00
pokamest 97090888d5 Bump version 2023-10-22 08:11:37 -07:00
pokamest 4642308fbb Merge pull request #374 from amnezia-vpn/bugfix/split-tunneling
Bugfix/split tunneling
2023-10-22 08:02:43 -07:00
vladimir.kuznetsov 59bccb1188 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into bugfix/split-tunneling 2023-10-22 20:00:39 +05:00
pokamest cd8fc007ac Merge pull request #392 from amnezia-vpn/bugfix/existing-awg-container
added getting awg parameters when adding an already installed awg container
2023-10-22 07:49:34 -07:00
vladimir.kuznetsov 7cfb38307e removed re-processing of server config for awg 2023-10-22 18:04:34 +05:00
vladimir.kuznetsov 994aa32745 added getting awg parameters when adding an already installed awg container 2023-10-22 17:31:13 +05:00
Mykola Baibuz f0b872e86b Merge remote-tracking branch 'origin/bugfix/pull-awg-config' into feature/split-tunnel-mobile 2023-10-21 23:24:54 +03:00
Mykola Baibuz 0c33432436 Fix pulling exiting AWG config from server 2023-10-21 14:55:15 -04:00
pokamest 0bb4dd9442 Text and translations fixes 2023-10-21 18:32:30 +01:00
pokamest 7a54dc15da Update amneziavpn_ru.ts 2023-10-21 16:33:21 +01:00
pokamest e16a1100d8 Update amneziavpn_ru.ts 2023-10-21 16:20:57 +01:00
pokamest 99214e22e3 Fix docs url 2023-10-21 16:05:09 +01:00
pokamest c77d35a2ed Merge pull request #390 from amnezia-vpn/revert-370-feature/custom_drawer_component
Revert "added new drawer2type for replacing drawertype"
2023-10-21 06:21:07 -07:00
pokamest d98fdbdc5c Revert "added new drawer2type for replacing drawertype" 2023-10-21 14:17:45 +01:00
ronoaer 4551cf0a21 Merge pull request #370 from amnezia-vpn/feature/custom_drawer_component
added new drawer2type for replacing drawertype
2023-10-21 09:34:21 +08:00
ronoaer 023c3474d2 Merge branch 'dev' into feature/custom_drawer_component 2023-10-21 09:28:41 +08:00
pokamest 2a4cefb4bf Merge pull request #387 from amnezia-vpn/bugfix/awg-mtu-len-fix
Fix MTU len for Win WG/AWG
2023-10-20 15:02:29 -07:00
Mykola Baibuz 09305724fa Fix MTU len for Win WG/AWG 2023-10-20 16:44:30 -04:00
pokamest 360fda1ba7 Merge pull request #386 from amnezia-vpn/bugfix/minor-ui-fixes-4-version
Bugfix/minor UI fixes 4 version
2023-10-20 12:23:03 -07:00
vladimir.kuznetsov dadf0cf96e Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into dev 2023-10-20 21:51:40 +05:00
vladimir.kuznetsov 3d60ac751e removed the default protocol/server change if connected to VPN 2023-10-20 20:52:14 +05:00
pokamest 32793eef8c Merge pull request #385 from amnezia-vpn/bugfix/translated_new_source_strings_to_chinese
translated new source strings to chinese
2023-10-20 06:36:17 -07:00
ronoaer da1cdfd6fa translated new source strings to chinese 2023-10-20 18:01:57 +08:00
vladimir.kuznetsov 58ad7dc161 removed the "remove protocol" buttons from where they shouldn't be 2023-10-20 14:10:04 +05:00
ronoaer 0a15f44193 removed states 'opened', 'closed' 2023-10-20 10:38:12 +08:00
pokamest e1dec3c1ba Merge pull request #384 from amnezia-vpn/bugfix/startCentos7docker
Restoring autostart and enable docker for CentOS 7
2023-10-19 18:30:45 -07:00
pokamest 7834860245 Merge pull request #383 from amnezia-vpn/feature/awg-random-values
Feature/awg random values
2023-10-19 18:28:13 -07:00
pokamest 2da1025f26 Random port on install 2023-10-20 02:25:40 +01:00
Mykola Baibuz 78c83b2e21 Some logic fix 2023-10-19 17:03:24 -04:00
Mykola Baibuz 414a47e2f2 WG/AWG Desktop AllowedIP from plain WG config 2023-10-19 14:50:51 -04:00
ronoaer 6c78b4ec8f enabled drag-pagehome-drawer in tabBar 2023-10-19 23:01:03 +08:00
ronoaer a6949bd3ae resized questiondrawer of page serverdata 2023-10-19 19:45:22 +08:00
ronoaer f7bed04ab2 removed invalid function code 2023-10-19 19:32:15 +08:00
ronoaer 6ec773079c added hovering effect of button 2023-10-19 11:22:52 +08:00
ronoaer 366e27a321 re-adatped pagehome 2023-10-19 09:27:39 +08:00
Mykola Baibuz 32c304dc1b WG/AWG SplitTunnel for desktop 2023-10-18 17:44:28 -04:00
vladimir.kuznetsov 338499247d changed the display order of containers 2023-10-19 01:16:36 +05:00
vladimir.kuznetsov 79e1761c1f added generation of random values for awg parameters 2023-10-19 01:14:09 +05:00
Mykola Baibuz 4ea1a19572 Cleanup WG implementation 2023-10-18 13:41:58 -04:00
pokamest e2ae341ba9 AndroidManifest fix 2023-10-18 14:01:06 +01:00
pokamest de03435bac Merge pull request #381 from amnezia-vpn/bugfix/minor-ui-fixes-4-version
Bugfix/minor UI fixes 4 version
2023-10-18 04:05:18 -07:00
pokamest e16c425f87 PageHome.qml fix 2023-10-18 12:04:39 +01:00
ronoaer c461e00c5c keeping parent's cusorshape and Drawer2Type's close-animation 2023-10-18 16:17:57 +08:00
vladimir.kuznetsov fcf6bb43b7 Merge branch 'bugfix/split-tunneling' of github.com:amnezia-vpn/amnezia-client into bugfix/split-tunneling 2023-10-18 12:18:46 +05:00
vladimir.kuznetsov f5f72f87a6 fixed switcher status display for page split site tunneling 2023-10-18 12:17:24 +05:00
vladimir.kuznetsov 3340451245 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into bugfix/split-tunneling 2023-10-18 11:55:24 +05:00
Mykola Baibuz c14f1b5000 Android OpenVPN/Cloak Split tunnel 2023-10-17 16:39:56 -04:00
vladimir.kuznetsov a46e55d5c2 added a dash for drawerType 2023-10-18 01:11:41 +05:00
vladimir.kuznetsov 4b64bfaec0 fixed questionDrawer height 2023-10-18 00:37:15 +05:00
vladimir.kuznetsov 2f0c1eeecc fixed selection of default container after installing a new server 2023-10-18 00:36:40 +05:00
Mykola Baibuz 546d4c1d3d WG/AWG Android splitTunnel 2023-10-17 14:54:46 -04:00
lunardunno 160d88f002 Restoring autostart and enable docker for CentOS 7 2023-10-17 21:26:50 +04:00
ronoaer a83cd29f72 fixed the cursorShape, and some minor issues 2023-10-17 22:00:19 +08:00
pokamest 94304b5777 Version bump 2023-10-17 14:47:31 +01:00
pokamest 61ddfe01a1 macos build script updated [no ci] 2023-10-17 06:39:49 -07:00
pokamest 00d334f704 Merge pull request #377 from amnezia-vpn/bugfix/minor-ui-fixes-4-version
disabled the ability to change the protocol/server when a vpn connection is active
2023-10-17 05:39:51 -07:00
pokamest f4a4979997 Merge pull request #378 from amnezia-vpn/bugfix/updated_chinese_translations
updated Chinese translations for updating source strings
2023-10-17 05:11:19 -07:00
ronoaer 03171e4743 update background color and drag-effect, moved dulicated code 2023-10-17 19:34:34 +08:00
ronoaer 5369e68267 updated Chinese translations for updating source strings 2023-10-17 14:30:59 +08:00
vladimir.kuznetsov 9eb23e38bd disabled the ability to change the protocol/server when a vpn connection is active 2023-10-16 22:57:12 +05:00
Mykola Baibuz 2a0166bb26 Merge branch 'bugfix/split-tunneling' of https://github.com/amnezia-vpn/amnezia-client into bugfix/split-tunneling 2023-10-16 12:05:50 -04:00
Mykola Baibuz 2df612ec1f Android SplitTunnel 2023-10-16 12:05:35 -04:00
pokamest 36ba3758db Translation updates 2023-10-16 15:27:26 +01:00
ronoaer 7cc0f39d3c adapted pagehome by new custom drawer type 2023-10-16 22:21:01 +08:00
vladimir.kuznetsov 9cf5590371 disabled split site tunneling for awg 2023-10-16 15:17:09 +05:00
pokamest 81f835458f Merge pull request #375 from amnezia-vpn/bugfix/minor-ui-fixes-4-version
Bugfix/minor UI fixes 4 version
2023-10-16 03:10:53 -07:00
vladimir.kuznetsov e01b1db706 text corrections 2023-10-16 14:34:03 +05:00
vladimir.kuznetsov cdb18de305 brought back the ability to share wireguard native format configs 2023-10-16 13:43:27 +05:00
vladimir.kuznetsov 8e0eef3316 fixed selection of default container after installing a new container 2023-10-16 13:40:43 +05:00
vladimir.kuznetsov 221d45f564 fixed pageSettingsDns width 2023-10-16 13:32:56 +05:00
vladimir.kuznetsov 2a4a01a4be removed split site tunneling page blocking when switcher is turned off 2023-10-16 13:28:37 +05:00
Mykola Baibuz 501670bdd2 Merge branch 'feature/split-tunneling-config' into bugfix/split-tunneling 2023-10-15 15:10:05 -04:00
vladimir.kuznetsov 24637a1693 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD 2023-10-15 21:08:45 +05:00
vladimir.kuznetsov 7bd1340190 fixed display of sites on page split tunneling 2023-10-15 20:41:49 +05:00
ronoaer cb5c09d967 adapted questionDrawer 2023-10-15 21:29:01 +08:00
pokamest a01ba5909c Version bump 2023-10-15 12:53:44 +01:00
pokamest 1c4678af95 Merge pull request #373 from amnezia-vpn/fix/update_ru_ts
Updated ru ts #2
2023-10-15 04:43:04 -07:00
pokamest 5f5435c645 Updated ru ts 2023-10-15 12:41:01 +01:00
pokamest 2f7dc2c46c Merge pull request #372 from amnezia-vpn/fix/update_ru_ts
Update ru translation
2023-10-15 04:38:29 -07:00
pokamest 9bc1c9dd03 Merge branch 'dev' into fix/update_ru_ts 2023-10-15 12:30:13 +01:00
pokamest 4c81cdb4a2 Update translation 2023-10-15 12:29:41 +01:00
pokamest 3406ffa7a2 Merge pull request #371 from amnezia-vpn/bugfix/minor-ui-fixes-4-version
Minor UI fixes 4 version
2023-10-15 02:54:27 -07:00
pokamest 6d05b6845e VPN protocol descriptions updated 2023-10-15 10:53:09 +01:00
ronoaer 29b4966119 shown ConnectionTypeSelectionDrawer on top level alway 2023-10-15 17:34:35 +08:00
ronoaer d0f8358431 removed invalid code, and fixed top button hidden-shown 2023-10-15 17:29:22 +08:00
ronoaer a75bd07cd8 fixed the clicked event 2023-10-15 15:54:05 +08:00
ronoaer 8c1835950b added transparent-background, for blocking clicked event 2023-10-15 15:17:04 +08:00
pokamest c7cd8e4c80 Minor ui fixes and refactoring 2023-10-15 02:30:42 +01:00
pokamest f65e4066e3 ui fixes 2023-10-14 23:59:46 +01:00
vladimir.kuznetsov 37c18c5d3c Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into dev 2023-10-14 21:25:09 +05:00
vladimir.kuznetsov 8885f580b2 added notification after saving backup and logs files 2023-10-14 21:18:38 +05:00
vladimir.kuznetsov 512ac74ee6 temporarily disabled the drawer close button 2023-10-14 20:59:03 +05:00
ronoaer 384ce9853b added new drawer2type for replacing drawertype 2023-10-14 23:00:31 +08:00
pokamest b6d2030041 Ru translation 2023-10-14 15:55:52 +01:00
pokamest 3ac09181c6 Text lables fixes 2023-10-14 15:55:07 +01:00
vladimir.kuznetsov ffc9e5823a text corrections 2023-10-14 18:21:49 +05:00
vladimir.kuznetsov f5448fed59 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into dev 2023-10-14 16:58:14 +05:00
vladimir.kuznetsov 8163e51434 fixes on page split tunneling according to the design layout 2023-10-14 16:52:22 +05:00
pokamest 3836836c72 Change easySetupOrder 2023-10-14 02:15:49 +01:00
vladimir.kuznetsov b78bf39767 added split tunneling to the config 2023-10-13 15:45:06 +05:00
vladimir.kuznetsov 25f8283edd added getting the config from the cloud service 2023-10-12 20:48:03 +05:00
pokamest 7c8399ce88 Fix awg description 2023-10-12 13:57:58 +01:00
pokamest 9fe2a1dd41 Merge pull request #354 from amnezia-vpn/feature/amnezia-wireguard-client-impl
AWG protocol implementation
2023-10-12 03:39:59 -07:00
Nethius 846f554157 Merge pull request #366 from amnezia-vpn/bigfix/updated_translation_for_wg
updated translations for branch feature/amnezia-wireguard-client-impl
2023-10-12 15:44:12 +07:00
ronoaer d1f66cbf4d updated translations for branch feature/amnezia-wireguard-client-impl 2023-10-12 16:26:37 +08:00
vladimir.kuznetsov a4624c7377 removed the close button for the app for mobile platforms 2023-10-12 10:57:13 +05:00
pokamest 10435cea69 Tiny refactoring and text fixes 2023-10-12 01:15:05 +01:00
pokamest ce9a23e021 Merge branch 'dev' into feature/amnezia-wireguard-client-impl 2023-10-11 19:40:40 +01:00
pokamest 4b7c8f21c2 Merge pull request #364 from amnezia-vpn/bigfix/reset_topbutton_xposition
updated x position of topbutton  when resize window
2023-10-11 11:37:17 -07:00
pokamest 6ddebdbbd1 Merge pull request #365 from amnezia-vpn/bugfix/container-config-on-connect
fixed container config synchronization
2023-10-11 11:36:39 -07:00
pokamest d92729d346 Fix install_docker.sh 2023-10-11 15:30:55 +01:00
Mykola Baibuz fa06dbbd29 Bump Android verion 2023-10-10 08:52:36 -04:00
vladimir.kuznetsov 5d59a1a10e fixed an error when after the first connection with admin config the container model was not updated 2023-10-10 12:18:56 +03:00
vladimir.kuznetsov 222a251180 Merge branch 'feature/amnezia-wireguard-client-impl' of github.com:amnezia-vpn/amnezia-client into feature/amnezia-wireguard-client-impl 2023-10-10 14:16:02 +05:00
vladimir.kuznetsov 9d6559f0d7 fixed an error when after the first connection with admin config the container model was not updated 2023-10-10 12:50:41 +05:00
ronoaer da02f49850 update x value of topbutton when resize window 2023-10-10 08:43:56 +08:00
Mykola Baibuz 992961c488 Update Windows WG to AWG protocol support 2023-10-09 16:32:43 -04:00
vladimir.kuznetsov 0ce30a4e81 Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/amnezia-wireguard-client-impl 2023-10-09 23:19:48 +05:00
vladimir.kuznetsov bb2d794b6f corrections to the text 2023-10-09 23:18:24 +05:00
Nethius 45dc302de4 Merge pull request #362 from amnezia-vpn/bugfix/minor-ui-fixes-4-version
Bugfix/minor UI fixes 4 version
2023-10-10 01:12:57 +07:00
vladimir.kuznetsov 4a2706a9d9 increased the application version to 4.0.8.1 2023-10-09 23:00:53 +05:00
vladimir.kuznetsov 00be3c3ccc corrections to the text 2023-10-09 22:54:33 +05:00
vladimir.kuznetsov cb7fe50d46 added margins for picture with qr code 2023-10-09 22:40:06 +05:00
vladimir.kuznetsov d364dbac2c now when a new container is installed, it is selected as the default container 2023-10-09 22:39:32 +05:00
vladimir.kuznetsov 042788bec3 moved add new server button to main tabbar 2023-10-09 20:19:22 +05:00
Mykola Baibuz def261f578 Merge branch 'dev' into feature/amnezia-wireguard-client-impl 2023-10-09 11:00:37 -04:00
Mykola Baibuz c08e23085e Fix protocol change from AWG to WG for Android 2023-10-09 10:29:42 -04:00
vladimir.kuznetsov e01dd2bf57 added close application button in settings page 2023-10-09 19:16:06 +05:00
pokamest 61396ec82e Merge pull request #361 from amnezia-vpn/fix/android-accessibility
Disable android accessibility
2023-10-08 12:43:05 -07:00
albexk 357c283437 Disable android accessibility 2023-10-08 20:08:32 +03:00
Nethius 1b38cd6ca7 Merge pull request #360 from amnezia-vpn/bugfix/minor-ui-fixes-4-version
Bugfix/minor UI fixes 4 version
2023-10-08 23:15:34 +07:00
Mykola Baibuz bdfa8bfe5b AWG Android support 2023-10-07 09:01:29 -04:00
Mykola Baibuz 7f2ef65fe6 Update WG to AWG for Android 2023-10-06 17:20:41 -04:00
vladimir.kuznetsov 102d0472c7 Merge branch 'feature/amnezia-wireguard-client-impl' of github.com:amnezia-vpn/amnezia-client into HEAD 2023-10-06 22:06:50 +05:00
vladimir.kuznetsov 445fc6efb1 renamed amneziawireguard to awg in ios controller 2023-10-06 22:05:48 +05:00
pokamest 135726f177 Merge branch 'dev' into feature/amnezia-wireguard-client-impl 2023-10-06 14:22:45 +01:00
vladimir.kuznetsov 671ca0a66f renamed amneziawireguard to awg 2023-10-06 17:26:45 +05:00
vladimir.kuznetsov aa4a79934a renamed amenziawireguard to awg 2023-10-06 17:19:44 +05:00
vladimir.kuznetsov 16fc0617e4 renamed amneziawireguard files to awg 2023-10-06 17:02:28 +05:00
vladimir.kuznetsov 64a2f3f8bb Merge branch 'feature/amnezia-wireguard-client-impl' of github.com:amnezia-vpn/amnezia-client into HEAD 2023-10-06 16:44:58 +05:00
vladimir.kuznetsov b7a65343af added the ability to change awg parameters on the protocol settings page 2023-10-06 16:43:52 +05:00
Nethius 5c121ea48d Merge pull request #353 from amnezia-vpn/feature/added_i18n_for_v4
added i18n for v4
2023-10-06 11:49:17 +03:00
ronoaer 673f28ed64 retanslate donation way 2023-10-06 16:32:04 +08:00
ronoaer 3fb97d16bb updated about page 2023-10-06 15:49:48 +08:00
ronoaer 079c9176ef fixed minor issues of translation 2023-10-06 15:29:15 +08:00
ronoaer 9377a0b545 updated translated-text to connectStatusText in ConnectionController 2023-10-06 14:37:10 +08:00
ronoaer 1357c4a309 applied translation-funcation to SystemTray 2023-10-06 13:43:32 +08:00
Mykola Baibuz d77be5a244 Update iOS network extension 2023-10-06 00:38:54 +03:00
Mykola Baibuz 08863edb52 Update AWG iOS binary again 2023-10-05 17:11:40 -04:00
Mykola Baibuz 3a77705142 Update AWG binary 2023-10-05 15:55:32 -04:00
ronoaer 1eafa9a38a updated about and tor 2023-10-05 23:47:50 +08:00
vladimir.kuznetsov 396b7aac18 fixed display of amnezia dns description on main menu 2023-10-05 13:56:00 +05:00
ronoaer 08defbbbd8 updated original string format, for adapting multi-language 2023-10-05 13:26:11 +08:00
ronoaer 79d371fb76 translated pages from english to chinese 2023-10-05 00:54:49 +08:00
vladimir.kuznetsov 9df262d502 fixed sending parameters to the awg daemon for windows 2023-10-04 19:14:27 +03:00
pokamest 6f392ce126 Crash on exit fix for Windows 2023-10-04 16:09:03 +01:00
vladimir.kuznetsov a83ec10b61 updated description for full access sharing 2023-10-04 14:47:49 +05:00
vladimir.kuznetsov a93f75fb5a added full version to page about 2023-10-04 14:40:17 +05:00
ronoaer 2353cc4f2c translated sub-page of Settings to Chinese 2023-10-04 15:48:35 +08:00
ronoaer 30709c66ef translated settings page 2023-10-04 09:05:29 +08:00
ronoaer 27f770604b tried to translate some pages, from English to Chinese 2023-10-03 15:59:53 +08:00
vladimir.kuznetsov 6dbbf1fc89 added parsing parameters for windows 2023-10-02 18:48:11 +03:00
vladimir.kuznetsov c254f2fdc4 Merge branch 'feature/amnezia-wireguard-client-impl' of github.com:amnezia-vpn/desktop-client into feature/amnezia-wireguard-client-impl 2023-10-02 18:21:00 +03:00
vladimir.kuznetsov cf450fa4e4 Merge remote-tracking branch 'origin/feature/amnezia-wireguard-client-impl' into HEAD 2023-10-02 20:04:40 +05:00
vladimir.kuznetsov 304f29bfac returned 'address' to awg server config and set it to 10.8.1.1/24 2023-10-02 20:03:01 +05:00
vladimir.kuznetsov 50b8b3d649 added parsing of wireguard config parameters when importing native configs 2023-10-02 18:30:32 +05:00
vladimir.kuznetsov 39c2124a26 returned the awg setting via wg-quick 2023-10-01 21:43:30 +05:00
ronoaer eaede032b4 1. updated memory text when language changed,
2. updated initialize index
2023-10-01 11:12:27 +08:00
Mykola Baibuz 4ed153373f Fix Linux build, some naming changes 2023-09-30 16:05:23 -04:00
ronoaer 07d7fac490 removed invalid code 2023-09-30 17:40:26 +08:00
ronoaer 5535b6a6e3 embedded qm files into qrc file 2023-09-30 17:36:06 +08:00
Mykola Baibuz b7fbb84a58 iOS AWG protocol Setup 2023-09-30 00:58:08 +03:00
vladimir.kuznetsov 19bd94ed02 Merge branch 'feature/amnezia-wireguard-client-impl' of github.com:amnezia-vpn/amnezia-client into feature/amnezia-wireguard-client-impl 2023-09-29 18:42:45 +05:00
vladimir.kuznetsov 54b45a36e1 test configuration using wg instead of wg-quick to configure the server 2023-09-29 18:41:00 +05:00
Mykola Baibuz 2986a18c8f iOS AWG support 2023-09-28 23:54:32 +03:00
ronoaer 68095700a2 added i18n for v4 2023-09-28 23:21:13 +08:00
vladimir.kuznetsov 4cb871849b Merge remote-tracking branch 'remotes/origin/dev' into feature/amnezia-wireguard-client-impl 2023-09-28 00:26:26 +03:00
vladimir.kuznetsov 423305c35a moved the configuration of new parameters for awg to addInterface() 2023-09-28 02:14:07 +05:00
vladimir.kuznetsov b55313527e added passing new amneziawireguard config parameters over uapi for all platforms 2023-09-27 00:45:42 +05:00
vladimir.kuznetsov af53c456ea added passing new wireguard config parameters over uapi and configuring the amneziawireguard container 2023-09-27 00:40:01 +05:00
vladimir.kuznetsov 7284bb54bc Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/amnezia-wireguard-client-impl 2023-09-22 00:39:32 +05:00
vladimir.kuznetsov 6afdd8375d added models, classes and ui files for amnezia wireguard 2023-09-22 00:37:55 +05:00
pokamest 9090ec54e7 Merge pull request #339 from amnezia-vpn/dev
Release 3.1.0.1
2023-09-21 07:28:08 -07:00
394 changed files with 19095 additions and 87880 deletions
+1
View File
@@ -3,3 +3,4 @@ deploy/data/windows/x64/tap/windows_10/OemVista.inf eol=crlf
deploy/data/windows/x32/tap/windows_7/OemVista.inf eol=crlf
deploy/data/windows/x32/tap/windows_10/OemVista.inf eol=crlf
client/3rd/* linguist-vendored
client/android/gradlew.bat eol=crlf
+117 -55
View File
@@ -1,7 +1,12 @@
name: 'Deploy workflow'
on:
push:
branches:
- '**'
on: [push]
env:
QT_MIRROR: https://mirrors.ocf.berkeley.edu/qt/ # https://download.qt.io/static/mirrorlist/
jobs:
Build-Linux-Ubuntu:
@@ -25,7 +30,7 @@ jobs:
setup-python: 'true'
tools: 'tools_ifw'
set-env: 'true'
extra: '--external 7z'
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Get sources'
uses: actions/checkout@v3
@@ -43,14 +48,18 @@ jobs:
export QIF_BIN_DIR=${{ runner.temp }}/Qt/Tools/QtInstallerFramework/${{ env.QIF_VERSION }}/bin
bash deploy/build_linux.sh
- name: 'Pack installer'
run: cd deploy && tar -cf AmneziaVPN_Linux_Installer.tar AmneziaVPN_Linux_Installer.bin
- name: 'Upload installer artifact'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN_Linux_installer
path: deploy/AmneziaVPN_Linux_Installer
name: AmneziaVPN_Linux_installer.tar
path: deploy/AmneziaVPN_Linux_Installer.tar
retention-days: 7
- name: 'Upload unpacked artifact'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN_Linux_unpacked
path: deploy/AppDir
@@ -89,7 +98,7 @@ jobs:
setup-python: 'true'
tools: 'tools_ifw'
set-env: 'true'
extra: '--external 7z'
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Setup mvsc'
uses: ilammy/msvc-dev-cmd@v1
@@ -105,13 +114,14 @@ jobs:
call deploy\\build_windows.bat
- name: 'Upload installer artifact'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN_Windows_installer
path: AmneziaVPN_x${{ env.BUILD_ARCH }}.exe
retention-days: 7
- name: 'Upload unpacked artifact'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN_Windows_unpacked
path: deploy\\build_${{ env.BUILD_ARCH }}\\client\\Release
@@ -119,15 +129,14 @@ jobs:
# ------------------------------------------------------
Build-IOS:
name: 'Build-IOS'
Build-iOS:
name: 'Build-iOS'
runs-on: macos-12
env:
QT_VERSION: 6.5.2
steps:
# Just select XCode
- name: 'Setup xcode'
uses: maxim-lobanov/setup-xcode@v1
with:
@@ -143,6 +152,7 @@ jobs:
arch: 'clang_64'
dir: ${{ runner.temp }}
set-env: 'true'
extra: '--base ${{ env.QT_MIRROR }}'
- name: 'Install iOS Qt'
uses: jurplel/install-qt-action@v3
@@ -154,7 +164,7 @@ jobs:
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Install go'
uses: actions/setup-go@v3
@@ -174,7 +184,7 @@ jobs:
- name: 'Setup ccache'
uses: hendrikmuhs/ccache-action@v1.2
- name: Install dependencies
- name: 'Install dependencies'
run: pip install jsonschema jinja2
- name: 'Build project'
@@ -195,7 +205,7 @@ jobs:
IOS_NE_PROVISIONING_PROFILE: ${{ secrets.IOS_NE_PROVISIONING_PROFILE }}
# - name: 'Upload appstore .ipa and dSYMs to artifacts'
# uses: actions/upload-artifact@v3
# uses: actions/upload-artifact@v4
# with:
# name: app-store ipa & dsyms
# path: |
@@ -232,7 +242,7 @@ jobs:
setup-python: 'true'
tools: 'tools_ifw'
set-env: 'true'
extra: '--external 7z'
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Get sources'
uses: actions/checkout@v3
@@ -250,13 +260,14 @@ jobs:
bash deploy/build_macos.sh
- name: 'Upload installer artifact'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN_MacOS_installer
path: AmneziaVPN.dmg
retention-days: 7
- name: 'Upload unpacked artifact'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN_MacOS_unpacked
path: deploy/build/client/AmneziaVPN.app
@@ -268,21 +279,11 @@ jobs:
name: 'Build-Android'
runs-on: ubuntu-latest
strategy:
matrix:
include:
- abi: 'x86_64'
qt_arch: 'android_x86_64'
- abi: 'x86'
qt_arch: 'android_x86'
- abi: 'armeabi-v7a'
qt_arch: 'android_armv7'
- abi: 'arm64-v8a'
qt_arch: 'android_arm64_v8a'
env:
QT_VERSION: 6.5.2
ANDROID_BUILD_PLATFORM: android-33
ANDROID_BUILD_PLATFORM: android-34
QT_VERSION: 6.6.1
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
BUILD_AAB: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') }}
steps:
- name: 'Install desktop Qt'
@@ -292,29 +293,58 @@ jobs:
host: 'linux'
target: 'desktop'
arch: 'gcc_64'
modules: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
modules: ${{ env.QT_MODULES }}
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Install android Qt'
- name: 'Install android_x86_64 Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'android'
arch: ${{ matrix.qt_arch }}
modules: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
arch: 'android_x86_64'
modules: ${{ env.QT_MODULES }}
dir: ${{ runner.temp }}
setup-python: 'true'
set-env: 'true'
extra: '--external 7z'
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Install android_x86 Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'android'
arch: 'android_x86'
modules: ${{ env.QT_MODULES }}
dir: ${{ runner.temp }}
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Install android_armv7 Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'android'
arch: 'android_armv7'
modules: ${{ env.QT_MODULES }}
dir: ${{ runner.temp }}
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Install android_arm64_v8a Qt'
uses: jurplel/install-qt-action@v3
with:
version: ${{ env.QT_VERSION }}
host: 'linux'
target: 'android'
arch: 'android_arm64_v8a'
modules: ${{ env.QT_MODULES }}
dir: ${{ runner.temp }}
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Grant execute permission for qt-cmake'
shell: bash
run: |
chmod +x ${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/${{ matrix.qt_arch }}/bin/qt-cmake
chmod +x ${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/android_x86_64/bin/qt-cmake
- name: 'Get sources'
uses: actions/checkout@v3
@@ -328,15 +358,14 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'
java-version: '17'
cache: 'gradle'
- name: 'Setup Android NDK'
id: setup-ndk
uses: nttld/setup-ndk@v1
with:
ndk-version: 'r25c'
local-cache: 'true'
ndk-version: 'r26b'
- name: 'Decode keystore secret to file'
env:
@@ -349,16 +378,49 @@ jobs:
env:
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
QT_HOST_PATH: ${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64
QT_ANDROID_KEYSTORE_PATH: ${{ github.workspace }}/android.keystore
QT_ANDROID_KEYSTORE_ALIAS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_ALIAS }}
QT_ANDROID_KEYSTORE_STORE_PASS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_PASS }}
QT_ANDROID_KEYSTORE_KEY_PASS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_PASS }}
ANDROID_KEYSTORE_PATH: ${{ github.workspace }}/android.keystore
ANDROID_KEYSTORE_KEY_ALIAS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_ALIAS }}
ANDROID_KEYSTORE_KEY_PASS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_PASS }}
shell: bash
run: ./deploy/build_android.sh --apk ${{ matrix.abi }} --platform ${{ env.ANDROID_BUILD_PLATFORM }}
run: ./deploy/build_android.sh ${{ env.BUILD_AAB == 'true' && '--aab' || '' }} --apk all --build-platform ${{ env.ANDROID_BUILD_PLATFORM }}
- name: 'Upload apk'
uses: actions/upload-artifact@v3
- name: 'Upload x86_64 apk'
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN-android-${{ matrix.abi }}
path: deploy/build/AmneziaVPN-${{ matrix.abi }}-release-signed.apk
name: AmneziaVPN-android-x86_64
path: deploy/build/AmneziaVPN-x86_64-release.apk
compression-level: 0
retention-days: 7
- name: 'Upload x86 apk'
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN-android-x86
path: deploy/build/AmneziaVPN-x86-release.apk
compression-level: 0
retention-days: 7
- name: 'Upload arm64-v8a apk'
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN-android-arm64-v8a
path: deploy/build/AmneziaVPN-arm64-v8a-release.apk
compression-level: 0
retention-days: 7
- name: 'Upload armeabi-v7a apk'
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN-android-armeabi-v7a
path: deploy/build/AmneziaVPN-armeabi-v7a-release.apk
compression-level: 0
retention-days: 7
- name: 'Upload aab'
if: ${{ env.BUILD_AAB == 'true' }}
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN-android
path: deploy/build/AmneziaVPN-release.aab
compression-level: 0
retention-days: 7
+64
View File
@@ -0,0 +1,64 @@
name: 'Upload a new version'
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+.[0-9]+'
jobs:
upload:
runs-on: ubuntu-latest
name: upload
steps:
- name: Checkout CMakeLists.txt
uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
sparse-checkout: |
CMakeLists.txt
sparse-checkout-cone-mode: false
- name: Verify git tag
run: |
GIT_TAG=${{ github.ref_name }}
CMAKE_TAG=$(grep 'project.*VERSION' CMakeLists.txt | sed -E 's/.* ([0-9]+.[0-9]+.[0-9]+.[0-9]+)$/\1/')
if [[ "$GIT_TAG" == "$CMAKE_TAG" ]]; then
echo "Git tag ($GIT_TAG) and version in CMakeLists.txt ($CMAKE_TAG) are the same. Continuing..."
else
echo "Git tag ($GIT_TAG) and version in CMakeLists.txt ($CMAKE_TAG) are not the same! Cancelling..."
exit 1
fi
- name: Download artifacts from the "${{ github.ref_name }}" tag
uses: robinraju/release-downloader@v1.8
with:
tag: ${{ github.ref_name }}
fileName: "AmneziaVPN_(Linux_|)${{ github.ref_name }}*"
out-file-path: ${{ github.ref_name }}
- name: Upload beta version
uses: jakejarvis/s3-sync-action@master
if: contains(github.event.base_ref, 'dev')
with:
args: --include "AmneziaVPN*" --delete
env:
AWS_S3_BUCKET: updates
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_SECRET_ACCESS_KEY }}
AWS_S3_ENDPOINT: https://${{ vars.CF_ACCOUNT_ID }}.r2.cloudflarestorage.com
SOURCE_DIR: ${{ github.ref_name }}
DEST_DIR: beta/${{ github.ref_name }}
- name: Upload stable version
uses: jakejarvis/s3-sync-action@master
if: contains(github.event.base_ref, 'master')
with:
args: --include "AmneziaVPN*" --delete
env:
AWS_S3_BUCKET: updates
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_SECRET_ACCESS_KEY }}
AWS_S3_ENDPOINT: https://${{ vars.CF_ACCOUNT_ID }}.r2.cloudflarestorage.com
SOURCE_DIR: ${{ github.ref_name }}
DEST_DIR: stable/${{ github.ref_name }}
+3 -3
View File
@@ -1,6 +1,3 @@
[submodule "client/3rd/wireguard-apple"]
path = client/3rd/wireguard-apple
url = https://github.com/WireGuard/wireguard-apple
[submodule "client/3rd/OpenVPNAdapter"]
path = client/3rd/OpenVPNAdapter
url = https://github.com/amnezia-vpn/OpenVPNAdapter.git
@@ -25,3 +22,6 @@
[submodule "client/3rd-prebuilt"]
path = client/3rd-prebuilt
url = https://github.com/amnezia-vpn/3rd-prebuilt
[submodule "client/3rd/amneziawg-apple"]
path = client/3rd/amneziawg-apple
url = https://github.com/amnezia-vpn/amneziawg-apple
+2 -1
View File
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN)
project(${PROJECT} VERSION 4.0.7.1
project(${PROJECT} VERSION 4.2.1.0
DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/"
)
@@ -11,6 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(APP_ANDROID_VERSION_CODE 42)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux")
+12 -3
View File
@@ -36,7 +36,7 @@ AmneziaVPN uses a number of open source projects to work:
Make sure to pull all submodules after checking out the repo.
```bash
git submodule update --init
git submodule update --init --recursive
```
## Development
@@ -50,7 +50,15 @@ Look deploy folder for build scripts.
1. First, make sure you have [XCode](https://developer.apple.com/xcode/) installed, at least version 14 or higher.
2. We use QT to generate the XCode project. we need QT version 6.4. Install QT for macos in [here](https://doc.qt.io/qt-6/macos.html)
2. We use QT to generate the XCode project. we need QT version 6.6.1. Install QT for macos in [here](https://doc.qt.io/qt-6/macos.html) or [QT Online Installer](https://www.qt.io/download-open-source). Required modules:
- macOS
- iOS
- Qt 5 Compatibility Module
- Qt Shader Tools
- Additional Libraries:
- Qt Image Formats
- Qt Multimedia
- Qt Remote Objects
3. Install cmake is require. We recommend cmake version 3.25. You can install cmake in [here](https://cmake.org/download/)
@@ -66,10 +74,11 @@ gomobile init
5. Build project
```bash
export QT_BIN_DIR="<PATH-TO-QT-FOLDER>/Qt/<QT-VERSION>/ios/bin"
export QT_MACOS_ROOT_DIR="<PATH-TO-QT-FOLDER>/Qt/<QT-VERSION>/macos"
export QT_IOS_BIN=$QT_BIN_DIR
export PATH=$PATH:~/go/bin
mkdir build-ios
$QT_IOS_BIN/qt-cmake . -B build-ios -GXcode -DQT_HOST_PATH=$QT_BIN_DIR
$QT_IOS_BIN/qt-cmake . -B build-ios -GXcode -DQT_HOST_PATH=$QT_MACOS_ROOT_DIR
```
Replace PATH-TO-QT-FOLDER and QT-VERSION to your environment
Vendored Submodule
+1
+26 -5
View File
@@ -50,12 +50,31 @@ endif()
qt6_add_resources(QRC ${QRC} ${CMAKE_CURRENT_LIST_DIR}/resources.qrc)
qt6_add_translations(${PROJECT} TS_FILES
# -- i18n begin
set(CMAKE_AUTORCC ON)
set(AMNEZIAVPN_TS_FILES
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru.ts
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_zh_CN.ts
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_fa_IR.ts
)
file(GLOB_RECURSE AMNEZIAVPN_TS_SOURCES *.qrc *.cpp *.h *.ui)
qt_create_translation(AMNEZIAVPN_QM_FILES ${AMNEZIAVPN_TS_SOURCES} ${AMNEZIAVPN_TS_FILES})
set(QM_FILE_LIST "")
foreach(FILE ${AMNEZIAVPN_QM_FILES})
get_filename_component(QM_FILE_NAME ${FILE} NAME)
list(APPEND QM_FILE_LIST "<file>${QM_FILE_NAME}</file>")
endforeach()
string(REPLACE ";" "" QM_FILE_LIST ${QM_FILE_LIST})
configure_file(${CMAKE_CURRENT_LIST_DIR}/translations/translations.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc)
qt6_add_resources(QRC ${I18NQRC} ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc)
# -- i18n end
if(IOS)
#execute_process(COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/scripts/run-build-cloak.sh)
execute_process(COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/ios/scripts/openvpn.sh args
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
endif()
@@ -89,7 +108,7 @@ set(HEADERS ${HEADERS}
${CMAKE_CURRENT_LIST_DIR}/core/errorstrings.h
${CMAKE_CURRENT_LIST_DIR}/core/scripts_registry.h
${CMAKE_CURRENT_LIST_DIR}/core/server_defs.h
${CMAKE_CURRENT_LIST_DIR}/core/servercontroller.h
${CMAKE_CURRENT_LIST_DIR}/core/controllers/serverController.h
${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h
${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.h
${CMAKE_CURRENT_LIST_DIR}/ui/notificationhandler.h
@@ -128,7 +147,7 @@ set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/core/errorstrings.cpp
${CMAKE_CURRENT_LIST_DIR}/core/scripts_registry.cpp
${CMAKE_CURRENT_LIST_DIR}/core/server_defs.cpp
${CMAKE_CURRENT_LIST_DIR}/core/servercontroller.cpp
${CMAKE_CURRENT_LIST_DIR}/core/controllers/serverController.cpp
${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.cpp
${CMAKE_CURRENT_LIST_DIR}/ui/notificationhandler.cpp
${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.cpp
@@ -263,6 +282,7 @@ if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.h
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.h
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.h
${CMAKE_CURRENT_LIST_DIR}/protocols/awgprotocol.h
)
set(SOURCES ${SOURCES}
@@ -273,6 +293,7 @@ if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.cpp
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.cpp
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.cpp
${CMAKE_CURRENT_LIST_DIR}/protocols/awgprotocol.cpp
)
endif()
@@ -322,5 +343,5 @@ if(NOT IOS AND NOT ANDROID)
endif()
target_sources(${PROJECT} PRIVATE ${SOURCES} ${HEADERS} ${RESOURCES} ${QRC})
target_sources(${PROJECT} PRIVATE ${SOURCES} ${HEADERS} ${RESOURCES} ${QRC} ${I18NQRC})
qt_finalize_target(${PROJECT})
+389 -367
View File
@@ -1,367 +1,389 @@
#include "amnezia_application.h"
#include <QClipboard>
#include <QFontDatabase>
#include <QMimeData>
#include <QQuickStyle>
#include <QResource>
#include <QStandardPaths>
#include <QTextDocument>
#include <QTimer>
#include <QTranslator>
#include <QQuickItem>
#include "logger.h"
#include "version.h"
#include "platforms/ios/QRCodeReaderBase.h"
#if defined(Q_OS_ANDROID)
#include "platforms/android/android_controller.h"
#endif
#include "protocols/qml_register_protocols.h"
#if defined(Q_OS_IOS)
#include "platforms/ios/ios_controller.h"
#endif
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
AmneziaApplication::AmneziaApplication(int &argc, char *argv[]) : AMNEZIA_BASE_CLASS(argc, argv)
#else
AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary, SingleApplication::Options options,
int timeout, const QString &userData)
: SingleApplication(argc, argv, allowSecondary, options, timeout, userData)
#endif
{
setQuitOnLastWindowClosed(false);
// Fix config file permissions
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
{
QSettings s(ORGANIZATION_NAME, APPLICATION_NAME);
s.setValue("permFixed", true);
}
QString configLoc1 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/"
+ ORGANIZATION_NAME + "/" + APPLICATION_NAME + ".conf";
QFile::setPermissions(configLoc1, QFileDevice::ReadOwner | QFileDevice::WriteOwner);
QString configLoc2 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/"
+ ORGANIZATION_NAME + "/" + APPLICATION_NAME + "/" + APPLICATION_NAME + ".conf";
QFile::setPermissions(configLoc2, QFileDevice::ReadOwner | QFileDevice::WriteOwner);
#endif
m_settings = std::shared_ptr<Settings>(new Settings);
}
AmneziaApplication::~AmneziaApplication()
{
m_vpnConnectionThread.quit();
m_vpnConnectionThread.wait(3000);
if (m_engine) {
QObject::disconnect(m_engine, 0, 0, 0);
delete m_engine;
}
}
void AmneziaApplication::init()
{
m_engine = new QQmlApplicationEngine;
const QUrl url(QStringLiteral("qrc:/ui/qml/main2.qml"));
QObject::connect(
m_engine, &QQmlApplicationEngine::objectCreated, this,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
m_engine->rootContext()->setContextProperty("Debug", &Logger::Instance());
m_configurator = std::shared_ptr<VpnConfigurator>(new VpnConfigurator(m_settings, this));
m_vpnConnection.reset(new VpnConnection(m_settings, m_configurator));
m_vpnConnection->moveToThread(&m_vpnConnectionThread);
m_vpnConnectionThread.start();
initModels();
initControllers();
#ifdef Q_OS_ANDROID
connect(AndroidController::instance(), &AndroidController::initialized, this,
[this](bool status, bool connected, const QDateTime &connectionDate) {
if (connected) {
m_connectionController->onConnectionStateChanged(Vpn::ConnectionState::Connected);
if (m_vpnConnection)
m_vpnConnection->restoreConnection();
}
});
if (!AndroidController::instance()->initialize()) {
qCritical() << QString("Init failed");
if (m_vpnConnection)
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Error);
return;
}
connect(AndroidController::instance(), &AndroidController::importConfigFromOutside, [this](QString data) {
m_pageController->replaceStartPage();
m_importController->extractConfigFromData(data);
m_pageController->goToPageViewConfig();
});
#endif
#ifdef Q_OS_IOS
IosController::Instance()->initialize();
connect(IosController::Instance(), &IosController::importConfigFromOutside, [this](QString data) {
m_pageController->replaceStartPage();
m_importController->extractConfigFromData(data);
m_pageController->goToPageViewConfig();
});
connect(IosController::Instance(), &IosController::importBackupFromOutside, [this](QString filePath) {
m_pageController->replaceStartPage();
m_pageController->goToPageSettingsBackup();
m_settingsController->importBackupFromOutside(filePath);
});
#endif
m_notificationHandler.reset(NotificationHandler::create(nullptr));
connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, m_notificationHandler.get(),
&NotificationHandler::setConnectionState);
connect(m_notificationHandler.get(), &NotificationHandler::raiseRequested, m_pageController.get(),
&PageController::raiseMainWindow);
connect(m_notificationHandler.get(), &NotificationHandler::connectRequested, m_connectionController.get(),
&ConnectionController::openConnection);
connect(m_notificationHandler.get(), &NotificationHandler::disconnectRequested, m_connectionController.get(),
&ConnectionController::closeConnection);
m_engine->load(url);
m_systemController->setQmlRoot(m_engine->rootObjects().value(0));
if (m_settings->isSaveLogs()) {
if (!Logger::init()) {
qWarning() << "Initialization of debug subsystem failed";
}
}
#ifdef Q_OS_WIN
if (m_parser.isSet("a"))
m_pageController->showOnStartup();
else
emit m_pageController->raiseMainWindow();
#else
m_pageController->showOnStartup();
#endif
// TODO - fix
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
if (isPrimary()) {
QObject::connect(this, &SingleApplication::instanceStarted, m_pageController.get(), [this]() {
qDebug() << "Secondary instance started, showing this window instead";
emit m_pageController->raiseMainWindow();
});
}
#endif
// Android TextField clipboard workaround
// https://bugreports.qt.io/browse/QTBUG-113461
#ifdef Q_OS_ANDROID
QObject::connect(qApp, &QGuiApplication::applicationStateChanged, [](Qt::ApplicationState state) {
if (state == Qt::ApplicationActive) {
if (qApp->clipboard()->mimeData()->formats().contains("text/html")) {
QTextDocument doc;
doc.setHtml(qApp->clipboard()->mimeData()->html());
qApp->clipboard()->setText(doc.toPlainText());
}
}
});
#endif
}
void AmneziaApplication::registerTypes()
{
qRegisterMetaType<ServerCredentials>("ServerCredentials");
qRegisterMetaType<DockerContainer>("DockerContainer");
qRegisterMetaType<TransportProto>("TransportProto");
qRegisterMetaType<Proto>("Proto");
qRegisterMetaType<ServiceType>("ServiceType");
declareQmlProtocolEnum();
declareQmlContainerEnum();
qmlRegisterType<QRCodeReader>("QRCodeReader", 1, 0, "QRCodeReader");
m_containerProps.reset(new ContainerProps());
qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", m_containerProps.get());
m_protocolProps.reset(new ProtocolProps());
qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", m_protocolProps.get());
qmlRegisterSingletonType(QUrl("qrc:/ui/qml/Filters/ContainersModelFilters.qml"), "ContainersModelFilters", 1, 0,
"ContainersModelFilters");
//
Vpn::declareQmlVpnConnectionStateEnum();
PageLoader::declareQmlPageEnum();
}
void AmneziaApplication::loadFonts()
{
QQuickStyle::setStyle("Basic");
QFontDatabase::addApplicationFont(":/fonts/pt-root-ui_vf.ttf");
}
void AmneziaApplication::loadTranslator()
{
auto locale = m_settings->getAppLanguage();
m_translator.reset(new QTranslator());
if (locale != QLocale::English) {
if (m_translator->load(locale, QString("amneziavpn"), QLatin1String("_"), QLatin1String(":/i18n"))) {
if (QCoreApplication::installTranslator(m_translator.get())) {
m_settings->setAppLanguage(locale);
}
}
}
}
void AmneziaApplication::updateTranslator(const QLocale &locale)
{
QResource::registerResource(":/translations.qrc");
if (!m_translator->isEmpty())
QCoreApplication::removeTranslator(m_translator.get());
if (locale == QLocale::English) {
m_settings->setAppLanguage(locale);
m_engine->retranslate();
}
if (m_translator->load(locale, QString("amneziavpn"), QLatin1String("_"), QLatin1String(":/i18n"))) {
if (QCoreApplication::installTranslator(m_translator.get())) {
m_settings->setAppLanguage(locale);
}
m_engine->retranslate();
}
emit translationsUpdated();
}
bool AmneziaApplication::parseCommands()
{
m_parser.setApplicationDescription(APPLICATION_NAME);
m_parser.addHelpOption();
m_parser.addVersionOption();
QCommandLineOption c_autostart { { "a", "autostart" }, "System autostart" };
m_parser.addOption(c_autostart);
QCommandLineOption c_cleanup { { "c", "cleanup" }, "Cleanup logs" };
m_parser.addOption(c_cleanup);
m_parser.process(*this);
if (m_parser.isSet(c_cleanup)) {
Logger::cleanUp();
QTimer::singleShot(100, this, [this] { quit(); });
exec();
return false;
}
return true;
}
QQmlApplicationEngine *AmneziaApplication::qmlEngine() const
{
return m_engine;
}
void AmneziaApplication::initModels()
{
m_containersModel.reset(new ContainersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
m_serversModel.reset(new ServersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
connect(m_serversModel.get(), &ServersModel::currentlyProcessedServerIndexChanged, m_containersModel.get(),
&ContainersModel::setCurrentlyProcessedServerIndex);
m_languageModel.reset(new LanguageModel(m_settings, this));
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
connect(m_languageModel.get(), &LanguageModel::updateTranslations, this, &AmneziaApplication::updateTranslator);
connect(this, &AmneziaApplication::translationsUpdated, m_languageModel.get(), &LanguageModel::translationsUpdated);
m_sitesModel.reset(new SitesModel(m_settings, this));
m_engine->rootContext()->setContextProperty("SitesModel", m_sitesModel.get());
connect(m_containersModel.get(), &ContainersModel::defaultContainerChanged, this, [this]() {
if (m_containersModel->getDefaultContainer() == DockerContainer::WireGuard
&& m_sitesModel->getRouteMode() != Settings::RouteMode::VpnAllSites) {
m_sitesModel->setRouteMode(Settings::RouteMode::VpnAllSites);
emit m_pageController->showNotificationMessage(
tr("Split tunneling for WireGuard is not implemented, the option was disabled"));
}
});
m_protocolsModel.reset(new ProtocolsModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get());
m_openVpnConfigModel.reset(new OpenVpnConfigModel(this));
m_engine->rootContext()->setContextProperty("OpenVpnConfigModel", m_openVpnConfigModel.get());
m_shadowSocksConfigModel.reset(new ShadowSocksConfigModel(this));
m_engine->rootContext()->setContextProperty("ShadowSocksConfigModel", m_shadowSocksConfigModel.get());
m_cloakConfigModel.reset(new CloakConfigModel(this));
m_engine->rootContext()->setContextProperty("CloakConfigModel", m_cloakConfigModel.get());
m_wireguardConfigModel.reset(new WireGuardConfigModel(this));
m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireguardConfigModel.get());
#ifdef Q_OS_WINDOWS
m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this));
m_engine->rootContext()->setContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel.get());
#endif
m_sftpConfigModel.reset(new SftpConfigModel(this));
m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get());
}
void AmneziaApplication::initControllers()
{
m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel, m_vpnConnection));
m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get());
m_pageController.reset(new PageController(m_serversModel, m_settings));
m_engine->rootContext()->setContextProperty("PageController", m_pageController.get());
m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, m_settings));
m_engine->rootContext()->setContextProperty("InstallController", m_installController.get());
connect(m_installController.get(), &InstallController::passphraseRequestStarted, m_pageController.get(),
&PageController::showPassphraseRequestDrawer);
connect(m_pageController.get(), &PageController::passphraseRequestDrawerClosed, m_installController.get(),
&InstallController::setEncryptedPassphrase);
connect(m_installController.get(), &InstallController::currentContainerUpdated, m_connectionController.get(),
&ConnectionController::onCurrentContainerUpdated);
m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings));
m_engine->rootContext()->setContextProperty("ImportController", m_importController.get());
m_exportController.reset(new ExportController(m_serversModel, m_containersModel, m_settings, m_configurator));
m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get());
m_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_settings));
m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get());
if (m_settingsController->isAutoStartEnabled() && m_serversModel->getDefaultServerIndex() >= 0) {
QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); });
}
m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel));
m_engine->rootContext()->setContextProperty("SitesController", m_sitesController.get());
m_systemController.reset(new SystemController(m_settings));
m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get());
}
#include "amnezia_application.h"
#include <QClipboard>
#include <QFontDatabase>
#include <QMimeData>
#include <QQuickStyle>
#include <QResource>
#include <QStandardPaths>
#include <QTextDocument>
#include <QTimer>
#include <QTranslator>
#include <QQuickItem>
#include "logger.h"
#include "version.h"
#include "platforms/ios/QRCodeReaderBase.h"
#if defined(Q_OS_ANDROID)
#include "platforms/android/android_controller.h"
#endif
#include "protocols/qml_register_protocols.h"
#if defined(Q_OS_IOS)
#include "platforms/ios/ios_controller.h"
#endif
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
AmneziaApplication::AmneziaApplication(int &argc, char *argv[]) : AMNEZIA_BASE_CLASS(argc, argv)
#else
AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary, SingleApplication::Options options,
int timeout, const QString &userData)
: SingleApplication(argc, argv, allowSecondary, options, timeout, userData)
#endif
{
setQuitOnLastWindowClosed(false);
// Fix config file permissions
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
{
QSettings s(ORGANIZATION_NAME, APPLICATION_NAME);
s.setValue("permFixed", true);
}
QString configLoc1 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/"
+ ORGANIZATION_NAME + "/" + APPLICATION_NAME + ".conf";
QFile::setPermissions(configLoc1, QFileDevice::ReadOwner | QFileDevice::WriteOwner);
QString configLoc2 = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first() + "/"
+ ORGANIZATION_NAME + "/" + APPLICATION_NAME + "/" + APPLICATION_NAME + ".conf";
QFile::setPermissions(configLoc2, QFileDevice::ReadOwner | QFileDevice::WriteOwner);
#endif
m_settings = std::shared_ptr<Settings>(new Settings);
}
AmneziaApplication::~AmneziaApplication()
{
m_vpnConnectionThread.quit();
m_vpnConnectionThread.wait(3000);
if (m_engine) {
QObject::disconnect(m_engine, 0, 0, 0);
delete m_engine;
}
}
void AmneziaApplication::init()
{
m_engine = new QQmlApplicationEngine;
const QUrl url(QStringLiteral("qrc:/ui/qml/main2.qml"));
QObject::connect(
m_engine, &QQmlApplicationEngine::objectCreated, this,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
m_engine->rootContext()->setContextProperty("Debug", &Logger::Instance());
m_configurator = std::shared_ptr<VpnConfigurator>(new VpnConfigurator(m_settings, this));
m_vpnConnection.reset(new VpnConnection(m_settings, m_configurator));
m_vpnConnection->moveToThread(&m_vpnConnectionThread);
m_vpnConnectionThread.start();
initModels();
loadTranslator();
initControllers();
#ifdef Q_OS_ANDROID
if(!AndroidController::initLogging()) {
qFatal("Android logging initialization failed");
}
AndroidController::instance()->setSaveLogs(m_settings->isSaveLogs());
connect(m_settings.get(), &Settings::saveLogsChanged,
AndroidController::instance(), &AndroidController::setSaveLogs);
connect(AndroidController::instance(), &AndroidController::initConnectionState, this,
[this](Vpn::ConnectionState state) {
m_connectionController->onConnectionStateChanged(state);
if (m_vpnConnection)
m_vpnConnection->restoreConnection();
});
if (!AndroidController::instance()->initialize()) {
qFatal("Android controller initialization failed");
}
connect(AndroidController::instance(), &AndroidController::importConfigFromOutside, [this](QString data) {
m_pageController->replaceStartPage();
m_importController->extractConfigFromData(data);
m_pageController->goToPageViewConfig();
});
#endif
#ifdef Q_OS_IOS
IosController::Instance()->initialize();
connect(IosController::Instance(), &IosController::importConfigFromOutside, [this](QString data) {
m_pageController->replaceStartPage();
m_importController->extractConfigFromData(data);
m_pageController->goToPageViewConfig();
});
connect(IosController::Instance(), &IosController::importBackupFromOutside, [this](QString filePath) {
m_pageController->replaceStartPage();
m_pageController->goToPageSettingsBackup();
m_settingsController->importBackupFromOutside(filePath);
});
#endif
m_notificationHandler.reset(NotificationHandler::create(nullptr));
connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, m_notificationHandler.get(),
&NotificationHandler::setConnectionState);
connect(m_notificationHandler.get(), &NotificationHandler::raiseRequested, m_pageController.get(),
&PageController::raiseMainWindow);
connect(m_notificationHandler.get(), &NotificationHandler::connectRequested, m_connectionController.get(),
&ConnectionController::openConnection);
connect(m_notificationHandler.get(), &NotificationHandler::disconnectRequested, m_connectionController.get(),
&ConnectionController::closeConnection);
connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(),
&NotificationHandler::onTranslationsUpdated);
m_engine->load(url);
m_systemController->setQmlRoot(m_engine->rootObjects().value(0));
#ifndef Q_OS_ANDROID
if (m_settings->isSaveLogs()) {
if (!Logger::init()) {
qWarning() << "Initialization of debug subsystem failed";
}
}
#endif
#ifdef Q_OS_WIN
if (m_parser.isSet("a"))
m_pageController->showOnStartup();
else
emit m_pageController->raiseMainWindow();
#else
m_pageController->showOnStartup();
#endif
// TODO - fix
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
if (isPrimary()) {
QObject::connect(this, &SingleApplication::instanceStarted, m_pageController.get(), [this]() {
qDebug() << "Secondary instance started, showing this window instead";
emit m_pageController->raiseMainWindow();
});
}
#endif
// Android TextArea clipboard workaround
// Text from TextArea always has "text/html" mime-type:
// /qt/6.6.1/Src/qtdeclarative/src/quick/items/qquicktextcontrol.cpp:1865
// Next, html is created for this mime-type:
// /qt/6.6.1/Src/qtdeclarative/src/quick/items/qquicktextcontrol.cpp:1885
// And this html goes to the Androids clipboard, i.e. text from TextArea is always copied as richText:
// /qt/6.6.1/Src/qtbase/src/plugins/platforms/android/androidjniclipboard.cpp:46
// So we catch all the copies to the clipboard and clear them from "text/html"
#ifdef Q_OS_ANDROID
connect(QGuiApplication::clipboard(), &QClipboard::dataChanged, []() {
auto clipboard = QGuiApplication::clipboard();
if (clipboard->mimeData()->hasHtml()) {
clipboard->setText(clipboard->text());
}
});
#endif
}
void AmneziaApplication::registerTypes()
{
qRegisterMetaType<ServerCredentials>("ServerCredentials");
qRegisterMetaType<DockerContainer>("DockerContainer");
qRegisterMetaType<TransportProto>("TransportProto");
qRegisterMetaType<Proto>("Proto");
qRegisterMetaType<ServiceType>("ServiceType");
declareQmlProtocolEnum();
declareQmlContainerEnum();
qmlRegisterType<QRCodeReader>("QRCodeReader", 1, 0, "QRCodeReader");
m_containerProps.reset(new ContainerProps());
qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", m_containerProps.get());
m_protocolProps.reset(new ProtocolProps());
qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", m_protocolProps.get());
qmlRegisterSingletonType(QUrl("qrc:/ui/qml/Filters/ContainersModelFilters.qml"), "ContainersModelFilters", 1, 0,
"ContainersModelFilters");
//
Vpn::declareQmlVpnConnectionStateEnum();
PageLoader::declareQmlPageEnum();
}
void AmneziaApplication::loadFonts()
{
QQuickStyle::setStyle("Basic");
QFontDatabase::addApplicationFont(":/fonts/pt-root-ui_vf.ttf");
}
void AmneziaApplication::loadTranslator()
{
auto locale = m_settings->getAppLanguage();
m_translator.reset(new QTranslator());
updateTranslator(locale);
}
void AmneziaApplication::updateTranslator(const QLocale &locale)
{
if (!m_translator->isEmpty()) {
QCoreApplication::removeTranslator(m_translator.get());
}
QString strFileName = QString(":/translations/amneziavpn") + QLatin1String("_") + locale.name() + ".qm";
if (m_translator->load(strFileName)) {
if (QCoreApplication::installTranslator(m_translator.get())) {
m_settings->setAppLanguage(locale);
}
} else {
m_settings->setAppLanguage(QLocale::English);
}
m_engine->retranslate();
emit translationsUpdated();
}
bool AmneziaApplication::parseCommands()
{
m_parser.setApplicationDescription(APPLICATION_NAME);
m_parser.addHelpOption();
m_parser.addVersionOption();
QCommandLineOption c_autostart { { "a", "autostart" }, "System autostart" };
m_parser.addOption(c_autostart);
QCommandLineOption c_cleanup { { "c", "cleanup" }, "Cleanup logs" };
m_parser.addOption(c_cleanup);
m_parser.process(*this);
if (m_parser.isSet(c_cleanup)) {
Logger::cleanUp();
QTimer::singleShot(100, this, [this] { quit(); });
exec();
return false;
}
return true;
}
QQmlApplicationEngine *AmneziaApplication::qmlEngine() const
{
return m_engine;
}
void AmneziaApplication::initModels()
{
m_containersModel.reset(new ContainersModel(this));
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
m_serversModel.reset(new ServersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(),
&ContainersModel::updateModel);
connect(m_serversModel.get(), &ServersModel::defaultContainerChanged, m_containersModel.get(),
&ContainersModel::setDefaultContainer);
m_containersModel->setDefaultContainer(m_serversModel->getDefaultContainer()); // make better?
m_languageModel.reset(new LanguageModel(m_settings, this));
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
connect(m_languageModel.get(), &LanguageModel::updateTranslations, this, &AmneziaApplication::updateTranslator);
connect(this, &AmneziaApplication::translationsUpdated, m_languageModel.get(), &LanguageModel::translationsUpdated);
m_sitesModel.reset(new SitesModel(m_settings, this));
m_engine->rootContext()->setContextProperty("SitesModel", m_sitesModel.get());
m_protocolsModel.reset(new ProtocolsModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get());
m_openVpnConfigModel.reset(new OpenVpnConfigModel(this));
m_engine->rootContext()->setContextProperty("OpenVpnConfigModel", m_openVpnConfigModel.get());
m_shadowSocksConfigModel.reset(new ShadowSocksConfigModel(this));
m_engine->rootContext()->setContextProperty("ShadowSocksConfigModel", m_shadowSocksConfigModel.get());
m_cloakConfigModel.reset(new CloakConfigModel(this));
m_engine->rootContext()->setContextProperty("CloakConfigModel", m_cloakConfigModel.get());
m_wireGuardConfigModel.reset(new WireGuardConfigModel(this));
m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireGuardConfigModel.get());
m_awgConfigModel.reset(new AwgConfigModel(this));
m_engine->rootContext()->setContextProperty("AwgConfigModel", m_awgConfigModel.get());
#ifdef Q_OS_WINDOWS
m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this));
m_engine->rootContext()->setContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel.get());
#endif
m_sftpConfigModel.reset(new SftpConfigModel(this));
m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get());
m_clientManagementModel.reset(new ClientManagementModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ClientManagementModel", m_clientManagementModel.get());
connect(m_clientManagementModel.get(), &ClientManagementModel::adminConfigRevoked,
m_serversModel.get(), &ServersModel::clearCachedProfile);
connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, this,
[this](const QString &clientId, const QString &clientName, const DockerContainer container,
ServerCredentials credentials) {
m_serversModel->reloadContainerConfig();
m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
emit m_configurator->clientModelUpdated();
});
}
void AmneziaApplication::initControllers()
{
m_connectionController.reset(new ConnectionController(m_serversModel, m_containersModel, m_vpnConnection));
m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get());
connect(this, &AmneziaApplication::translationsUpdated, m_connectionController.get(),
&ConnectionController::onTranslationsUpdated);
m_pageController.reset(new PageController(m_serversModel, m_settings));
m_engine->rootContext()->setContextProperty("PageController", m_pageController.get());
m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, m_settings));
m_engine->rootContext()->setContextProperty("InstallController", m_installController.get());
connect(m_installController.get(), &InstallController::passphraseRequestStarted, m_pageController.get(),
&PageController::showPassphraseRequestDrawer);
connect(m_pageController.get(), &PageController::passphraseRequestDrawerClosed, m_installController.get(),
&InstallController::setEncryptedPassphrase);
connect(m_installController.get(), &InstallController::currentContainerUpdated, m_connectionController.get(),
&ConnectionController::onCurrentContainerUpdated);
m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings));
m_engine->rootContext()->setContextProperty("ImportController", m_importController.get());
m_exportController.reset(new ExportController(m_serversModel, m_containersModel, m_clientManagementModel,
m_settings, m_configurator));
m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get());
m_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_sitesModel, m_settings));
m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get());
if (m_settingsController->isAutoConnectEnabled() && m_serversModel->getDefaultServerIndex() >= 0) {
QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); });
}
connect(m_settingsController.get(), &SettingsController::amneziaDnsToggled , m_serversModel.get(),
&ServersModel::toggleAmneziaDns);
m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel));
m_engine->rootContext()->setContextProperty("SitesController", m_sitesController.get());
m_systemController.reset(new SystemController(m_settings));
m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get());
m_cloudController.reset(new ApiController(m_serversModel, m_containersModel));
m_engine->rootContext()->setContextProperty("ApiController", m_cloudController.get());
}
+127 -121
View File
@@ -1,121 +1,127 @@
#ifndef AMNEZIA_APPLICATION_H
#define AMNEZIA_APPLICATION_H
#include <QCommandLineParser>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QThread>
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#include <QGuiApplication>
#else
#include <QApplication>
#endif
#include "settings.h"
#include "vpnconnection.h"
#include "configurators/vpn_configurator.h"
#include "ui/controllers/connectionController.h"
#include "ui/controllers/exportController.h"
#include "ui/controllers/importController.h"
#include "ui/controllers/installController.h"
#include "ui/controllers/pageController.h"
#include "ui/controllers/settingsController.h"
#include "ui/controllers/sitesController.h"
#include "ui/controllers/systemController.h"
#include "ui/models/containers_model.h"
#include "ui/models/languageModel.h"
#include "ui/models/protocols/cloakConfigModel.h"
#include "ui/notificationhandler.h"
#ifdef Q_OS_WINDOWS
#include "ui/models/protocols/ikev2ConfigModel.h"
#endif
#include "ui/models/protocols/openvpnConfigModel.h"
#include "ui/models/protocols/shadowsocksConfigModel.h"
#include "ui/models/protocols/wireguardConfigModel.h"
#include "ui/models/protocols_model.h"
#include "ui/models/servers_model.h"
#include "ui/models/services/sftpConfigModel.h"
#include "ui/models/sites_model.h"
#define amnApp (static_cast<AmneziaApplication *>(QCoreApplication::instance()))
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#define AMNEZIA_BASE_CLASS QGuiApplication
#else
#define AMNEZIA_BASE_CLASS SingleApplication
#define QAPPLICATION_CLASS QApplication
#include "singleapplication.h"
#endif
class AmneziaApplication : public AMNEZIA_BASE_CLASS
{
Q_OBJECT
public:
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
AmneziaApplication(int &argc, char *argv[]);
#else
AmneziaApplication(int &argc, char *argv[], bool allowSecondary = false,
SingleApplication::Options options = SingleApplication::User, int timeout = 1000,
const QString &userData = {});
#endif
virtual ~AmneziaApplication();
void init();
void registerTypes();
void loadFonts();
void loadTranslator();
void updateTranslator(const QLocale &locale);
bool parseCommands();
QQmlApplicationEngine *qmlEngine() const;
signals:
void translationsUpdated();
private:
void initModels();
void initControllers();
QQmlApplicationEngine *m_engine {};
std::shared_ptr<Settings> m_settings;
std::shared_ptr<VpnConfigurator> m_configurator;
QSharedPointer<ContainerProps> m_containerProps;
QSharedPointer<ProtocolProps> m_protocolProps;
QSharedPointer<QTranslator> m_translator;
QCommandLineParser m_parser;
QSharedPointer<ContainersModel> m_containersModel;
QSharedPointer<ServersModel> m_serversModel;
QSharedPointer<LanguageModel> m_languageModel;
QSharedPointer<ProtocolsModel> m_protocolsModel;
QSharedPointer<SitesModel> m_sitesModel;
QScopedPointer<OpenVpnConfigModel> m_openVpnConfigModel;
QScopedPointer<ShadowSocksConfigModel> m_shadowSocksConfigModel;
QScopedPointer<CloakConfigModel> m_cloakConfigModel;
QScopedPointer<WireGuardConfigModel> m_wireguardConfigModel;
#ifdef Q_OS_WINDOWS
QScopedPointer<Ikev2ConfigModel> m_ikev2ConfigModel;
#endif
QScopedPointer<SftpConfigModel> m_sftpConfigModel;
QSharedPointer<VpnConnection> m_vpnConnection;
QThread m_vpnConnectionThread;
QScopedPointer<NotificationHandler> m_notificationHandler;
QScopedPointer<ConnectionController> m_connectionController;
QScopedPointer<PageController> m_pageController;
QScopedPointer<InstallController> m_installController;
QScopedPointer<ImportController> m_importController;
QScopedPointer<ExportController> m_exportController;
QScopedPointer<SettingsController> m_settingsController;
QScopedPointer<SitesController> m_sitesController;
QScopedPointer<SystemController> m_systemController;
};
#endif // AMNEZIA_APPLICATION_H
#ifndef AMNEZIA_APPLICATION_H
#define AMNEZIA_APPLICATION_H
#include <QCommandLineParser>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QThread>
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#include <QGuiApplication>
#else
#include <QApplication>
#endif
#include "settings.h"
#include "vpnconnection.h"
#include "configurators/vpn_configurator.h"
#include "ui/controllers/connectionController.h"
#include "ui/controllers/exportController.h"
#include "ui/controllers/importController.h"
#include "ui/controllers/installController.h"
#include "ui/controllers/pageController.h"
#include "ui/controllers/settingsController.h"
#include "ui/controllers/sitesController.h"
#include "ui/controllers/systemController.h"
#include "ui/controllers/apiController.h"
#include "ui/models/containers_model.h"
#include "ui/models/languageModel.h"
#include "ui/models/protocols/cloakConfigModel.h"
#include "ui/notificationhandler.h"
#ifdef Q_OS_WINDOWS
#include "ui/models/protocols/ikev2ConfigModel.h"
#endif
#include "ui/models/protocols/awgConfigModel.h"
#include "ui/models/protocols/openvpnConfigModel.h"
#include "ui/models/protocols/shadowsocksConfigModel.h"
#include "ui/models/protocols/wireguardConfigModel.h"
#include "ui/models/protocols_model.h"
#include "ui/models/servers_model.h"
#include "ui/models/services/sftpConfigModel.h"
#include "ui/models/sites_model.h"
#include "ui/models/clientManagementModel.h"
#define amnApp (static_cast<AmneziaApplication *>(QCoreApplication::instance()))
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#define AMNEZIA_BASE_CLASS QGuiApplication
#else
#define AMNEZIA_BASE_CLASS SingleApplication
#define QAPPLICATION_CLASS QApplication
#include "singleapplication.h"
#endif
class AmneziaApplication : public AMNEZIA_BASE_CLASS
{
Q_OBJECT
public:
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
AmneziaApplication(int &argc, char *argv[]);
#else
AmneziaApplication(int &argc, char *argv[], bool allowSecondary = false,
SingleApplication::Options options = SingleApplication::User, int timeout = 1000,
const QString &userData = {});
#endif
virtual ~AmneziaApplication();
void init();
void registerTypes();
void loadFonts();
void loadTranslator();
void updateTranslator(const QLocale &locale);
bool parseCommands();
QQmlApplicationEngine *qmlEngine() const;
signals:
void translationsUpdated();
private:
void initModels();
void initControllers();
QQmlApplicationEngine *m_engine {};
std::shared_ptr<Settings> m_settings;
std::shared_ptr<VpnConfigurator> m_configurator;
QSharedPointer<ContainerProps> m_containerProps;
QSharedPointer<ProtocolProps> m_protocolProps;
QSharedPointer<QTranslator> m_translator;
QCommandLineParser m_parser;
QSharedPointer<ContainersModel> m_containersModel;
QSharedPointer<ServersModel> m_serversModel;
QSharedPointer<LanguageModel> m_languageModel;
QSharedPointer<ProtocolsModel> m_protocolsModel;
QSharedPointer<SitesModel> m_sitesModel;
QSharedPointer<ClientManagementModel> m_clientManagementModel;
QScopedPointer<OpenVpnConfigModel> m_openVpnConfigModel;
QScopedPointer<ShadowSocksConfigModel> m_shadowSocksConfigModel;
QScopedPointer<CloakConfigModel> m_cloakConfigModel;
QScopedPointer<WireGuardConfigModel> m_wireGuardConfigModel;
QScopedPointer<AwgConfigModel> m_awgConfigModel;
#ifdef Q_OS_WINDOWS
QScopedPointer<Ikev2ConfigModel> m_ikev2ConfigModel;
#endif
QScopedPointer<SftpConfigModel> m_sftpConfigModel;
QSharedPointer<VpnConnection> m_vpnConnection;
QThread m_vpnConnectionThread;
QScopedPointer<NotificationHandler> m_notificationHandler;
QScopedPointer<ConnectionController> m_connectionController;
QScopedPointer<PageController> m_pageController;
QScopedPointer<InstallController> m_installController;
QScopedPointer<ImportController> m_importController;
QScopedPointer<ExportController> m_exportController;
QScopedPointer<SettingsController> m_settingsController;
QScopedPointer<SitesController> m_sitesController;
QScopedPointer<SystemController> m_systemController;
QScopedPointer<ApiController> m_cloudController;
};
#endif // AMNEZIA_APPLICATION_H
+112 -119
View File
@@ -1,165 +1,158 @@
<?xml version="1.0"?>
<!-- Leave package attribute for androiddeployqt -->
<manifest
package="org.amnezia.vpn"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.amnezia.vpn"
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.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.any" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<!-- Enable when VPN-per-app mode will be implemented -->
<!-- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> -->
<uses-permission android:name="android.permission.CAMERA"/>
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- The following comment will be replaced upon deployment with default features based on the dependencies
of the application. Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:anyDensity="true"
android:smallScreens="true"/>
<uses-permission android:name="android.permission.INTERNET" />
<!-- To request network state -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- Enable when VPN-per-app mode will be implemented -->
<!-- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/> -->
<application
android:name=".qt.AmneziaApp"
android:hardwareAccelerated="true"
android:name=".AmneziaApplication"
android:label="-- %%INSERT_APP_NAME%% --"
android:extractNativeLibs="true"
android:requestLegacyExternalStorage="true"
android:allowNativeHeapPointerTagging="false"
android:theme="@style/Theme.AppCompat.NoActionBar"
android:icon="@drawable/icon"
android:roundIcon="@drawable/icon_round">
android:icon="@mipmap/icon"
android:roundIcon="@mipmap/icon_round"
android:theme="@style/NoActionBar"
android:fullBackupContent="@xml/backup_content"
android:dataExtractionRules="@xml/data_extraction_rules"
tools:targetApi="s">
<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:name=".AmneziaActivity"
android:configChanges="uiMode|screenSize|smallestScreenSize|screenLayout|orientation|density
|fontScale|layoutDirection|locale|keyboard|keyboardHidden|navigation|mcc|mnc"
android:launchMode="singleInstance"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<!-- android:theme="@style/splashScreenTheme"-->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="org.amnezia.vpn.qt.IMPORT_CONFIG" />
<action android:name="org.amnezia.vpn.IMPORT_CONFIG" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
android:value="-- %%INSERT_APP_LIB_NAME%% --" />
<meta-data
android:name="android.app.extract_android_style"
android:value="minimal" />
<meta-data
android:name="android.app.background_running"
android:value="false"/>
<meta-data
android:name="android.app.arguments"
android:value="-- %%INSERT_APP_ARGUMENTS%% --" />
</activity>
<activity
android:name=".qt.CameraActivity"
android:name=".CameraActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity=""
android:exported="false" />
<activity
android:name=".qt.ImportConfigActivity"
android:exported="true" >
<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"/>
android:name=".VpnRequestActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity=""
android:exported="false"
android:theme="@style/Translucent" />
<activity
android:name=".ImportConfigActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity=""
android:exported="true"
android:theme="@style/Translucent">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/octet-stream" />
<data android:mimeType="text/plain" />
</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>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="vpn" android:host="*" />
</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>
<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" />
<data android:pathPattern=".*\\.cfg" />
<data android:pathPattern=".*\\..*\\.cfg" />
<data android:pathPattern=".*\\..*\\..*\\.cfg" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.cfg" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.cfg" />
<data android:pathPattern=".*\\.conf" />
<data android:pathPattern=".*\\..*\\.conf" />
<data android:pathPattern=".*\\..*\\..*\\.conf" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.conf" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.conf" />
</intent-filter>
</activity>
<service
android:name=".VPNService"
android:process=":QtOnlyProcess"
android:name=".AmneziaVpnService"
android:process=":amneziaVpnService"
android:permission="android.permission.BIND_VPN_SERVICE"
android:foregroundServiceType="connectedDevice"
android:exported="true">
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<intent-filter>
<action android:name="android.net.VpnService"/>
</intent-filter>
android:foregroundServiceType="specialUse"
android:exported="false">
<intent-filter>
<action android:name="android.net.VpnService" />
</intent-filter>
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="vpn" />
</service>
<service
android:name=".qt.VPNPermissionHelper"
android:permission="android.permission.BIND_VPN_SERVICE"
android:foregroundServiceType="connectedDevice"
android:exported="true">
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
</service>
<!-- 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:authorities="org.amnezia.vpn.qtprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/fileprovider"/>
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/qtprovider_paths" />
</provider>
</application>
</manifest>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-17
View File
@@ -1,17 +0,0 @@
[proxy_all]
[bypass_list]
0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
172.16.0.0/12
192.0.0.0/29
192.0.2.0/24
192.88.99.0/24
192.168.0.0/16
198.18.0.0/15
198.51.100.0/24
203.0.113.0/24
224.0.0.0/3
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
plugins {
id(libs.plugins.android.library.get().pluginId)
id(libs.plugins.kotlin.android.get().pluginId)
}
kotlin {
jvmToolchain(17)
}
android {
namespace = "org.amnezia.vpn.protocol.awg"
}
dependencies {
compileOnly(project(":utils"))
compileOnly(project(":protocolApi"))
implementation(project(":wireguard"))
}
+80
View File
@@ -0,0 +1,80 @@
package org.amnezia.vpn.protocol.awg
import org.amnezia.vpn.protocol.wireguard.Wireguard
import org.json.JSONObject
/**
* Config example:
* {
* "protocol": "awg",
* "description": "Server 1",
* "dns1": "1.1.1.1",
* "dns2": "1.0.0.1",
* "hostName": "100.100.100.0",
* "splitTunnelSites": [
* ],
* "splitTunnelType": 0,
* "awg_config_data": {
* "H1": "969537490",
* "H2": "481688153",
* "H3": "2049399200",
* "H4": "52029755",
* "Jc": "3",
* "Jmax": "1000",
* "Jmin": "50",
* "S1": "49",
* "S2": "60",
* "client_ip": "10.8.1.1",
* "hostName": "100.100.100.0",
* "port": 12345,
* "client_pub_key": "clientPublicKeyBase64",
* "client_priv_key": "privateKeyBase64",
* "psk_key": "presharedKeyBase64",
* "server_pub_key": "publicKeyBase64",
* "config": "[Interface]
* Address = 10.8.1.1/32
* DNS = 1.1.1.1, 1.0.0.1
* PrivateKey = privateKeyBase64
* Jc = 3
* Jmin = 50
* Jmax = 1000
* S1 = 49
* S2 = 60
* H1 = 969537490
* H2 = 481688153
* H3 = 2049399200
* H4 = 52029755
*
* [Peer]
* PublicKey = publicKeyBase64
* PresharedKey = presharedKeyBase64
* AllowedIPs = 0.0.0.0/0, ::/0
* Endpoint = 100.100.100.0:12345
* PersistentKeepalive = 25
* "
* }
* }
*/
class Awg : Wireguard() {
override val ifName: String = "awg0"
override fun parseConfig(config: JSONObject): AwgConfig {
val configDataJson = config.getJSONObject("awg_config_data")
val configData = parseConfigData(configDataJson.getString("config"))
return AwgConfig.build {
configWireguard(configData)
configSplitTunneling(config)
configData["Jc"]?.let { setJc(it.toInt()) }
configData["Jmin"]?.let { setJmin(it.toInt()) }
configData["Jmax"]?.let { setJmax(it.toInt()) }
configData["S1"]?.let { setS1(it.toInt()) }
configData["S2"]?.let { setS2(it.toInt()) }
configData["H1"]?.let { setH1(it.toLong()) }
configData["H2"]?.let { setH2(it.toLong()) }
configData["H3"]?.let { setH3(it.toLong()) }
configData["H4"]?.let { setH4(it.toLong()) }
}
}
}
@@ -0,0 +1,108 @@
package org.amnezia.vpn.protocol.awg
import org.amnezia.vpn.protocol.BadConfigException
import org.amnezia.vpn.protocol.wireguard.WireguardConfig
class AwgConfig private constructor(
wireguardConfigBuilder: WireguardConfig.Builder,
val jc: Int,
val jmin: Int,
val jmax: Int,
val s1: Int,
val s2: Int,
val h1: Long,
val h2: Long,
val h3: Long,
val h4: Long
) : WireguardConfig(wireguardConfigBuilder) {
private constructor(builder: Builder) : this(
builder,
builder.jc,
builder.jmin,
builder.jmax,
builder.s1,
builder.s2,
builder.h1,
builder.h2,
builder.h3,
builder.h4
)
override fun appendDeviceLine(sb: StringBuilder) = with(sb) {
super.appendDeviceLine(this)
appendLine("jc=$jc")
appendLine("jmin=$jmin")
appendLine("jmax=$jmax")
appendLine("s1=$s1")
appendLine("s2=$s2")
appendLine("h1=$h1")
appendLine("h2=$h2")
appendLine("h3=$h3")
appendLine("h4=$h4")
}
class Builder : WireguardConfig.Builder() {
private var _jc: Int? = null
internal var jc: Int
get() = _jc ?: throw BadConfigException("AWG: parameter jc is undefined")
private set(value) { _jc = value }
private var _jmin: Int? = null
internal var jmin: Int
get() = _jmin ?: throw BadConfigException("AWG: parameter jmin is undefined")
private set(value) { _jmin = value }
private var _jmax: Int? = null
internal var jmax: Int
get() = _jmax ?: throw BadConfigException("AWG: parameter jmax is undefined")
private set(value) { _jmax = value }
private var _s1: Int? = null
internal var s1: Int
get() = _s1 ?: throw BadConfigException("AWG: parameter s1 is undefined")
private set(value) { _s1 = value }
private var _s2: Int? = null
internal var s2: Int
get() = _s2 ?: throw BadConfigException("AWG: parameter s2 is undefined")
private set(value) { _s2 = value }
private var _h1: Long? = null
internal var h1: Long
get() = _h1 ?: throw BadConfigException("AWG: parameter h1 is undefined")
private set(value) { _h1 = value }
private var _h2: Long? = null
internal var h2: Long
get() = _h2 ?: throw BadConfigException("AWG: parameter h2 is undefined")
private set(value) { _h2 = value }
private var _h3: Long? = null
internal var h3: Long
get() = _h3 ?: throw BadConfigException("AWG: parameter h3 is undefined")
private set(value) { _h3 = value }
private var _h4: Long? = null
internal var h4: Long
get() = _h4 ?: throw BadConfigException("AWG: parameter h4 is undefined")
private set(value) { _h4 = value }
fun setJc(jc: Int) = apply { this.jc = jc }
fun setJmin(jmin: Int) = apply { this.jmin = jmin }
fun setJmax(jmax: Int) = apply { this.jmax = jmax }
fun setS1(s1: Int) = apply { this.s1 = s1 }
fun setS2(s2: Int) = apply { this.s2 = s2 }
fun setH1(h1: Long) = apply { this.h1 = h1 }
fun setH2(h2: Long) = apply { this.h2 = h2 }
fun setH3(h3: Long) = apply { this.h3 = h3 }
fun setH4(h4: Long) = apply { this.h4 = h4 }
override fun build(): AwgConfig = AwgConfig(this)
}
companion object {
inline fun build(block: Builder.() -> Unit): AwgConfig = Builder().apply(block).build()
}
}
+4 -152
View File
@@ -1,153 +1,5 @@
apply plugin: 'com.github.ben-manes.versions'
buildscript {
ext{
kotlin_version = "1.7.22"
// for libwg
appcompatVersion = '1.1.0'
annotationsVersion = '1.0.1'
databindingVersion = '3.3.1'
jsr305Version = '3.0.2'
streamsupportVersion = '1.7.0'
threetenabpVersion = '1.1.1'
groupName = 'org.amnezia.vpn'
minSdkVer = '24'
cmakeMinVersion = "3.25.0+"
}
repositories {
google()
jcenter()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.1'
classpath 'com.github.ben-manes:gradle-versions-plugin:0.21.0'
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.8.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
}
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlinx-serialization'
apply plugin: 'kotlin-kapt'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation group: 'org.json', name: 'json', version: '20220924'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation "androidx.security:security-crypto:1.1.0-alpha03"
implementation "androidx.security:security-identity-credential:1.0.0-alpha02"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
implementation project(path: ':shadowsocks')
// CameraX core library using the camera2 implementation
def camerax_version = "1.2.1"
implementation("androidx.camera:camera-core:${camerax_version}")
implementation("androidx.camera:camera-camera2:${camerax_version}")
implementation("androidx.camera:camera-lifecycle:${camerax_version}")
implementation("androidx.camera:camera-view:${camerax_version}")
implementation("androidx.camera:camera-extensions:${camerax_version}")
def camerax_ml_version = "1.2.0-beta02"
def ml_kit_version = "17.0.3"
implementation("androidx.camera:camera-mlkit-vision:${camerax_ml_version}")
implementation("com.google.mlkit:barcode-scanning:${ml_kit_version}")
}
androidExtensions {
experimental = true
}
android {
/*******************************************************
* The following variables:
* - androidBuildToolsVersion,
* - androidCompileSdkVersion
* - qtAndroidDir - holds the path to qt android files
* needed to build any Qt application
* on Android.
*
* are defined in gradle.properties file. This file is
* updated by QtCreator and androiddeployqt tools.
* Changing them manually might break the compilation!
*******************************************************/
compileSdkVersion androidCompileSdkVersion.toInteger()
buildToolsVersion androidBuildToolsVersion
ndkVersion androidNdkVersion
// Extract native libraries from the APK
packagingOptions.jniLibs.useLegacyPackaging true
dexOptions {
javaMaxHeapSize "3g"
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qtAndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qtAndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qtAndroidDir + '/res', 'res']
resources.srcDirs = ['resources']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
androidTest.assets.srcDirs += files("${qtAndroidDir}/schemas".toString())
}
}
tasks.withType(JavaCompile) {
options.incremental = true
}
compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8
lintOptions {
abortOnError false
}
// Do not compress Qt binary resources file
aaptOptions {
noCompress 'rcc'
}
defaultConfig {
resConfig "en"
minSdkVersion = 24
targetSdkVersion = 34
versionCode 32 // Change to a higher number
versionName "3.0.9" // Change to a higher number
javaCompileOptions.annotationProcessorOptions.arguments = [
"room.schemaLocation": "${qtAndroidDir}/schemas".toString()
]
}
}
// dummy file for androiddeployqt
// android.bundle.enableUncompressedNativeLibs is deprecated
// disable adding gradle property android.bundle.enableUncompressedNativeLibs by androiddeployqt
useLegacyPackaging
+114
View File
@@ -0,0 +1,114 @@
import com.android.build.gradle.internal.api.BaseVariantOutputImpl
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
id("property-delegate")
}
kotlin {
jvmToolchain(17)
}
// get values from gradle or local properties
val qtTargetSdkVersion: String by gradleProperties
val qtTargetAbiList: String by gradleProperties
val outputBaseName: String by gradleProperties
android {
namespace = "org.amnezia.vpn"
buildFeatures {
viewBinding = true
}
androidResources {
// don't compress Qt binary resources file
noCompress += "rcc"
}
packaging {
// compress .so binary libraries
jniLibs.useLegacyPackaging = true
}
defaultConfig {
applicationId = "org.amnezia.vpn"
targetSdk = qtTargetSdkVersion.toInt()
// keeps language resources for only the locales specified below
resourceConfigurations += listOf("en", "ru", "b+zh+Hans")
}
sourceSets {
getByName("main") {
manifest.srcFile("AndroidManifest.xml")
java.setSrcDirs(listOf("src"))
res.setSrcDirs(listOf("res"))
// androyddeployqt creates the folders below
assets.setSrcDirs(listOf("assets"))
jniLibs.setSrcDirs(listOf("libs"))
}
}
signingConfigs {
register("release") {
storeFile = providers.environmentVariable("ANDROID_KEYSTORE_PATH").orNull?.let { file(it) }
storePassword = providers.environmentVariable("ANDROID_KEYSTORE_KEY_PASS").orNull
keyAlias = providers.environmentVariable("ANDROID_KEYSTORE_KEY_ALIAS").orNull
keyPassword = providers.environmentVariable("ANDROID_KEYSTORE_KEY_PASS").orNull
}
}
buildTypes {
release {
// exclude coroutine debug resource from release build
packaging {
resources.excludes += "DebugProbesKt.bin"
}
signingConfig = signingConfigs["release"]
}
}
splits {
abi {
isEnable = true
reset()
include(*qtTargetAbiList.split(',').toTypedArray())
isUniversalApk = false
}
}
// fix for Qt Creator to allow deploying the application to a device
// to enable this fix, add the line outputBaseName=android-build to local.properties
if (outputBaseName.isNotEmpty()) {
applicationVariants.all {
outputs.map { it as BaseVariantOutputImpl }
.forEach { output ->
if (output.outputFileName.endsWith(".apk")) {
output.outputFileName = "$outputBaseName-${buildType.name}.apk"
}
}
}
}
lint {
disable += "InvalidFragmentVersionForActivityResult"
}
}
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar"))))
implementation(project(":qt"))
implementation(project(":utils"))
implementation(project(":protocolApi"))
implementation(project(":wireguard"))
implementation(project(":awg"))
implementation(project(":openvpn"))
implementation(project(":cloak"))
implementation(libs.androidx.core)
implementation(libs.androidx.activity)
implementation(libs.kotlinx.coroutines)
implementation(libs.bundles.androidx.camera)
implementation(libs.google.mlkit)
}
+18
View File
@@ -0,0 +1,18 @@
plugins {
id(libs.plugins.android.library.get().pluginId)
id(libs.plugins.kotlin.android.get().pluginId)
}
kotlin {
jvmToolchain(17)
}
android {
namespace = "org.amnezia.vpn.protocol.cloak"
}
dependencies {
compileOnly(project(":utils"))
compileOnly(project(":protocolApi"))
implementation(project(":openvpn"))
}
@@ -0,0 +1,69 @@
package org.amnezia.vpn.protocol.cloak
import android.util.Base64
import net.openvpn.ovpn3.ClientAPI_Config
import org.amnezia.vpn.protocol.openvpn.OpenVpn
import org.json.JSONObject
/**
* Config Example:
* {
* "protocol": "cloak",
* "description": "Server 1",
* "dns1": "1.1.1.1",
* "dns2": "1.0.0.1",
* "hostName": "100.100.100.0",
* "splitTunnelSites": [
* ],
* "splitTunnelType": 0,
* "openvpn_config_data": {
* "config": "openVpnConfig"
* }
* "cloak_config_data": {
* "BrowserSig": "chrome",
* "EncryptionMethod": "aes-gcm",
* "NumConn": 1,
* "ProxyMethod": "openvpn",
* "PublicKey": "PublicKey=",
* "RemoteHost": "100.100.100.0",
* "RemotePort": "443",
* "ServerName": "servername",
* "StreamTimeout": 300,
* "Transport": "direct",
* "UID": "UID="
* }
* }
*/
class Cloak : OpenVpn() {
override fun parseConfig(config: JSONObject): ClientAPI_Config {
val openVpnConfig = ClientAPI_Config()
val openVpnConfigStr = config.getJSONObject("openvpn_config_data").getString("config")
val cloakConfigJson = checkCloakJson(config.getJSONObject("cloak_config_data"))
val cloakConfigStr = Base64.encodeToString(cloakConfigJson.toString().toByteArray(), Base64.DEFAULT)
val configStr = "$openVpnConfigStr\n<cloak>\n$cloakConfigStr\n</cloak>\n"
openVpnConfig.usePluggableTransports = true
openVpnConfig.content = configStr
return openVpnConfig
}
private fun checkCloakJson(cloakConfigJson: JSONObject): JSONObject {
cloakConfigJson.put("NumConn", 1)
cloakConfigJson.put("ProxyMethod", "openvpn")
if (cloakConfigJson.has("port")) {
val port = cloakConfigJson["port"]
cloakConfigJson.remove("port")
cloakConfigJson.put("RemotePort", port)
}
if (cloakConfigJson.has("remote")) {
val remote = cloakConfigJson["remote"]
cloakConfigJson.remove("remote")
cloakConfigJson.put("RemoteHost", remote)
}
return cloakConfigJson
}
}
+41 -22
View File
@@ -1,27 +1,46 @@
# Project-wide Gradle settings.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# Gradle caching allows reusing the build artifacts from a previous
# build with the same inputs. However, over time, the cache size will
# grow. Uncomment the following line to enable it.
#org.gradle.caching=true
# Specifies the JVM arguments used for the daemon process
org.gradle.jvmargs=-Xms512m -Xmx4g -XX:+UseParallelGC -XX:MaxMetaspaceSize=768m -XX:+HeapDumpOnOutOfMemoryError \
-Dfile.encoding=UTF-8
org.gradle.caching=true
org.gradle.parallel=true
org.gradle.configureondemand=true
# Use AndroidX library instead of a Support Library
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Disable adding android:testOnly attribute to the manifest
android.injected.testOnly=false
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.bundle.enableUncompressedNativeLibs=false
androidBuildToolsVersion=30.0.2
androidCompileSdkVersion=30
org.gradle.caching=true
org.gradle.parallel=true
android.enableJetifier=true
android.injected.testOnly=false
kapt.use.worker.api=false
kapt.incremental.apt=false
# Disable providing custom values to resources from buildscript by default
android.defaults.buildfeatures.resvalues=false
# Disable compileShaders tasks by default
android.defaults.buildfeatures.shaders=false
# Disable Android resource processing for libraries by default
android.library.defaults.buildfeatures.androidresources=false
# Qt variables
# At build time androiddeployqt replaces these values with:
# androidCompileSdkVersion - androiddeployqt --android-platform parameter
# androidBuildToolsVersion - QT_ANDROID_SDK_BUILD_TOOLS_REVISION cmake target parameter
# qtMinSdkVersion - QT_ANDROID_MIN_SDK_VERSION cmake target parameter
# qtTargetSdkVersion - QT_ANDROID_TARGET_SDK_VERSION cmake target parameter
# androidNdkVersion - version from ANDROID_NDK_ROOT environment variable
# qtTargetAbiList - qt-cmake QT_ANDROID_ABIS parameter
# qtAndroidDir - path to qt binding java source code
# buildDir - hardcoded "build" value in androiddeployqt
# For development copy and set local values for these parameters in local.properties
#androidCompileSdkVersion=android-34
#androidBuildToolsVersion=34.0.0
#qtMinSdkVersion=24
#qtTargetSdkVersion=34
#androidNdkVersion=26.1.10909125
#qtTargetAbiList=x86_64
#qtAndroidDir=/QT_BASE/android_ABI/src/android/java
#buildDir=build
# Note about qtAndroidDir:
# Some IDEs (for example, IntelliJ IDEA) may index all data from a common root of the project and qtAndroidDir.
# Therefore, it's recommended to copy qt android files to a directory inside the project
# and specify the path to that directory in qtAndroidDir.
+35
View File
@@ -0,0 +1,35 @@
[versions]
agp = "8.2.0"
kotlin = "1.9.20"
androidx-core = "1.12.0"
androidx-activity = "1.8.1"
androidx-annotation = "1.7.0"
androidx-camera = "1.3.0"
androidx-security-crypto = "1.1.0-alpha06"
kotlinx-coroutines = "1.7.3"
google-mlkit = "17.2.0"
[libraries]
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" }
androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "androidx-annotation" }
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "androidx-camera" }
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "androidx-camera" }
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "androidx-camera" }
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "androidx-camera" }
androidx-security-crypto = { module = "androidx.security:security-crypto-ktx", version.ref = "androidx-security-crypto" }
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
google-mlkit = { module = "com.google.mlkit:barcode-scanning", version.ref = "google-mlkit" }
[bundles]
androidx-camera = [
"androidx-camera-core",
"androidx-camera-lifecycle",
"androidx-camera-view",
"androidx-camera-camera2"
]
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
@@ -0,0 +1,25 @@
plugins {
`kotlin-dsl`
}
repositories {
gradlePluginPortal()
}
kotlin {
jvmToolchain(17)
}
gradlePlugin {
plugins {
register("settingsGradlePropertyDelegate") {
id = "settings-property-delegate"
implementationClass = "SettingsPropertyDelegate"
}
register("projectGradlePropertyDelegate") {
id = "property-delegate"
implementationClass = "ProjectPropertyDelegate"
}
}
}
@@ -0,0 +1,49 @@
import java.io.File
import java.io.FileInputStream
import java.io.InputStreamReader
import java.util.Properties
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.initialization.Settings
import org.gradle.api.provider.ProviderFactory
private fun localProperties(rootDir: File) = Properties().apply {
val localProperties = File(rootDir, "local.properties")
if (localProperties.isFile) {
InputStreamReader(FileInputStream(localProperties), Charsets.UTF_8).use {
load(it)
}
}
}
private class PropertyDelegate(
rootDir: File,
private val providers: ProviderFactory,
private val localProperties: Properties = localProperties(rootDir)
) : ReadOnlyProperty<Any?, String> {
override fun getValue(thisRef: Any?, property: KProperty<*>): String =
providers.gradleProperty(property.name).orNull ?: localProperties.getProperty(property.name).orEmpty()
}
private lateinit var settingsPropertyDelegate: ReadOnlyProperty<Any?, String>
private lateinit var projectPropertyDelegate: ReadOnlyProperty<Any?, String>
class SettingsPropertyDelegate : Plugin<Settings> {
override fun apply(settings: Settings) {
settingsPropertyDelegate = PropertyDelegate(settings.rootDir, settings.providers)
}
}
class ProjectPropertyDelegate : Plugin<Project> {
override fun apply(project: Project) {
projectPropertyDelegate = PropertyDelegate(project.rootDir, project.providers)
}
}
val Settings.gradleProperties: ReadOnlyProperty<Any?, String>
get() = settingsPropertyDelegate
val Project.gradleProperties: ReadOnlyProperty<Any?, String>
get() = projectPropertyDelegate
Binary file not shown.
+3 -1
View File
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+193 -116
View File
@@ -1,78 +1,127 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -81,92 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
+32 -24
View File
@@ -1,4 +1,20 @@
@if "%DEBUG%" == "" @echo off
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -9,19 +25,23 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +55,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,38 +65,26 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
+18
View File
@@ -0,0 +1,18 @@
plugins {
id(libs.plugins.android.library.get().pluginId)
id(libs.plugins.kotlin.android.get().pluginId)
}
kotlin {
jvmToolchain(17)
}
android {
namespace = "org.amnezia.vpn.protocol.openvpn"
}
dependencies {
compileOnly(project(":utils"))
compileOnly(project(":protocolApi"))
implementation(libs.kotlinx.coroutines)
}
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_Config {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_Config obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_ConnectionInfo {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_ConnectionInfo obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_DynamicChallenge {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_DynamicChallenge obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_EvalConfig {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_EvalConfig obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_Event {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_Event obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_ExternalPKIBase {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_ExternalPKIBase obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -20,6 +20,18 @@ public class ClientAPI_ExternalPKICertRequest extends ClientAPI_ExternalPKIReque
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_ExternalPKICertRequest obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_ExternalPKIRequestBase {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_ExternalPKIRequestBase obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -20,6 +20,18 @@ public class ClientAPI_ExternalPKISignRequest extends ClientAPI_ExternalPKIReque
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_ExternalPKISignRequest obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_InterfaceStats {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_InterfaceStats obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_KeyValue {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_KeyValue obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_LLVector extends java.util.AbstractList<Long> implements
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_LLVector obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_LogInfo {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_LogInfo obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_MergeConfig {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_MergeConfig obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -20,6 +20,18 @@ public class ClientAPI_OpenVPNClient extends ClientAPI_TunBuilderBase {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_OpenVPNClient obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_OpenVPNClientHelper {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_OpenVPNClientHelper obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_ProvideCreds {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_ProvideCreds obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_RemoteOverride {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_RemoteOverride obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_ServerEntry {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_ServerEntry obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_ServerEntryVector extends java.util.AbstractList<ClientAP
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_ServerEntryVector obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_SessionToken {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_SessionToken obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_Status {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_Status obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_StringVec extends java.util.AbstractList<String> implemen
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_StringVec obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_TransportStats {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_TransportStats obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -21,6 +21,18 @@ public class ClientAPI_TunBuilderBase {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(ClientAPI_TunBuilderBase obj) {
long ptr = 0;
if (obj != null) {
if (!obj.swigCMemOwn)
throw new RuntimeException("Cannot release ownership as memory is not owned");
ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.delete();
}
return ptr;
}
@SuppressWarnings("deprecation")
protected void finalize() {
delete();
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -22,5 +22,9 @@ public class SWIGTYPE_p_std__string {
protected static long getCPtr(SWIGTYPE_p_std__string obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(SWIGTYPE_p_std__string obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
}
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -22,5 +22,9 @@ public class SWIGTYPE_p_std__vectorT_openvpn__ClientAPI__KeyValue_t {
protected static long getCPtr(SWIGTYPE_p_std__vectorT_openvpn__ClientAPI__KeyValue_t obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected static long swigRelease(SWIGTYPE_p_std__vectorT_openvpn__ClientAPI__KeyValue_t obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
}
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.1
* This file was automatically generated by SWIG (https://www.swig.org).
* Version 4.1.1
*
* Do not make changes to this file unless you know what you are doing--modify
* Do not make changes to this file unless you know what you are doing - modify
* the SWIG interface file instead.
* ----------------------------------------------------------------------------- */
@@ -0,0 +1,136 @@
package org.amnezia.vpn.protocol.openvpn
import android.content.Context
import android.net.VpnService.Builder
import android.os.Build
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import net.openvpn.ovpn3.ClientAPI_Config
import org.amnezia.vpn.protocol.BadConfigException
import org.amnezia.vpn.protocol.Protocol
import org.amnezia.vpn.protocol.ProtocolState
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
import org.amnezia.vpn.protocol.Statistics
import org.amnezia.vpn.protocol.VpnStartException
import org.amnezia.vpn.util.net.InetNetwork
import org.amnezia.vpn.util.net.getLocalNetworks
import org.json.JSONObject
/**
* Config Example:
* {
* "protocol": "openvpn",
* "description": "Server 1",
* "dns1": "1.1.1.1",
* "dns2": "1.0.0.1",
* "hostName": "100.100.100.0",
* "splitTunnelSites": [
* ],
* "splitTunnelType": 0,
* "openvpn_config_data": {
* "config": "openVpnConfig"
* }
* }
*/
open class OpenVpn : Protocol() {
private lateinit var context: Context
private var openVpnClient: OpenVpnClient? = null
private lateinit var scope: CoroutineScope
override val statistics: Statistics
get() {
openVpnClient?.let { client ->
val stats = client.transport_stats()
return Statistics.build {
setRxBytes(stats.bytesIn)
setTxBytes(stats.bytesOut)
}
}
return Statistics.EMPTY_STATISTICS
}
override fun initialize(context: Context, state: MutableStateFlow<ProtocolState>, onError: (String) -> Unit) {
super.initialize(context, state, onError)
loadSharedLibrary(context, "ovpn3")
this.context = context
scope = CoroutineScope(Dispatchers.IO)
}
override fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
val configBuilder = OpenVpnConfig.Builder()
openVpnClient = OpenVpnClient(
configBuilder = configBuilder,
state = state,
getLocalNetworks = { ipv6 -> getLocalNetworks(context, ipv6) },
establish = makeEstablish(vpnBuilder),
protect = protect,
onError = onError
)
try {
openVpnClient?.let { client ->
val openVpnConfig = parseConfig(config)
val evalConfig = client.eval_config(openVpnConfig)
if (evalConfig.error) {
throw BadConfigException("OpenVPN config parse error: ${evalConfig.message}")
}
configBuilder.apply {
// fix for split tunneling
// The exclude split tunneling OpenVpn configuration does not contain a default route.
// It is required for split tunneling in newer versions of Android.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
addRoute(InetNetwork("0.0.0.0", 0))
addRoute(InetNetwork("::", 0))
}
configSplitTunneling(config)
}
scope.launch {
val status = client.connect()
if (status.error) {
state.value = DISCONNECTED
onError("OpenVpn connect() error: ${status.status}: ${status.message}")
}
}
}
} catch (e: Exception) {
openVpnClient = null
throw e
}
}
override fun stopVpn() {
openVpnClient?.stop()
openVpnClient = null
}
override fun reconnectVpn(vpnBuilder: Builder) {
openVpnClient?.let {
it.establish = makeEstablish(vpnBuilder)
it.reconnect(0)
}
}
protected open fun parseConfig(config: JSONObject): ClientAPI_Config {
val openVpnConfig = ClientAPI_Config()
openVpnConfig.content = config.getJSONObject("openvpn_config_data").getString("config")
return openVpnConfig
}
private fun makeEstablish(vpnBuilder: Builder): (OpenVpnConfig.Builder) -> Int = { configBuilder ->
val openVpnConfig = configBuilder.build()
buildVpnInterface(openVpnConfig, vpnBuilder)
vpnBuilder.establish().use { tunFd ->
if (tunFd == null) {
throw VpnStartException("Create VPN interface: permission not granted or revoked")
}
return@use tunFd.detachFd()
}
}
}
@@ -0,0 +1,428 @@
package org.amnezia.vpn.protocol.openvpn
import android.net.ProxyInfo
import android.os.Build
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.getAndUpdate
import net.openvpn.ovpn3.ClientAPI_Config
import net.openvpn.ovpn3.ClientAPI_EvalConfig
import net.openvpn.ovpn3.ClientAPI_Event
import net.openvpn.ovpn3.ClientAPI_LogInfo
import net.openvpn.ovpn3.ClientAPI_OpenVPNClient
import net.openvpn.ovpn3.ClientAPI_Status
import net.openvpn.ovpn3.ClientAPI_StringVec
import net.openvpn.ovpn3.ClientAPI_TransportStats
import org.amnezia.vpn.protocol.ProtocolState
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
import org.amnezia.vpn.protocol.ProtocolState.RECONNECTING
import org.amnezia.vpn.util.Log
import org.amnezia.vpn.util.net.InetNetwork
import org.amnezia.vpn.util.net.parseInetAddress
private const val TAG = "OpenVpnClient"
private const val EMULATED_EXCLUDE_ROUTES = (1 shl 16)
class OpenVpnClient(
private val configBuilder: OpenVpnConfig.Builder,
private val state: MutableStateFlow<ProtocolState>,
private val getLocalNetworks: (Boolean) -> List<InetNetwork>,
internal var establish: (OpenVpnConfig.Builder) -> Int,
private val protect: (Int) -> Boolean,
private val onError: (String) -> Unit
) : ClientAPI_OpenVPNClient() {
/**************************************************************************
* Tun builder callbacks
**************************************************************************/
// Tun builder methods, loosely based on the Android VpnService.Builder
// abstraction. These methods comprise an abstraction layer that
// allows the OpenVPN C++ core to call out to external methods for
// establishing the tunnel, adding routes, etc.
// All methods returning bool use the return
// value to indicate success (true) or fail (false).
// tun_builder_new() should be called first, then arbitrary setter methods,
// and finally tun_builder_establish to return the socket descriptor
// for the session. IP addresses are pre-validated before being passed to
// these methods.
// This interface is based on Android's VpnService.Builder.
// Callback to construct a new tun builder
// Should be called first.
override fun tun_builder_new(): Boolean {
Log.d(TAG, "tun_builder_new")
configBuilder.clearAddresses()
return true
}
// Callback to set MTU of the VPN interface
// Never called more than once per tun_builder session.
override fun tun_builder_set_mtu(mtu: Int): Boolean {
Log.d(TAG, "tun_builder_set_mtu: $mtu")
configBuilder.setMtu(mtu)
return true
}
// Callback to add network address to VPN interface
// May be called more than once per tun_builder session
override fun tun_builder_add_address(
address: String, prefix_length: Int,
gateway: String, ipv6: Boolean, net30: Boolean
): Boolean {
Log.d(TAG, "tun_builder_add_address: $address, $prefix_length, $gateway, $ipv6, $net30")
configBuilder.addAddress(InetNetwork(address, prefix_length))
return true
}
// Callback to add route to VPN interface
// May be called more than once per tun_builder session
// metric is optional and should be ignored if < 0
override fun tun_builder_add_route(address: String, prefix_length: Int, metric: Int, ipv6: Boolean): Boolean {
Log.d(TAG, "tun_builder_add_route: $address, $prefix_length, $metric, $ipv6")
if (address == "remote_host") return false
configBuilder.addRoute(InetNetwork(address, prefix_length))
return true
}
// Callback to exclude route from VPN interface
// May be called more than once per tun_builder session
// metric is optional and should be ignored if < 0
override fun tun_builder_exclude_route(address: String, prefix_length: Int, metric: Int, ipv6: Boolean): Boolean {
Log.d(TAG, "tun_builder_exclude_route: $address, $prefix_length, $metric, $ipv6")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
configBuilder.excludeRoute(InetNetwork(address, prefix_length))
}
return true
}
// Callback to add DNS server to VPN interface
// May be called more than once per tun_builder session
// If reroute_dns is true, all DNS traffic should be routed over the
// tunnel, while if false, only DNS traffic that matches an added search
// domain should be routed.
// Guaranteed to be called after tun_builder_reroute_gw.
override fun tun_builder_add_dns_server(address: String, ipv6: Boolean): Boolean {
Log.d(TAG, "tun_builder_add_dns_server: $address, $ipv6")
configBuilder.addDnsServer(parseInetAddress(address))
return true
}
// Optional callback that indicates whether traffic of a certain
// address family (AF_INET or AF_INET6) should be
// blocked or allowed, to prevent unencrypted packet leakage when
// the tunnel is IPv4-only/IPv6-only, but the local machine
// has connectivity with the other protocol to the internet.
// Controlled by "block-ipv6" and block-ipv6 config var.
// If addresses are added for a family this setting should be
// ignored for that family
// See also Android's VPNService.Builder.allowFamily method
/* override fun tun_builder_set_allow_family(af: Int, allow: Boolean): Boolean {
Log.d(TAG, "tun_builder_set_allow_family: $af, $allow")
return true
} */
// Callback to set address of remote server
// Never called more than once per tun_builder session.
override fun tun_builder_set_remote_address(address: String, ipv6: Boolean): Boolean {
Log.d(TAG, "tun_builder_set_remote_address: $address, $ipv6")
return true
}
// Optional callback that indicates OSI layer, should be 2 or 3.
// Defaults to 3.
override fun tun_builder_set_layer(layer: Int): Boolean {
Log.d(TAG, "tun_builder_set_layer: $layer")
return layer == 3
}
// Callback to set the session name
// Never called more than once per tun_builder session.
override fun tun_builder_set_session_name(name: String): Boolean {
Log.d(TAG, "tun_builder_set_session_name: $name")
return true
}
// Callback to establish the VPN tunnel, returning a file descriptor
// to the tunnel, which the caller will henceforth own. Returns -1
// if the tunnel could not be established.
// Always called last after tun_builder session has been configured.
override fun tun_builder_establish(): Int {
Log.d(TAG, "tun_builder_establish")
return establish(configBuilder)
}
// Callback to reroute default gateway to VPN interface.
// ipv4 is true if the default route to be added should be IPv4.
// ipv6 is true if the default route to be added should be IPv6.
// flags are defined in RGWFlags (rgwflags.hpp).
// Never called more than once per tun_builder session.
override fun tun_builder_reroute_gw(ipv4: Boolean, ipv6: Boolean, flags: Long): Boolean {
Log.d(TAG, "tun_builder_reroute_gw: $ipv4, $ipv6, $flags")
if ((flags and EMULATED_EXCLUDE_ROUTES.toLong()) != 0L) return true
if (ipv4) {
configBuilder.addRoute(InetNetwork("0.0.0.0", 0))
}
if (ipv6) {
configBuilder.addRoute(InetNetwork("::", 0))
}
return true
}
// Callback to add search domain to DNS resolver
// May be called more than once per tun_builder session
// See tun_builder_add_dns_server above for description of
// reroute_dns parameter.
// Guaranteed to be called after tun_builder_reroute_gw.
override fun tun_builder_add_search_domain(domain: String): Boolean {
Log.d(TAG, "tun_builder_add_search_domain: $domain")
configBuilder.setSearchDomain(domain)
return true
}
// Callback to set the HTTP proxy
// Never called more than once per tun_builder session.
override fun tun_builder_set_proxy_http(host: String, port: Int): Boolean {
Log.d(TAG, "tun_builder_set_proxy_http: $host, $port")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
try {
configBuilder.setHttpProxy(ProxyInfo.buildDirectProxy(host, port))
} catch (e: Exception) {
Log.e(TAG, "Could not set proxy: ${e.message}")
return false
}
}
return true
}
// Callback to set the HTTPS proxy
// Never called more than once per tun_builder session.
override fun tun_builder_set_proxy_https(host: String, port: Int): Boolean {
Log.d(TAG, "tun_builder_set_proxy_https: $host, $port")
return false
}
// When the exclude local network option is enabled this
// function is called to get a list of local networks so routes
// to exclude them from the VPN network are generated
// This should be a list of CIDR networks (e.g. 192.168.0.0/24)
override fun tun_builder_get_local_networks(ipv6: Boolean): ClientAPI_StringVec {
Log.d(TAG, "tun_builder_get_local_networks: $ipv6")
val networks = ClientAPI_StringVec()
for (address in getLocalNetworks(ipv6)) {
networks.add(address.toString())
}
return networks
}
// Optional callback to set default value for route metric.
// Guaranteed to be called before other methods that deal
// with routes such as tun_builder_add_route and
// tun_builder_reroute_gw. Route metric is ignored
// if < 0.
/* override fun tun_builder_set_route_metric_default(metric: Int): Boolean {
Log.d(TAG, "tun_builder_set_route_metric_default: $metric")
return super.tun_builder_set_route_metric_default(metric)
} */
// Callback to add a host which should bypass the proxy
// May be called more than once per tun_builder session
/* override fun tun_builder_add_proxy_bypass(bypass_host: String): Boolean {
Log.d(TAG, "tun_builder_add_proxy_bypass: $bypass_host")
return super.tun_builder_add_proxy_bypass(bypass_host)
} */
// Callback to set the proxy "Auto Config URL"
// Never called more than once per tun_builder session.
/* override fun tun_builder_set_proxy_auto_config_url(url: String): Boolean {
Log.d(TAG, "tun_builder_set_proxy_auto_config_url: $url")
return super.tun_builder_set_proxy_auto_config_url(url)
} */
// Callback to add Windows WINS server to VPN interface.
// WINS server addresses are always IPv4.
// May be called more than once per tun_builder session.
// Guaranteed to be called after tun_builder_reroute_gw.
/* override fun tun_builder_add_wins_server(address: String): Boolean {
Log.d(TAG, "tun_builder_add_wins_server: $address")
return super.tun_builder_add_wins_server(address)
} */
// Optional callback to set a DNS suffix on tun/tap adapter.
// Currently only implemented on Windows, where it will
// set the "Connection-specific DNS Suffix" property on
// the TAP driver.
/* override fun tun_builder_set_adapter_domain_suffix(name: String): Boolean {
Log.d(TAG, "tun_builder_set_adapter_domain_suffix: $name")
return super.tun_builder_set_adapter_domain_suffix(name)
} */
// Return true if tun interface may be persisted, i.e. rolled
// into a new session with properties untouched. This method
// is only called after all other tests of persistence
// allowability succeed, therefore it can veto persistence.
// If persistence is ultimately enabled,
// tun_builder_establish_lite() will be called. Otherwise,
// tun_builder_establish() will be called.
/* override fun tun_builder_persist(): Boolean {
Log.d(TAG, "tun_builder_persist")
return super.tun_builder_persist()
} */
// Indicates a reconnection with persisted tun state.
/* override fun tun_builder_establish_lite() {
Log.d(TAG, "tun_builder_establish_lite")
super.tun_builder_establish_lite()
} */
// Indicates that tunnel is being torn down.
// If disconnect == true, then the teardown is occurring
// prior to final disconnect.
/* override fun tun_builder_teardown(disconnect: Boolean) {
Log.d(TAG, "tun_builder_teardown: $disconnect")
super.tun_builder_teardown(disconnect)
} */
/**************************************************************************
* Connection control methods
**************************************************************************/
// Parse OpenVPN configuration file.
override fun eval_config(arg0: ClientAPI_Config): ClientAPI_EvalConfig {
Log.d(TAG, "eval_config")
return super.eval_config(arg0)
}
// Primary VPN client connect method, doesn't return until disconnect.
// Should be called by a worker thread. This method will make callbacks
// to event() and log() functions. Make sure to call eval_config()
// and possibly provide_creds() as well before this function.
override fun connect(): ClientAPI_Status {
Log.d(TAG, "connect")
return super.connect()
}
// Callback to "protect" a socket from being routed through the tunnel.
// Will be called from the thread executing connect().
// The remote and ipv6 are the remote host this socket will connect to
override fun socket_protect(socket: Int, remote: String, ipv6: Boolean): Boolean {
Log.d(TAG, "socket_protect: $socket, $remote, $ipv6")
return protect(socket)
}
// Stop the client. Only meaningful when connect() is running.
// May be called asynchronously from a different thread
// when connect() is running.
override fun stop() {
Log.d(TAG, "stop")
super.stop()
}
// Pause the client -- useful to avoid continuous reconnection attempts
// when network is down. May be called from a different thread
// when connect() is running.
override fun pause(reason: String) {
Log.d(TAG, "pause: $reason")
super.pause(reason)
}
// Resume the client after it has been paused. May be called from a
// different thread when connect() is running.
override fun resume() {
Log.d(TAG, "resume")
super.resume()
}
// Do a disconnect/reconnect cycle n seconds from now. May be called
// from a different thread when connect() is running.
override fun reconnect(seconds: Int) {
Log.d(TAG, "reconnect: $seconds")
super.reconnect(seconds)
}
// When a connection is close to timeout, the core will call this
// method. If it returns false, the core will disconnect with a
// CONNECTION_TIMEOUT event. If true, the core will enter a PAUSE
// state.
override fun pause_on_connection_timeout(): Boolean {
Log.d(TAG, "pause_on_connection_timeout")
return false
}
// Return information about the most recent connection. Should be called
// after an event of type "CONNECTED".
/* override fun connection_info(): ClientAPI_ConnectionInfo {
Log.d(TAG, "connection_info")
return super.connection_info()
} */
/**************************************************************************
* Status callbacks
**************************************************************************/
// Callback for delivering events during connect() call.
// Will be called from the thread executing connect().
override fun event(event: ClientAPI_Event) {
val name = event.name
val info = event.info
Log.d(TAG, "OpenVpn event: $name: $info")
when (name) {
"COMPRESSION_ENABLED", "WARN" -> Log.w(TAG, "$name: $info")
"CONNECTED" -> state.value = CONNECTED
"DISCONNECTED" -> state.value = DISCONNECTED
"RECONNECTING" -> {
state.getAndUpdate { state ->
if (state == DISCONNECTED || state == CONNECTED) RECONNECTING
else state
}
}
}
if (event.error || event.fatal) {
state.value = DISCONNECTED
onError("OpenVpn ${if (event.error) "ERROR" else "FATAL"}: $name: $info")
}
}
// Callback for logging.
// Will be called from the thread executing connect().
override fun log(arg0: ClientAPI_LogInfo) {
arg0.text.dropLastWhile { it == '\n' }.let {
Log.d(TAG, "OpenVpnLog: $it")
}
}
/**************************************************************************
* Stats methods
**************************************************************************/
// return transport stats only
override fun transport_stats(): ClientAPI_TransportStats {
Log.d(TAG, "transport_stats")
return super.transport_stats()
}
// return a stats value, index should be >= 0 and < stats_n()
/* override fun stats_value(index: Int): Long {
Log.d(TAG, "stats_value: $index")
return super.stats_value(index)
} */
// return all stats in a bundle
/* override fun stats_bundle(): ClientAPI_LLVector {
Log.d(TAG, "stats_bundle")
return super.stats_bundle()
} */
// return tun stats only
/* override fun tun_stats(): ClientAPI_InterfaceStats {
Log.d(TAG, "tun_stats")
return super.tun_stats()
} */
// post control channel message
/* override fun post_cc_msg(msg: String) {
Log.d(TAG, "post_cc_msg: $msg")
super.post_cc_msg(msg)
} */
}
@@ -0,0 +1,20 @@
package org.amnezia.vpn.protocol.openvpn
import org.amnezia.vpn.protocol.ProtocolConfig
private const val OPENVPN_DEFAULT_MTU = 1500
class OpenVpnConfig private constructor(
protocolConfigBuilder: ProtocolConfig.Builder
) : ProtocolConfig(protocolConfigBuilder) {
class Builder : ProtocolConfig.Builder(false) {
override var mtu: Int = OPENVPN_DEFAULT_MTU
override fun build(): OpenVpnConfig = OpenVpnConfig(this)
}
companion object {
inline fun build(block: Builder.() -> Unit): OpenVpnConfig = Builder().apply(block).build()
}
}
@@ -0,0 +1,18 @@
plugins {
id(libs.plugins.android.library.get().pluginId)
id(libs.plugins.kotlin.android.get().pluginId)
}
kotlin {
jvmToolchain(17)
}
android {
namespace = "org.amnezia.vpn.protocol"
}
dependencies {
compileOnly(project(":utils"))
implementation(libs.androidx.annotation)
implementation(libs.kotlinx.coroutines)
}
@@ -0,0 +1,9 @@
package org.amnezia.vpn.protocol
sealed class ProtocolException(message: String? = null, cause: Throwable? = null) : Exception(message, cause)
class LoadLibraryException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
class BadConfigException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
class VpnStartException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
class VpnException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
@@ -0,0 +1,217 @@
package org.amnezia.vpn.protocol
import android.annotation.SuppressLint
import android.content.Context
import android.net.IpPrefix
import android.net.VpnService
import android.net.VpnService.Builder
import android.os.Build
import android.system.OsConstants
import androidx.annotation.RequiresApi
import java.io.File
import java.io.FileOutputStream
import java.util.zip.ZipFile
import kotlinx.coroutines.flow.MutableStateFlow
import org.amnezia.vpn.util.Log
import org.amnezia.vpn.util.net.InetNetwork
import org.amnezia.vpn.util.net.IpRange
import org.amnezia.vpn.util.net.IpRangeSet
import org.json.JSONObject
private const val TAG = "Protocol"
const val VPN_SESSION_NAME = "AmneziaVPN"
private const val SPLIT_TUNNEL_DISABLE = 0
private const val SPLIT_TUNNEL_INCLUDE = 1
private const val SPLIT_TUNNEL_EXCLUDE = 2
abstract class Protocol {
abstract val statistics: Statistics
protected lateinit var state: MutableStateFlow<ProtocolState>
protected lateinit var onError: (String) -> Unit
open fun initialize(context: Context, state: MutableStateFlow<ProtocolState>, onError: (String) -> Unit) {
this.state = state
this.onError = onError
}
abstract fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean)
abstract fun stopVpn()
abstract fun reconnectVpn(vpnBuilder: Builder)
protected fun ProtocolConfig.Builder.configSplitTunneling(config: JSONObject) {
if (!allowSplitTunneling) {
Log.i(TAG, "Global address split tunneling is prohibited, " +
"only tunneling from the protocol config is used")
return
}
val splitTunnelType = config.optInt("splitTunnelType")
if (splitTunnelType == SPLIT_TUNNEL_DISABLE) return
val splitTunnelSites = config.getJSONArray("splitTunnelSites")
when (splitTunnelType) {
SPLIT_TUNNEL_INCLUDE -> {
// remove default routes, if any
removeRoute(InetNetwork("0.0.0.0", 0))
removeRoute(InetNetwork("::", 0))
// add routes from config
for (i in 0 until splitTunnelSites.length()) {
val address = InetNetwork.parse(splitTunnelSites.getString(i))
addRoute(address)
}
}
SPLIT_TUNNEL_EXCLUDE -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// exclude routes from config
for (i in 0 until splitTunnelSites.length()) {
val address = InetNetwork.parse(splitTunnelSites.getString(i))
excludeRoute(address)
}
} else {
// For older versions of Android, build a list of subnets without excluded addresses
val ipRangeSet = IpRangeSet()
ipRangeSet.remove(IpRange("127.0.0.0", 8))
for (i in 0 until splitTunnelSites.length()) {
val address = InetNetwork.parse(splitTunnelSites.getString(i))
ipRangeSet.remove(IpRange(address))
}
// remove default routes, if any
removeRoute(InetNetwork("0.0.0.0", 0))
removeRoute(InetNetwork("::", 0))
ipRangeSet.subnets().forEach(::addRoute)
addRoute(InetNetwork("2000::", 3))
}
}
}
}
protected open fun buildVpnInterface(config: ProtocolConfig, vpnBuilder: Builder) {
vpnBuilder.setSession(VPN_SESSION_NAME)
for (addr in config.addresses) {
Log.d(TAG, "addAddress: $addr")
vpnBuilder.addAddress(addr)
}
for (addr in config.dnsServers) {
Log.d(TAG, "addDnsServer: $addr")
vpnBuilder.addDnsServer(addr)
}
// fix for Samsung android ignoring DNS servers outside the VPN route range
if (Build.BRAND == "samsung") {
for (addr in config.dnsServers) {
Log.d(TAG, "addRoute: $addr")
vpnBuilder.addRoute(InetNetwork(addr))
}
}
config.searchDomain?.let {
Log.d(TAG, "addSearchDomain: $it")
vpnBuilder.addSearchDomain(it)
}
for (addr in config.routes) {
Log.d(TAG, "addRoute: $addr")
vpnBuilder.addRoute(addr)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
for (addr in config.excludedRoutes) {
Log.d(TAG, "excludeRoute: $addr")
vpnBuilder.excludeRoute(addr)
}
}
for (app in config.excludedApplications) {
Log.d(TAG, "addDisallowedApplication: $app")
vpnBuilder.addDisallowedApplication(app)
}
Log.d(TAG, "setMtu: ${config.mtu}")
vpnBuilder.setMtu(config.mtu)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
config.httpProxy?.let {
Log.d(TAG, "setHttpProxy: $it")
vpnBuilder.setHttpProxy(it)
}
}
if (config.allowAllAF) {
Log.d(TAG, "allowFamily")
vpnBuilder.allowFamily(OsConstants.AF_INET)
vpnBuilder.allowFamily(OsConstants.AF_INET6)
}
Log.d(TAG, "setBlocking: ${config.blockingMode}")
vpnBuilder.setBlocking(config.blockingMode)
vpnBuilder.setUnderlyingNetworks(null)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
vpnBuilder.setMetered(false)
}
companion object {
private fun extractLibrary(context: Context, libraryName: String, destination: File): Boolean {
Log.d(TAG, "Extracting library: $libraryName")
val apks = hashSetOf<String>()
context.applicationInfo.run {
sourceDir?.let { apks += it }
splitSourceDirs?.let { apks += it }
}
for (abi in Build.SUPPORTED_ABIS) {
for (apk in apks) {
ZipFile(File(apk), ZipFile.OPEN_READ).use { zipFile ->
val mappedName = System.mapLibraryName(libraryName)
val libraryZipPath = listOf("lib", abi, mappedName).joinToString(File.separator)
val zipEntry = zipFile.getEntry(libraryZipPath)
zipEntry?.let {
Log.d(TAG, "Extracting apk:/$libraryZipPath to ${destination.absolutePath}")
FileOutputStream(destination).use { outStream ->
zipFile.getInputStream(zipEntry).use { inStream ->
inStream.copyTo(outStream, 32 * 1024)
outStream.fd.sync()
}
}
}
return true
}
}
}
return false
}
@SuppressLint("UnsafeDynamicallyLoadedCode")
fun loadSharedLibrary(context: Context, libraryName: String) {
Log.d(TAG, "Loading library: $libraryName")
try {
System.loadLibrary(libraryName)
return
} catch (_: UnsatisfiedLinkError) {
Log.d(TAG, "Failed to load library, try to extract it from apk")
}
var tempFile: File? = null
try {
tempFile = File.createTempFile("lib", ".so", context.codeCacheDir)
if (extractLibrary(context, libraryName, tempFile)) {
System.load(tempFile.absolutePath)
return
}
} catch (e: Exception) {
throw LoadLibraryException("Failed to load library apk: $libraryName", e)
} finally {
tempFile?.delete()
}
}
}
}
private fun VpnService.Builder.addAddress(addr: InetNetwork) = addAddress(addr.address, addr.mask)
private fun VpnService.Builder.addRoute(addr: InetNetwork) = addRoute(addr.address, addr.mask)
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private fun VpnService.Builder.excludeRoute(addr: InetNetwork) = excludeRoute(IpPrefix(addr.address, addr.mask))
@@ -0,0 +1,113 @@
package org.amnezia.vpn.protocol
import android.net.ProxyInfo
import android.os.Build
import androidx.annotation.RequiresApi
import java.net.InetAddress
import org.amnezia.vpn.util.net.InetNetwork
open class ProtocolConfig protected constructor(
val addresses: Set<InetNetwork>,
val dnsServers: Set<InetAddress>,
val searchDomain: String?,
val routes: Set<InetNetwork>,
val excludedRoutes: Set<InetNetwork>,
val excludedApplications: Set<String>,
val httpProxy: ProxyInfo?,
val allowAllAF: Boolean,
val blockingMode: Boolean,
val mtu: Int
) {
protected constructor(builder: Builder) : this(
builder.addresses,
builder.dnsServers,
builder.searchDomain,
builder.routes,
builder.excludedRoutes,
builder.excludedApplications,
builder.httpProxy,
builder.allowAllAF,
builder.blockingMode,
builder.mtu
)
open class Builder(blockingMode: Boolean) {
internal val addresses: MutableSet<InetNetwork> = hashSetOf()
internal val dnsServers: MutableSet<InetAddress> = hashSetOf()
internal val routes: MutableSet<InetNetwork> = hashSetOf()
internal val excludedRoutes: MutableSet<InetNetwork> = hashSetOf()
internal val excludedApplications: MutableSet<String> = hashSetOf()
internal var searchDomain: String? = null
private set
internal var httpProxy: ProxyInfo? = null
private set
internal var allowAllAF: Boolean = false
private set
internal var blockingMode: Boolean = blockingMode
private set
internal var allowSplitTunneling: Boolean = true
private set
open var mtu: Int = 0
protected set
fun addAddress(addr: InetNetwork) = apply { this.addresses += addr }
fun addAddresses(addresses: Collection<InetNetwork>) = apply { this.addresses += addresses }
fun clearAddresses() = apply { this.addresses.clear() }
fun addDnsServer(dnsServer: InetAddress) = apply { this.dnsServers += dnsServer }
fun addDnsServers(dnsServers: Collection<InetAddress>) = apply { this.dnsServers += dnsServers }
fun setSearchDomain(domain: String) = apply { this.searchDomain = domain }
fun addRoute(route: InetNetwork) = apply { this.routes += route }
fun addRoutes(routes: Collection<InetNetwork>) = apply { this.routes += routes }
fun removeRoute(route: InetNetwork) = apply { this.routes.remove(route) }
fun clearRoutes() = apply { this.routes.clear() }
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun excludeRoute(route: InetNetwork) = apply { this.excludedRoutes += route }
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun excludeRoutes(routes: Collection<InetNetwork>) = apply { this.excludedRoutes += routes }
fun excludeApplication(application: String) = apply { this.excludedApplications += application }
fun excludeApplications(applications: Collection<String>) = apply { this.excludedApplications += applications }
@RequiresApi(Build.VERSION_CODES.Q)
fun setHttpProxy(httpProxy: ProxyInfo) = apply { this.httpProxy = httpProxy }
fun setAllowAllAF(allowAllAF: Boolean) = apply { this.allowAllAF = allowAllAF }
fun setBlockingMode(blockingMode: Boolean) = apply { this.blockingMode = blockingMode }
fun disableSplitTunneling() = apply { this.allowSplitTunneling = false }
fun setMtu(mtu: Int) = apply { this.mtu = mtu }
private fun validate() {
val errorMessage = StringBuilder()
with(errorMessage) {
if (addresses.isEmpty()) appendLine("VPN interface network address not specified.")
if (routes.isEmpty()) appendLine("VPN interface route not specified.")
if (mtu == 0) appendLine("MTU not set.")
}
if (errorMessage.isNotEmpty()) throw BadConfigException(errorMessage.toString())
}
open fun build(): ProtocolConfig = validate().run { ProtocolConfig(this@Builder) }
}
companion object {
inline fun build(blockingMode: Boolean, block: Builder.() -> Unit): ProtocolConfig =
Builder(blockingMode).apply(block).build()
}
}
@@ -0,0 +1,11 @@
package org.amnezia.vpn.protocol
// keep synchronized with client/platforms/android/android_controller.h ConnectionState
enum class ProtocolState {
CONNECTED,
CONNECTING,
DISCONNECTED,
DISCONNECTING,
RECONNECTING,
UNKNOWN
}
@@ -0,0 +1,50 @@
package org.amnezia.vpn.protocol
import android.os.Bundle
private const val RX_BYTES_KEY = "rxBytes"
private const val TX_BYTES_KEY = "txBytes"
@Suppress("DataClassPrivateConstructor")
data class Statistics private constructor(
val rxBytes: Long = 0L,
val txBytes: Long = 0L
) {
private constructor(builder: Builder) : this(builder.rxBytes, builder.txBytes)
@Suppress("SuspiciousEqualsCombination")
fun isEmpty(): Boolean = this === EMPTY_STATISTICS || this == EMPTY_STATISTICS
class Builder {
var rxBytes: Long = 0L
private set
var txBytes: Long = 0L
private set
fun setRxBytes(rxBytes: Long) = apply { this.rxBytes = rxBytes }
fun setTxBytes(txBytes: Long) = apply { this.txBytes = txBytes }
fun build(): Statistics =
if (rxBytes + txBytes == 0L) EMPTY_STATISTICS
else Statistics(this)
}
companion object {
val EMPTY_STATISTICS: Statistics = Statistics()
inline fun build(block: Builder.() -> Unit): Statistics = Builder().apply(block).build()
}
}
fun Bundle.putStatistics(statistics: Statistics) {
putLong(RX_BYTES_KEY, statistics.rxBytes)
putLong(TX_BYTES_KEY, statistics.txBytes)
}
fun Bundle.getStatistics(): Statistics =
Statistics.build {
setRxBytes(getLong(RX_BYTES_KEY))
setTxBytes(getLong(TX_BYTES_KEY))
}
@@ -0,0 +1,34 @@
package org.amnezia.vpn.protocol
import android.os.Bundle
private const val STATE_KEY = "state"
@Suppress("DataClassPrivateConstructor")
data class Status private constructor(
val state: ProtocolState
) {
private constructor(builder: Builder) : this(builder.state)
class Builder {
lateinit var state: ProtocolState
private set
fun setState(state: ProtocolState) = apply { this.state = state }
fun build(): Status = Status(this)
}
companion object {
inline fun build(block: Builder.() -> Unit): Status = Builder().apply(block).build()
}
}
fun Bundle.putStatus(status: Status) {
putInt(STATE_KEY, status.state.ordinal)
}
fun Bundle.getStatus(): Status =
Status.build {
setState(ProtocolState.entries[getInt(STATE_KEY)])
}
+25
View File
@@ -0,0 +1,25 @@
plugins {
id(libs.plugins.android.library.get().pluginId)
id("property-delegate")
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
val qtAndroidDir: String by gradleProperties
android {
namespace = "org.qtproject.qt.android.binding"
sourceSets {
getByName("main") {
java.setSrcDirs(listOf("$qtAndroidDir/src"))
res.setSrcDirs(listOf("$qtAndroidDir/res"))
}
}
}
dependencies {
implementation(fileTree(mapOf("dir" to "../libs", "include" to listOf("*.jar", "*.aar"))))
}
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CameraActivity">
<androidx.camera.view.PreviewView
android:id="@+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" />
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.camera.view.PreviewView
android:id="@+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

@@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat.Dialog">
<style name="NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="Translucent" parent="NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowCloseOnTouchOutside">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="ThemeOverlay.AppCompat.DayNight" parent="ThemeOverlay.AppCompat.Light"/>
</resources>
</resources>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<exclude domain="sharedpref" path="." />
</full-backup-content>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
<cloud-backup>
<exclude domain="sharedpref" path="." />
</cloud-backup>
<device-transfer>
<exclude domain="sharedpref" path="." />
</device-transfer>
</data-extraction-rules>
-4
View File
@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path name="cache" path="/" />
</paths>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="files_path" path="/"/>
</paths>
@@ -1,132 +0,0 @@
{
"formatVersion": 1,
"database": {
"version": 1000,
"identityHash": "14b379f7776710b79b9d617090efe40e",
"entities": [
{
"tableName": "Profile",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `host` TEXT NOT NULL, `remotePort` INTEGER NOT NULL, `password` TEXT NOT NULL, `method` TEXT NOT NULL, `remoteDns` TEXT NOT NULL, `udpdns` INTEGER NOT NULL, `ipv6` INTEGER NOT NULL, `tx` INTEGER NOT NULL, `rx` INTEGER NOT NULL, `userOrder` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "host",
"columnName": "host",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "remotePort",
"columnName": "remotePort",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "password",
"columnName": "password",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "method",
"columnName": "method",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "remoteDns",
"columnName": "remoteDns",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "udpdns",
"columnName": "udpdns",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "ipv6",
"columnName": "ipv6",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "tx",
"columnName": "tx",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "rx",
"columnName": "rx",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "userOrder",
"columnName": "userOrder",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "KeyValuePair",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `valueType` INTEGER NOT NULL, `value` BLOB NOT NULL, PRIMARY KEY(`key`))",
"fields": [
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "valueType",
"columnName": "valueType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "BLOB",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"key"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '14b379f7776710b79b9d617090efe40e')"
]
}
}
@@ -1,46 +0,0 @@
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "f1aab1fb633378621635c344dbc8ac7b",
"entities": [
{
"tableName": "KeyValuePair",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `valueType` INTEGER NOT NULL, `value` BLOB NOT NULL, PRIMARY KEY(`key`))",
"fields": [
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "valueType",
"columnName": "valueType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "BLOB",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"key"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f1aab1fb633378621635c344dbc8ac7b')"
]
}
}
-21
View File
@@ -1,21 +0,0 @@
pluginManagement {
repositories {
google()
mavenCentral()
jcenter()
gradlePluginPortal()
maven { url 'https://jitpack.io' }
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
jcenter()
maven { url 'https://jitpack.io' }
}
}
include ':shadowsocks'
+60
View File
@@ -0,0 +1,60 @@
import com.android.build.api.dsl.SettingsExtension
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
includeBuild("./gradle/plugins")
}
@Suppress("UnstableApiUsage")
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
includeBuild("./gradle/plugins")
plugins {
id("com.android.settings") version "8.2.0"
id("settings-property-delegate")
}
rootProject.name = "AmneziaVPN"
rootProject.buildFileName = "build.gradle.kts"
include(":qt")
include(":utils")
include(":protocolApi")
include(":wireguard")
include(":awg")
include(":openvpn")
include(":cloak")
// get values from gradle or local properties
val androidBuildToolsVersion: String by gradleProperties
val androidCompileSdkVersion: String by gradleProperties
val androidNdkVersion: String by gradleProperties
val qtMinSdkVersion: String by gradleProperties
// set default values for all modules
configure<SettingsExtension> {
buildToolsVersion = androidBuildToolsVersion
compileSdk = androidCompileSdkVersion.substringAfter('-').toInt()
minSdk = qtMinSdkVersion.toInt()
ndkVersion = androidNdkVersion
}
// stop Gradle running by androiddeployqt
gradle.taskGraph.whenReady {
if (providers.environmentVariable("ANDROIDDEPLOYQT_RUN").isPresent
&& !providers.systemProperty("explicitRun").isPresent) {
allTasks.forEach { it.enabled = false }
}
}

Some files were not shown because too many files have changed in this diff Show More