├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── font
│ │ │ │ ├── open_sans_bold.ttf
│ │ │ │ ├── open_sans_light.ttf
│ │ │ │ ├── open_sans_italic.ttf
│ │ │ │ ├── open_sans_regular.ttf
│ │ │ │ ├── open_sans_semibold.ttf
│ │ │ │ ├── open_sans_extra_bold.ttf
│ │ │ │ ├── open_sans_bold_italic.ttf
│ │ │ │ ├── open_sans_light_italic.ttf
│ │ │ │ ├── open_sans_semibold_italic.ttf
│ │ │ │ └── open_sans_extra_bold_italic.ttf
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ ├── ic_launcher_background.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ ├── ic_launcher_background.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── drawable-hdpi
│ │ │ │ └── logo_black.png
│ │ │ ├── drawable-mdpi
│ │ │ │ └── logo_black.png
│ │ │ ├── drawable-xhdpi
│ │ │ │ └── logo_black.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ ├── ic_launcher_background.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ ├── ic_launcher_background.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── drawable-xxhdpi
│ │ │ │ ├── logo_black.png
│ │ │ │ ├── surfnet_logo.png
│ │ │ │ ├── external_provider.png
│ │ │ │ ├── maintenance_icon.png
│ │ │ │ ├── icon_shield_access_white_full.png
│ │ │ │ └── icon_shield_internet_white_full.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ ├── ic_launcher_background.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── values
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── ids.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── content_description.xml
│ │ │ │ └── colors.xml
│ │ │ ├── drawable
│ │ │ │ ├── dialog_background.xml
│ │ │ │ ├── loading_gradient.xml
│ │ │ │ ├── delete_icon.xml
│ │ │ │ ├── button_bg.xml
│ │ │ │ ├── dialog_button_bg.xml
│ │ │ │ ├── bg_search.xml
│ │ │ │ ├── scrollbar_thumb.xml
│ │ │ │ ├── access_type_bg.xml
│ │ │ │ ├── ic_chevron_right.xml
│ │ │ │ ├── ic_add.xml
│ │ │ │ ├── ic_arrow_drop_down.xml
│ │ │ │ ├── ic_warning.xml
│ │ │ │ ├── switch_thumb.xml
│ │ │ │ ├── ic_institute.xml
│ │ │ │ ├── bg_progressbar_indeterminate.xml
│ │ │ │ ├── ic_search.xml
│ │ │ │ ├── ic_vpn_profile.xml
│ │ │ │ ├── ic_secure_internet.xml
│ │ │ │ ├── ic_server.xml
│ │ │ │ ├── switch_track.xml
│ │ │ │ ├── bg_progress_indeterminate_layers.xml
│ │ │ │ ├── ic_help.xml
│ │ │ │ ├── ic_settings.xml
│ │ │ │ └── ic_connection_status_connecting.xml
│ │ │ ├── interpolator
│ │ │ │ ├── progress_indeterminate_horizontal_rect1_scalex.xml
│ │ │ │ ├── progress_indeterminate_horizontal_rect1_translatex.xml
│ │ │ │ ├── progress_indeterminate_horizontal_rect2_translatex.xml
│ │ │ │ └── progress_indeterminate_horizontal_rect2_scalex.xml
│ │ │ ├── anim
│ │ │ │ ├── progress_indeterminate_horizontal_rect1.xml
│ │ │ │ ├── progress_indeterminate_horizontal_rect2.xml
│ │ │ │ ├── fade_in.xml
│ │ │ │ └── fade_out.xml
│ │ │ ├── layout
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── activity_settings.xml
│ │ │ │ ├── activity_openvpn_logs.xml
│ │ │ │ ├── activity_licenses.xml
│ │ │ │ ├── list_item_provider.xml
│ │ │ │ ├── activity_api_logs.xml
│ │ │ │ ├── fragment_profile_selection.xml
│ │ │ │ ├── list_item_message.xml
│ │ │ │ ├── dialog_error.xml
│ │ │ │ └── list_item_profile.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── color
│ │ │ │ └── bg_big_button.xml
│ │ │ ├── values-de
│ │ │ │ └── content_description.xml
│ │ │ ├── values-ca
│ │ │ │ └── content_description.xml
│ │ │ ├── values-es
│ │ │ │ └── content_description.xml
│ │ │ └── menu
│ │ │ │ └── logmenu.xml
│ │ └── java
│ │ │ └── nl
│ │ │ └── eduvpn
│ │ │ └── app
│ │ │ ├── livedata
│ │ │ ├── ByteCount.kt
│ │ │ ├── IPs.kt
│ │ │ ├── openvpn
│ │ │ │ └── ByteCountLiveData.kt
│ │ │ ├── UnlessDisconnectedLiveData.kt
│ │ │ └── ConnectionTimeLiveData.kt
│ │ │ ├── utils
│ │ │ ├── Listener.kt
│ │ │ ├── WireGuardTunnel.kt
│ │ │ └── serializer
│ │ │ │ ├── DateSerializer.kt
│ │ │ │ └── TranslatableStringSerializer.kt
│ │ │ ├── entity
│ │ │ ├── VPNConfig.kt
│ │ │ ├── exception
│ │ │ │ ├── ExceptionMessage.kt
│ │ │ │ ├── EduVPNException.kt
│ │ │ │ └── CommonException.kt
│ │ │ ├── CookieAndStringData.kt
│ │ │ ├── Profile.kt
│ │ │ ├── CertExpiryTimes.kt
│ │ │ ├── SerializedVpnConfig.kt
│ │ │ ├── CookieAndProfileMapData.kt
│ │ │ ├── ServerList.kt
│ │ │ ├── OrganizationList.kt
│ │ │ ├── Organization.kt
│ │ │ ├── AuthorizationType.kt
│ │ │ ├── Instance.kt
│ │ │ ├── CurrentServer.kt
│ │ │ └── AddedServers.kt
│ │ │ ├── viewmodel
│ │ │ ├── ApiLogsViewModel.kt
│ │ │ ├── SettingsViewModel.kt
│ │ │ ├── ProfileSelectionViewModel.kt
│ │ │ ├── ConnectionState.kt
│ │ │ ├── AddServerViewModel.kt
│ │ │ └── ViewModelFactory.kt
│ │ │ ├── DisconnectVPNBroadcastReceiver.kt
│ │ │ ├── inject
│ │ │ ├── ViewModelKey.kt
│ │ │ ├── EduVPNComponent.kt
│ │ │ └── ViewModelModule.kt
│ │ │ ├── base
│ │ │ ├── BaseActivity.kt
│ │ │ └── BaseFragment.kt
│ │ │ ├── Constants.kt
│ │ │ ├── ApiLogsActivity.kt
│ │ │ ├── service
│ │ │ ├── VPNService.kt
│ │ │ └── OrganizationService.kt
│ │ │ ├── OpenVpnLogsActivity.kt
│ │ │ ├── adapter
│ │ │ ├── viewholder
│ │ │ │ └── ProfileViewHolder.kt
│ │ │ └── ProfileAdapter.kt
│ │ │ ├── LicenseActivity.kt
│ │ │ ├── EduVPNApplication.java
│ │ │ ├── CertExpiredBroadcastReceiver.kt
│ │ │ └── SettingsActivity.kt
│ ├── gov
│ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ └── logo_black.png
│ │ │ ├── drawable-mdpi
│ │ │ └── logo_black.png
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_round.webp
│ │ │ └── ic_launcher_foreground.webp
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_round.webp
│ │ │ └── ic_launcher_foreground.webp
│ │ │ ├── drawable-xhdpi
│ │ │ └── logo_black.png
│ │ │ ├── drawable-xxhdpi
│ │ │ └── logo_black.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_round.webp
│ │ │ └── ic_launcher_foreground.webp
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_round.webp
│ │ │ └── ic_launcher_foreground.webp
│ │ │ ├── drawable-xxxhdpi
│ │ │ └── logo_black.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ ├── ic_launcher_round.webp
│ │ │ └── ic_launcher_foreground.webp
│ │ │ ├── values
│ │ │ ├── ic_launcher_background.xml
│ │ │ ├── strings.xml
│ │ │ └── colors.xml
│ │ │ └── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ ├── home
│ │ └── res
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_round.png
│ │ │ └── ic_launcher_background.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_round.png
│ │ │ └── ic_launcher_background.png
│ │ │ ├── drawable-hdpi
│ │ │ └── logo_black.png
│ │ │ ├── drawable-mdpi
│ │ │ └── logo_black.png
│ │ │ ├── drawable-xhdpi
│ │ │ └── logo_black.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_round.png
│ │ │ └── ic_launcher_background.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_round.png
│ │ │ └── ic_launcher_background.png
│ │ │ ├── drawable-xxhdpi
│ │ │ └── logo_black.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_round.png
│ │ │ └── ic_launcher_background.png
│ │ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ │ ├── values
│ │ │ ├── strings.xml
│ │ │ └── colors.xml
│ │ │ ├── values-de
│ │ │ └── strings.xml
│ │ │ ├── values-es
│ │ │ └── strings.xml
│ │ │ └── drawable
│ │ │ ├── ic_application_logo.xml
│ │ │ └── ic_launcher_foreground.xml
│ ├── dev
│ │ └── res
│ │ │ └── values
│ │ │ ├── strings.xml
│ │ │ └── colors.xml
│ └── androidTest
│ │ └── java
│ │ └── nl
│ │ └── eduvpn
│ │ └── app
│ │ ├── UnitTestSuite.java
│ │ ├── utils
│ │ └── ParcelableTest.kt
│ │ ├── WaitUntilGoneAction.kt
│ │ └── ui_test
│ │ └── BrowserTest.kt
└── proguard-rules.pro
├── common
├── .gitignore
├── consumer-rules.pro
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── org
│ │ └── eduvpn
│ │ └── common
│ │ ├── ServerType.java
│ │ ├── Protocol.java
│ │ ├── DataErrorTuple.java
│ │ └── FailoverResult.java
├── proguard-rules.pro
└── build.gradle
├── fastlane
└── metadata
│ └── android
│ └── en-US
│ ├── title.txt
│ ├── changelogs
│ ├── 16.txt
│ ├── 11.txt
│ ├── 29.txt
│ ├── 15.txt
│ ├── 21.txt
│ ├── 30.txt
│ ├── 7.txt
│ ├── 23.txt
│ ├── 22.txt
│ ├── 26.txt
│ ├── 12.txt
│ ├── 17.txt
│ ├── 25.txt
│ ├── 18.txt
│ ├── 31.txt
│ ├── 14.txt
│ ├── 24.txt
│ ├── 19.txt
│ ├── 20.txt
│ ├── 13.txt
│ ├── 27.txt
│ ├── 9.txt
│ ├── 28.txt
│ ├── 6.txt
│ └── 10.txt
│ ├── short_description.txt
│ ├── images
│ ├── icon.png
│ ├── featureGraphic.png
│ └── phoneScreenshots
│ │ ├── 090-Settings.jpg
│ │ ├── 080-ConnectionInfo.jpg
│ │ ├── 011-FirstScreenNthUse.jpg
│ │ ├── 010-FirstScreenFirstUse.jpg
│ │ ├── 030-ServerSearchResults.jpg
│ │ ├── 050-ConnectedToSecureInternet.jpg
│ │ ├── 040-ConnectingToSecureInternet.jpg
│ │ ├── 061-ConnectedToInstituteAccess.jpg
│ │ ├── 031-ServerSearchResultsWith2dots.jpg
│ │ └── 070-NotConnectedToSecureInternet.jpg
│ └── full_description.txt
├── .gitignore
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitmodules
├── create_release_tar.sh
├── NEW_RELEASE.md
├── gradle.properties
└── settings.gradle
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/common/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | .cxx/
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/title.txt:
--------------------------------------------------------------------------------
1 | eduVPN
2 |
--------------------------------------------------------------------------------
/common/consumer-rules.pro:
--------------------------------------------------------------------------------
1 | -keep public class org.eduvpn.common.** { *; }
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/16.txt:
--------------------------------------------------------------------------------
1 | * Update ics-openvpn
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/11.txt:
--------------------------------------------------------------------------------
1 | * Update ics-openvpn to version v0.7.13
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/29.txt:
--------------------------------------------------------------------------------
1 | - bump release for Google Play Store
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/15.txt:
--------------------------------------------------------------------------------
1 | * Fix certificate expiry countdown
2 | * Fix UI tests
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/21.txt:
--------------------------------------------------------------------------------
1 | * update ics-openvpn
2 | * Remove secure-preferences (#117)
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .DS_Store
5 | /build
6 | /.idea
7 | /captures
8 | *.apk
9 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/30.txt:
--------------------------------------------------------------------------------
1 | - embed WireGuard for Android
2 | - fix crash when reconnecting
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/7.txt:
--------------------------------------------------------------------------------
1 | * Use different OAuth client information for Let's Connect! flavor
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/23.txt:
--------------------------------------------------------------------------------
1 | * Only sort organizations when retrieving lists, not on every keypress
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/short_description.txt:
--------------------------------------------------------------------------------
1 | eduVPN connects securely and encrypted to your institution or Internet
2 |
--------------------------------------------------------------------------------
/app/src/main/res/font/open_sans_bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/font/open_sans_bold.ttf
--------------------------------------------------------------------------------
/app/src/main/res/font/open_sans_light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/font/open_sans_light.ttf
--------------------------------------------------------------------------------
/app/src/gov/res/drawable-hdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/drawable-hdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/gov/res/drawable-mdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/drawable-mdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/font/open_sans_italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/font/open_sans_italic.ttf
--------------------------------------------------------------------------------
/app/src/main/res/font/open_sans_regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/font/open_sans_regular.ttf
--------------------------------------------------------------------------------
/app/src/main/res/font/open_sans_semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/font/open_sans_semibold.ttf
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/gov/res/drawable-xhdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/drawable-xhdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/gov/res/drawable-xxhdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/drawable-xxhdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/home/res/drawable-hdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/drawable-hdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/home/res/drawable-mdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/drawable-mdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/home/res/drawable-xhdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/drawable-xhdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/drawable-hdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/drawable-mdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/drawable-xhdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/main/res/font/open_sans_extra_bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/font/open_sans_extra_bold.ttf
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/gov/res/drawable-xxxhdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/drawable-xxxhdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/home/res/drawable-xxhdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/drawable-xxhdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/drawable-xxhdpi/logo_black.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/surfnet_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/drawable-xxhdpi/surfnet_logo.png
--------------------------------------------------------------------------------
/app/src/main/res/font/open_sans_bold_italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/font/open_sans_bold_italic.ttf
--------------------------------------------------------------------------------
/app/src/main/res/font/open_sans_light_italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/font/open_sans_light_italic.ttf
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/icon.png
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/font/open_sans_semibold_italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/font/open_sans_semibold_italic.ttf
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/22.txt:
--------------------------------------------------------------------------------
1 | * Remove API v2 support
2 | * Added German translation
3 | * Remove save button
4 | * Bug fixes
5 |
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/livedata/ByteCount.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.livedata
2 |
3 | data class ByteCount(val bytesIn: Long, val bytesOut: Long)
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/external_provider.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/drawable-xxhdpi/external_provider.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/maintenance_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/drawable-xxhdpi/maintenance_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/font/open_sans_extra_bold_italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/font/open_sans_extra_bold_italic.ttf
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/26.txt:
--------------------------------------------------------------------------------
1 | - fix incorrect usage of seconds, should be ms
2 | - fix not being able to add secure internet servers
3 |
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-hdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-hdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-mdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-mdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-xhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-xhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-hdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-hdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-mdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-mdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-xhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-xhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/12.txt:
--------------------------------------------------------------------------------
1 | * Continue to add server screen if selection screen is empty
2 | * Fix app being stuck in creating keypair
3 |
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-xxhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-xxhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-xxxhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/gov/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-xxhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-xxhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-xxxhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/home/res/mipmap-xxxhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/common/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/17.txt:
--------------------------------------------------------------------------------
1 | * Add Spanish (Latin America) translation
2 | * Fix parallel installation issue with other ics-openvpn based apps
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/25.txt:
--------------------------------------------------------------------------------
1 | * update all build scripts for new release
2 | * create new tag to properly update CHANGES.md and fastlane files
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/featureGraphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/featureGraphic.png
--------------------------------------------------------------------------------
/app/src/gov/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000000
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_shield_access_white_full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/drawable-xxhdpi/icon_shield_access_white_full.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_shield_internet_white_full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/app/src/main/res/drawable-xxhdpi/icon_shield_internet_white_full.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/090-Settings.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/090-Settings.jpg
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/18.txt:
--------------------------------------------------------------------------------
1 | * fix 'certificate expired' popup loop (issue #329)
2 | * add fastlane for F-Droid/Google Play release automation
3 | * update discovery signing keys
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/31.txt:
--------------------------------------------------------------------------------
1 | - update WireGuard, OpenVPN and "common" sub-modules
2 | - Move backend methods to background threads
3 | - More crash fixes
4 | - small README updates
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/080-ConnectionInfo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/080-ConnectionInfo.jpg
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/14.txt:
--------------------------------------------------------------------------------
1 | * Update ics-openvpn
2 | * Reduce size of app (do not add all static libs)
3 | * Add additional public keys for eduVPN discovery
4 | * Add application tests
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/011-FirstScreenNthUse.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/011-FirstScreenNthUse.jpg
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/24.txt:
--------------------------------------------------------------------------------
1 | * Use common Go library for interfacing with VPN servers
2 | * Add govVPN flavor
3 | * Update dependencies
4 | * Added Catalan translation
5 | * Various bug fixes
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/010-FirstScreenFirstUse.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/010-FirstScreenFirstUse.jpg
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/030-ServerSearchResults.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/030-ServerSearchResults.jpg
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/050-ConnectedToSecureInternet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/050-ConnectedToSecureInternet.jpg
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/040-ConnectingToSecureInternet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/040-ConnectingToSecureInternet.jpg
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/061-ConnectedToInstituteAccess.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/061-ConnectedToInstituteAccess.jpg
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/031-ServerSearchResultsWith2dots.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/031-ServerSearchResultsWith2dots.jpg
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/070-NotConnectedToSecureInternet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eduvpn/android/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/070-NotConnectedToSecureInternet.jpg
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/livedata/IPs.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.livedata
2 |
3 | data class IPs(val clientIpv4: String?, val clientIpv6: String?, val tunnelData: TunnelData?)
4 | data class TunnelData(val tunnelIp: String?, val mtu: Int?)
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/19.txt:
--------------------------------------------------------------------------------
1 | * add support for APIv3
2 | * add support for WireGuard in combination with eduVPN/Let's Connect! 3.x servers
3 | * improve expiry notification
4 | * allow user to request a new session
5 | * update ics-openvpn
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/20.txt:
--------------------------------------------------------------------------------
1 | * add support for APIv3
2 | * add support for WireGuard in combination with eduVPN/Let's Connect! 3.x servers
3 | * improve expiry notification
4 | * allow user to request a new session
5 | * update ics-openvpn
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/full_description.txt:
--------------------------------------------------------------------------------
1 | eduVPN enables students, employees and researchers to connect securely and encrypted to the Internet. eduVPN integrates with the institutional network so that internal ICT services can be made available in a secure manner.
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dialog_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/13.txt:
--------------------------------------------------------------------------------
1 | * Redesigned the entire app
2 | * Search for your organization or add your own server
3 | * Update ics-openvpn to version v0.7.17a
4 | * Added support for certificate expiry notifications
5 | * Your added servers are now grouped by type
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/27.txt:
--------------------------------------------------------------------------------
1 | - Update eduvpn-common to release 2.0.2
2 | - Implement support for ProxyGuard (WireGuard over TCP)
3 | - Fix "Country Switcher"
4 | - Improve error dialogs
5 | - Do not crash on invalid WireGuard configuration files
6 | - Update ics-openvpn (v0.7.5.1)
7 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/utils/Listener.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.utils
2 |
3 | interface Listener {
4 | /**
5 | * @param o the object calling `update`
6 | * @param arg an optional argument
7 | * method.
8 | */
9 | fun update(o: Any, arg: Any?)
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/gov/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/loading_gradient.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/app/src/home/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/VPNConfig.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity
2 |
3 | import com.wireguard.config.Config
4 | import de.blinkt.openvpn.VpnProfile
5 |
6 | sealed class VPNConfig {
7 |
8 | data class OpenVPN(val profile: VpnProfile) : VPNConfig()
9 |
10 | data class WireGuard(val config: Config) : VPNConfig()
11 | }
12 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/9.txt:
--------------------------------------------------------------------------------
1 | * Fix Gradle build
2 | * Immediately show "add provider" page when starting the app and no providers were added before for Let's Connect! flavor
3 | * Show "Profiles" instead of "Institute Access" for Let's Connect! flavor
4 | * Use different "certificate name" through API for eduVPN / Let's Connect! flavor
5 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "ics-openvpn"]
2 | path = ics-openvpn
3 | url = https://codeberg.org/eduVPN/ics-openvpn
4 | [submodule "common/libs/eduvpn-common"]
5 | path = common/libs/eduvpn-common
6 | url = https://github.com/eduvpn/eduvpn-common
7 | [submodule "wireguard"]
8 | path = wireguard
9 | url = https://codeberg.org/eduVPN/wireguard-android
10 |
--------------------------------------------------------------------------------
/common/src/main/java/org/eduvpn/common/ServerType.java:
--------------------------------------------------------------------------------
1 | package org.eduvpn.common;
2 |
3 | public enum ServerType {
4 | Unknown(0),
5 | InstituteAccess(1),
6 | SecureInternet(2),
7 | Custom(3);
8 | public final Integer nativeValue;
9 | ServerType(Integer nativeValue) {
10 | this.nativeValue = nativeValue;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/exception/ExceptionMessage.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity.exception
2 |
3 | import kotlinx.serialization.Serializable
4 | import nl.eduvpn.app.entity.TranslatableString
5 |
6 | @Serializable
7 | data class ExceptionMessage(
8 | val message: TranslatableString? = null,
9 | val misc: Boolean? = false
10 | )
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/interpolator/progress_indeterminate_horizontal_rect1_scalex.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/28.txt:
--------------------------------------------------------------------------------
1 | - Custom tabs will be always on, remove the option
2 | - Move prefer TCP from a setting to a button
3 | - Sort country selector by country name
4 | - Display WireGuard (TCP) if connected with ProxyGuard
5 | - Fix connection state dialog staying on screen
6 | - Fix missing server name
7 | - Error handling for no connection case
8 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/CookieAndStringData.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class CookieAndStringData(
7 | val data: String,
8 | val cookie: Int
9 | )
10 |
11 | @Serializable
12 | data class CookieAndStringArrayData(
13 | val data: List,
14 | val cookie: Int
15 | )
--------------------------------------------------------------------------------
/app/src/main/res/interpolator/progress_indeterminate_horizontal_rect1_translatex.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/delete_icon.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/interpolator/progress_indeterminate_horizontal_rect2_translatex.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/common/src/main/java/org/eduvpn/common/Protocol.java:
--------------------------------------------------------------------------------
1 | package org.eduvpn.common;
2 |
3 | public enum Protocol {
4 | Unknown(0),
5 | OpenVPN(1),
6 | WireGuard(2),
7 | WireGuardWithTCP(3),
8 | OpenVPNWithTCP(100); // Using number 100 here because it has no mapping in common
9 |
10 |
11 | public final Integer nativeValue;
12 | Protocol(Integer nativeValue) {
13 | this.nativeValue = nativeValue;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/Profile.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity
2 |
3 | import android.os.Parcelable
4 | import kotlinx.parcelize.Parcelize
5 | import kotlinx.serialization.SerialName
6 | import kotlinx.serialization.Serializable
7 |
8 | @Serializable
9 | @Parcelize
10 | data class Profile (
11 |
12 | @SerialName("profile_id")
13 | val profileId: String,
14 |
15 | @SerialName("display_name")
16 | val displayName: TranslatableString,
17 | ) : Parcelable
18 |
--------------------------------------------------------------------------------
/app/src/main/res/interpolator/progress_indeterminate_horizontal_rect2_scalex.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/common/src/main/java/org/eduvpn/common/DataErrorTuple.java:
--------------------------------------------------------------------------------
1 | package org.eduvpn.common;
2 |
3 | import androidx.annotation.Nullable;
4 |
5 | public class DataErrorTuple {
6 | public final @Nullable String data;
7 | public final @Nullable String error;
8 |
9 | DataErrorTuple(@Nullable String data, @Nullable String error) {
10 | this.data = data;
11 | this.error = error;
12 | }
13 | public boolean isError() {
14 | return error != null;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/exception/EduVPNException.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity.exception
2 |
3 | import androidx.annotation.StringRes
4 |
5 | /**
6 | * Exception with translatable message.
7 | *
8 | * @param formatArgs Arguments for [resourceIdMessage]
9 | */
10 | class EduVPNException(
11 | @StringRes val resourceIdTitle: Int,
12 | @StringRes val resourceIdMessage: Int,
13 | vararg formatArgs: Any?
14 | ) : Exception() {
15 | val formatArgs = formatArgs
16 | }
17 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/6.txt:
--------------------------------------------------------------------------------
1 | * Update ics-openvpn submodule to v0.7.5
2 | * Update client_id
3 | * Fetch update server VPN configuration on connect
4 | * Fetch new client certificate if the old one expired
5 | * Fix connecting to 2FA enabled profile
6 | * Trigger new authorization on profiles page when OAuth client was revoked
7 | * Many text changes in the application
8 | * Initial Let's Connect! branding changes, still WiP
9 | * Fix use of "refresh token"
10 | * Update VPN connection status icon to new artwork
11 |
--------------------------------------------------------------------------------
/common/src/main/java/org/eduvpn/common/FailoverResult.java:
--------------------------------------------------------------------------------
1 | package org.eduvpn.common;
2 |
3 | import androidx.annotation.Nullable;
4 |
5 | public class FailoverResult {
6 | public final boolean doesRequireFailover;
7 | public final @Nullable String error;
8 |
9 | FailoverResult(boolean doesRequireFailover, @Nullable String error) {
10 | this.doesRequireFailover = doesRequireFailover;
11 | this.error = error;
12 | }
13 | public boolean isError() {
14 | return error != null;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/utils/WireGuardTunnel.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.utils
2 |
3 | import com.wireguard.android.backend.Tunnel
4 |
5 | class WireGuardTunnel(
6 | private val name: String,
7 | private val onStateChangeFunction: (newState: Tunnel.State) -> Unit
8 | ) : Tunnel {
9 |
10 | override fun getName() = name
11 |
12 | var state: Tunnel.State = Tunnel.State.DOWN
13 | private set
14 |
15 | override fun onStateChange(newState: Tunnel.State) {
16 | state = newState
17 | onStateChangeFunction(newState)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/CertExpiryTimes.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class CertExpiryTimes(
8 | @SerialName("start_time")
9 | val startTime: Long? = null,
10 | @SerialName("end_time")
11 | val endTime: Long? = null,
12 | @SerialName("button_time")
13 | val buttonTime: Long? = null,
14 | @SerialName("countdown_time")
15 | val countdownTime: Long? = null,
16 | @SerialName("notification_times")
17 | val notificationTimes: List = emptyList(),
18 | )
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/viewmodel/ApiLogsViewModel.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.viewmodel
2 |
3 | import androidx.lifecycle.AndroidViewModel
4 | import androidx.lifecycle.ViewModel
5 | import nl.eduvpn.app.service.BackendService
6 | import nl.eduvpn.app.service.HistoryService
7 | import nl.eduvpn.app.service.PreferencesService
8 | import javax.inject.Inject
9 |
10 | class ApiLogsViewModel @Inject constructor(
11 | private val backendService: BackendService
12 | ) : ViewModel() {
13 | fun getLogFileContents() : String {
14 | return backendService.getLogFile()!!.readLines().joinToString("\n")
15 | }
16 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # This will allow us to get the correct file line numbers to the errors
2 | -keepattributes SourceFile,LineNumberTable
3 |
4 | -dontwarn com.google.errorprone.annotations.*
5 | -dontwarn org.bouncycastle.jsse.**
6 | -dontwarn org.conscrypt.*
7 | -dontwarn org.openjsse.javax.net.ssl.*
8 | -dontwarn org.openjsse.net.ssl.*
9 |
10 | -keepclassmembers class com.wireguard.android.backend.GoBackend {
11 | ;
12 | }
13 | -keepclassmembers class com.wireguard.android.backend.GoBackend$GhettoCompletableFuture {
14 | ;
15 | }
16 | -keepclassmembers class android.net.VpnService {
17 | ;
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/SerializedVpnConfig.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 | import org.eduvpn.common.Protocol
6 |
7 | @Serializable
8 | data class SerializedVpnConfig(
9 | val config: String,
10 | val protocol: Int,
11 | @SerialName("default_gateway")
12 | val defaultGateway: Boolean,
13 | @SerialName("should_failover")
14 | val shouldFailover: Boolean = false,
15 | val proxy: ProxySettings? = null
16 | )
17 |
18 | @Serializable
19 | data class ProxySettings(
20 | @SerialName("source_port")
21 | val sourcePort: Int,
22 | val listen: String,
23 | val peer: String
24 | )
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 | -
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/create_release_tar.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | GIT_REPO=https://codeberg.org/eduVPN/android
4 | GIT_TAG=3.3.4
5 | #GIT_TAG=master
6 |
7 | ###############################################################################
8 | # CLONE
9 | ###############################################################################
10 |
11 | (
12 | mkdir -p release
13 | cd release || exit
14 |
15 | git clone --recursive -b ${GIT_TAG} ${GIT_REPO} eduvpn-android-${GIT_TAG}
16 |
17 | (
18 | cd eduvpn-android-${GIT_TAG} || exit
19 | # remove all ".git" folders
20 | find . -type d -name ".git" | xargs rm -rf
21 | )
22 |
23 | tar -cJf eduvpn-android-${GIT_TAG}.tar.xz eduvpn-android-${GIT_TAG}
24 | rm -rf eduvpn-android-${GIT_TAG}
25 | minisign -Sm eduvpn-android-${GIT_TAG}.tar.xz
26 | )
27 |
--------------------------------------------------------------------------------
/common/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/main/res/anim/progress_indeterminate_horizontal_rect1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dialog_button_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
7 |
10 |
11 |
12 | -
13 |
14 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/NEW_RELEASE.md:
--------------------------------------------------------------------------------
1 | # Tag a Release
2 |
3 | Walk through the following steps when making a new release:
4 |
5 | * Update `CHANGES.md` to make sure all changes are recorded for the new release
6 | including the release date, e.g.: `3.2.0 (2023-12-22)`;
7 | * Increment the `versionCode` and set `versionName` to the correct version tag
8 | in `app/build.gradle`;
9 | * Copy the entries from the `CHANGES.md` file you made also to
10 | `fastlane/metadata/android/en-US/changelogs/$versionCode.txt`;
11 | * Update the `build_app_git.sh`, `build_app_tar.sh`, `create_release_tar.sh`,
12 | and if necessary `builder_setup.sh`;
13 | * Create an "annotated" tag with e.g. `git tag 3.2.0 -a -m '3.2.0'`;
14 | * Push the tag, e.g.: `git push origin 3.2.0`;
15 | * Create a release with `create_release_tar.sh` and "attach" the `.tar.xz` and
16 | `.tar.xz.minisig` files to the release on the forge
17 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/utils/serializer/DateSerializer.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.utils.serializer
2 |
3 | import kotlinx.serialization.KSerializer
4 | import kotlinx.serialization.descriptors.PrimitiveKind
5 | import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
6 | import kotlinx.serialization.descriptors.SerialDescriptor
7 | import kotlinx.serialization.encoding.Decoder
8 | import kotlinx.serialization.encoding.Encoder
9 | import java.util.*
10 |
11 | object DateSerializer : KSerializer {
12 |
13 | override val descriptor: SerialDescriptor =
14 | PrimitiveSerialDescriptor("Date", PrimitiveKind.LONG)
15 |
16 | override fun serialize(encoder: Encoder, value: Date) {
17 | encoder.encodeLong(value.time)
18 | }
19 |
20 | override fun deserialize(decoder: Decoder): Date {
21 | return Date(decoder.decodeLong())
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/progress_indeterminate_horizontal_rect2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
17 |
18 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/viewmodel/SettingsViewModel.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.viewmodel
2 |
3 | import androidx.lifecycle.AndroidViewModel
4 | import androidx.lifecycle.ViewModel
5 | import androidx.lifecycle.viewModelScope
6 | import kotlinx.coroutines.Dispatchers
7 | import kotlinx.coroutines.launch
8 | import nl.eduvpn.app.service.BackendService
9 | import nl.eduvpn.app.service.HistoryService
10 | import javax.inject.Inject
11 |
12 | class SettingsViewModel @Inject constructor(
13 | private val historyService: HistoryService,
14 | private val backendService: BackendService
15 | ) : ViewModel() {
16 |
17 | val apiLogFile get() = backendService.getLogFile()
18 |
19 | val hasAddedServers get() = historyService.addedServers?.hasServers() == true
20 |
21 | fun removeOrganizationData() {
22 | viewModelScope.launch(Dispatchers.IO) {
23 | historyService.removeOrganizationData()
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/gov/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 | govVPN
20 | govVPN
21 |
22 |
--------------------------------------------------------------------------------
/app/src/dev/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 | eduVPN (dev)
20 | eduVPN (dev)
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/DisconnectVPNBroadcastReceiver.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app
2 |
3 | import android.content.BroadcastReceiver
4 | import android.content.Context
5 | import android.content.Intent
6 | import nl.eduvpn.app.service.VPNConnectionService
7 | import nl.eduvpn.app.service.VPNService
8 | import javax.inject.Inject
9 |
10 | class DisconnectVPNBroadcastReceiver : BroadcastReceiver() {
11 |
12 | @Inject
13 | protected lateinit var vpnConnectionService: VPNConnectionService
14 |
15 | @Inject
16 | protected lateinit var vpnService: VPNService
17 |
18 | companion object {
19 | val ACTION = this::class.qualifiedName!!.plus(".disconnect_vpn")
20 | }
21 |
22 | override fun onReceive(context: Context, intent: Intent) {
23 | EduVPNApplication.get(context).component().inject(this)
24 | if (intent.action != ACTION) {
25 | return
26 | }
27 | vpnConnectionService.disconnect(context, vpnService)
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/exception/CommonException.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity.exception
2 |
3 | import kotlinx.serialization.decodeFromString
4 | import kotlinx.serialization.json.Json
5 |
6 | data class CommonException(override val message: String?) : Exception(message) {
7 |
8 | private val exceptionMessage: ExceptionMessage? get() {
9 | if (message == null) {
10 | return null
11 | }
12 | return try {
13 | json.decodeFromString(message)
14 | } catch (ex: Exception) {
15 | null
16 | }
17 | }
18 |
19 | fun translatedMessage() : String {
20 | if (message == null) {
21 | return toString()
22 | }
23 | return exceptionMessage?.message?.bestTranslation ?: message
24 | }
25 |
26 | fun isMiscError(): Boolean {
27 | return exceptionMessage?.misc == true
28 | }
29 |
30 | companion object {
31 | private val json = Json { ignoreUnknownKeys = true }
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_search.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
17 |
18 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/10.txt:
--------------------------------------------------------------------------------
1 | * Updated the flow: instead of profiles you now select servers first. We don't connect to each server to fetch the latest profiles.
2 | * Added some animations and updated loading indicators for a smoother user experience.
3 | * You can remove servers by long pressing on them, instead of swiping.
4 | * Update ics-openvpn submodule to v0.7.10 (#188). This adds support for TLSv1.3, Ed25519 keys, and includes OpenSSL 1.1.1d.
5 | * Redirect URLs are now followed.
6 | * Android 10 support, also updated most of our libraries to their latest version.
7 | * Added license screen.
8 | * Fixed some edge-cases where IPv4 / IPv6 / Duration would not be displayed when connected, and the back button would not appear.
9 | * When connecting, the notifications tab is only shown when there are any notifications.
10 | * Fixed a crash which happened on screen rotation.
11 | * Removed mentions of 2FA.
12 | * Deprecated the secure-preferences library, added migration.
13 | * Updated documentations and build scripts.
14 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/CookieAndProfileMapData.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class CookieAndProfileMapData(
8 | val data: ProfileWithoutIdMap,
9 | val cookie: Int
10 | )
11 |
12 | @Serializable
13 | data class ProfileWithoutIdMap(
14 | internal val map: Map? = null,
15 | @SerialName("current")
16 | internal val currentProfileId: String?
17 | ) {
18 | fun getProfileList(): List {
19 | return map?.map {
20 | Profile(
21 | profileId = it.key,
22 | displayName = it.value.displayName,
23 | )
24 | } ?: emptyList()
25 | }
26 |
27 | val currentProfile: Profile? = getProfileList().firstOrNull { it.profileId == currentProfileId }
28 | }
29 |
30 | @Serializable
31 | data class ProfileWithoutId(
32 | @SerialName("display_name")
33 | val displayName: TranslatableString,
34 | )
--------------------------------------------------------------------------------
/app/src/main/res/anim/fade_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/ServerList.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.entity
20 |
21 | import kotlinx.serialization.SerialName
22 | import kotlinx.serialization.Serializable
23 |
24 | /**
25 | * A versioned list of organizations
26 | */
27 | @Serializable
28 | data class ServerList(
29 | @SerialName("server_list")
30 | val serverList: List? = null
31 | )
32 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/scrollbar_thumb.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/OrganizationList.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.entity
20 |
21 | import kotlinx.serialization.SerialName
22 | import kotlinx.serialization.Serializable
23 |
24 | /**
25 | * A versioned list of organizations
26 | */
27 | @Serializable
28 | data class OrganizationList(
29 | @SerialName("organization_list")
30 | val organizationList: List? = null
31 | )
--------------------------------------------------------------------------------
/app/src/main/res/color/bg_big_button.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 80dp
3 | 40dp
4 |
5 | 48dp
6 | 32dp
7 |
8 | 56dp
9 | 64dp
10 |
11 | 20sp
12 | 16dp
13 | 32dp
14 | 32dp
15 | 120dp
16 | 80dp
17 | 4dp
18 | 12dp
19 | 16dp
20 | 40dp
21 | 15sp
22 | 24dp
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/access_type_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
20 | -
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_chevron_right.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 | org.gradle.jvmargs=-Xmx1536M
20 |
21 | android.useAndroidX=true
22 | android.enableJetifier=true
23 | android.defaults.buildfeatures.buildconfig=true
24 |
25 | wireguardPackageName=com.wireguard
26 | wireguardVersionName=1.0.20231018-eduvpn-fork
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/inject/ViewModelKey.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.inject
20 |
21 | import androidx.lifecycle.ViewModel
22 | import dagger.MapKey
23 | import kotlin.reflect.KClass
24 |
25 | @MapKey
26 | @MustBeDocumented
27 | @Retention(AnnotationRetention.RUNTIME)
28 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
29 | annotation class ViewModelKey(val value: KClass)
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
25 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_drop_down.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
25 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_warning.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/switch_thumb.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_institute.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/Organization.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.entity
20 |
21 | import kotlinx.serialization.SerialName
22 | import kotlinx.serialization.Serializable
23 |
24 | @Serializable
25 | data class Organization(
26 | @SerialName("org_id")
27 | val orgId: String,
28 | @SerialName("display_name")
29 | val displayName: TranslatableString = TranslatableString(),
30 | @SerialName("keyword_list")
31 | val keywordList: TranslatableString = TranslatableString(),
32 | )
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_progressbar_indeterminate.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
21 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | // The following block is needed because of this issue: https://stackoverflow.com/a/76954759/1395437
2 | // Can be removed when upgrading to Android Studio Hedgehog
3 | pluginManagement {
4 | repositories {
5 | gradlePluginPortal()
6 | google()
7 | mavenCentral()
8 |
9 | }
10 | }
11 |
12 | dependencyResolutionManagement {
13 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
14 | repositories {
15 | gradlePluginPortal()
16 | google()
17 | mavenCentral()
18 | jcenter()
19 | maven {
20 | url = uri("https://jitpack.io")
21 | }
22 | }
23 | versionCatalogs {
24 | libVersions {
25 | from(files('ics-openvpn/gradle/libs.versions.toml'))
26 | }
27 | eduvpnVersions {
28 | from(files('gradle/libs.versions.toml'))
29 | }
30 | wireguardVersions {
31 | from(files('wireguard/gradle/libs.versions.toml'))
32 | }
33 | }
34 | }
35 |
36 | include ':app'
37 | include ':ics-openvpn-main'
38 | project(':ics-openvpn-main').projectDir = new File(rootDir, '/ics-openvpn/main')
39 | include ':common'
40 | include ':wireguard'
41 | project(':wireguard').projectDir = new File(rootDir, '/wireguard/tunnel')
42 |
--------------------------------------------------------------------------------
/app/src/home/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 | Let\'s Connect!
20 | Let\'s Connect!
21 | Add Provider
22 | Servers
23 |
27 | Profiles
28 |
29 |
--------------------------------------------------------------------------------
/app/src/home/res/values-de/strings.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 | Let\'s Connect!
20 | Let\'s Connect!
21 | Anbieter hinzufügen
22 | Server
23 |
27 | Profile
28 |
29 |
--------------------------------------------------------------------------------
/app/src/home/res/values-es/strings.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 | Let\'s Connect!
20 | Let\'s Connect!
21 | Agregar Proveedor
22 | Servidores
23 |
27 | Perfiles
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/AuthorizationType.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 |
18 | package nl.eduvpn.app.entity
19 |
20 | import kotlinx.serialization.SerialName
21 | import kotlinx.serialization.Serializable
22 |
23 | /**
24 | * The type of the VPN which the user will connect to.
25 | * Created by Daniel Zolnai on 2017-07-31.
26 | */
27 | @Serializable
28 | enum class AuthorizationType {
29 |
30 | @SerialName("institute_access")
31 | Local,
32 |
33 | @SerialName("secure_internet")
34 | Distributed,
35 |
36 | @SerialName("organization")
37 | Organization
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_search.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/viewmodel/ProfileSelectionViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.viewmodel
20 |
21 | import android.content.Context
22 | import nl.eduvpn.app.service.*
23 | import javax.inject.Inject
24 |
25 | class ProfileSelectionViewModel @Inject constructor(
26 | context: Context,
27 | historyService: HistoryService,
28 | preferencesService: PreferencesService,
29 | backendService: BackendService,
30 | vpnConnectionService: VPNConnectionService,
31 | ) : BaseConnectionViewModel(
32 | context,
33 | backendService,
34 | historyService,
35 | preferencesService,
36 | vpnConnectionService,
37 | )
38 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/viewmodel/ConnectionState.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.viewmodel
20 |
21 | import androidx.annotation.StringRes
22 | import nl.eduvpn.app.R
23 |
24 | enum class ConnectionState(@StringRes val displayString: Int?) {
25 | Ready(null),
26 | FetchingOrganizations(R.string.fetching_organization_servers),
27 | FetchingServerList(R.string.fetching_server_list),
28 | DiscoveringApi(R.string.api_discovery_message),
29 | FetchingProfiles(R.string.loading_available_profiles),
30 | Authorizing(R.string.loading_browser_for_authorization),
31 | ProfileDownloadingKeyPair(R.string.vpn_profile_creating_keypair)
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_vpn_profile.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/base/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.base
20 |
21 | import android.os.Bundle
22 | import androidx.annotation.LayoutRes
23 | import androidx.appcompat.app.AppCompatActivity
24 | import androidx.databinding.DataBindingUtil
25 | import androidx.databinding.ViewDataBinding
26 |
27 | abstract class BaseActivity : AppCompatActivity() {
28 |
29 | protected lateinit var binding: B
30 |
31 | @get:LayoutRes
32 | protected abstract val layout: Int
33 |
34 | override fun onCreate(savedInstanceState: Bundle?) {
35 | super.onCreate(savedInstanceState)
36 | binding = DataBindingUtil.setContentView(this, layout)
37 | binding.lifecycleOwner = this
38 | }
39 |
40 |
41 | }
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/livedata/openvpn/ByteCountLiveData.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 |
18 | package nl.eduvpn.app.livedata.openvpn
19 |
20 | import androidx.lifecycle.LiveData
21 | import de.blinkt.openvpn.core.VpnStatus
22 | import nl.eduvpn.app.livedata.ByteCount
23 |
24 | class ByteCountLiveData : LiveData() {
25 |
26 | private val byteCountListener: VpnStatus.ByteCountListener =
27 | VpnStatus.ByteCountListener { inBytes, outBytes, _, _ ->
28 | postValue(ByteCount(inBytes, outBytes))
29 | }
30 |
31 | override fun onActive() {
32 | VpnStatus.addByteCountListener(byteCountListener)
33 | }
34 |
35 | override fun onInactive() {
36 | VpnStatus.removeByteCountListener(byteCountListener)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/common/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libVersions.plugins.android.library)
3 | }
4 |
5 | android {
6 | namespace 'org.eduvpn.common'
7 | compileSdk 33
8 | ndkVersion = "26.1.10909125"
9 |
10 | def commonVersion = "2.0.0"
11 |
12 | defaultConfig {
13 | minSdk 21
14 |
15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
16 | consumerProguardFiles "consumer-rules.pro"
17 | externalNativeBuild {
18 | cmake {
19 | cppFlags ""
20 | }
21 | }
22 |
23 | buildConfigField "String", "COMMON_VERSION", "\"$commonVersion\""
24 | }
25 |
26 | buildTypes {
27 | release {
28 | minifyEnabled false
29 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
30 | }
31 | }
32 | externalNativeBuild {
33 | cmake {
34 | path "libs/CMakeLists.txt"
35 | }
36 | }
37 | compileOptions {
38 | sourceCompatibility JavaVersion.VERSION_1_8
39 | targetCompatibility JavaVersion.VERSION_1_8
40 | }
41 | buildTypes {
42 | configureEach {
43 | externalNativeBuild {
44 | cmake {
45 | targets("libeduvpn_common", "eduvpn_common-wrapper")
46 | arguments("-DCOMMON_VERSION=$commonVersion")
47 | }
48 | }
49 | }
50 | }
51 | }
52 |
53 | dependencies {
54 | implementation 'androidx.annotation:annotation-jvm:1.7.0'
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/Constants.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 | package nl.eduvpn.app
18 |
19 | import android.net.Uri
20 | import java.util.*
21 |
22 | /**
23 | * Contains application-wide constant values.
24 | * Created by Daniel Zolnai on 2016-09-14.
25 | */
26 | object Constants {
27 | @JvmField
28 | val DEBUG = BuildConfig.BUILD_TYPE.equals("debug", ignoreCase = true)
29 |
30 | @JvmField
31 | val LOCALE = Locale.getDefault()
32 | val ENGLISH_LOCALE = Locale.ENGLISH
33 |
34 | const val SERVER_LIST_VALID_FOR_MS: Long = 3600000 // 1 hour
35 |
36 | const val CERT_EXPIRY_NOTIFICATION_CHANNEL_ID = "cert_expiry"
37 | const val CERT_EXPIRY_NOTIFICATION_ID = 1
38 |
39 | const val VPN_CONNECTION_NOTIFICATION_CHANNEL_ID = "vpn_connection"
40 | const val VPN_CONNECTION_NOTIFICATION_ID = 2
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_openvpn_logs.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
26 |
27 |
32 |
33 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/ApiLogsActivity.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app
2 |
3 | import android.os.Bundle
4 | import android.view.MenuItem
5 | import androidx.activity.viewModels
6 | import androidx.core.view.isVisible
7 | import nl.eduvpn.app.base.BaseActivity
8 | import nl.eduvpn.app.databinding.ActivityApiLogsBinding
9 | import nl.eduvpn.app.viewmodel.ApiLogsViewModel
10 | import nl.eduvpn.app.viewmodel.ViewModelFactory
11 | import javax.inject.Inject
12 |
13 | class ApiLogsActivity : BaseActivity() {
14 |
15 | override val layout = R.layout.activity_api_logs
16 |
17 | @Inject
18 | protected lateinit var viewModelFactory: ViewModelFactory
19 |
20 | private val viewModel by viewModels { viewModelFactory }
21 | override fun onCreate(savedInstanceState: Bundle?) {
22 | super.onCreate(savedInstanceState)
23 | EduVPNApplication.get(this).component().inject(this)
24 | setSupportActionBar(binding.toolbar.toolbar)
25 | supportActionBar?.setDisplayHomeAsUpEnabled(true)
26 | binding.toolbar.settingsButton.isVisible = false
27 |
28 | }
29 |
30 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
31 | return if (item.itemId == android.R.id.home) {
32 | onBackPressedDispatcher.onBackPressed()
33 | true
34 | } else {
35 | super.onOptionsItemSelected(item)
36 | }
37 | }
38 |
39 | override fun onResume() {
40 | super.onResume()
41 | binding.logContents.text = viewModel.getLogFileContents()
42 | }
43 | }
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/service/VPNService.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.service
2 |
3 | import android.app.Notification
4 | import androidx.lifecycle.LiveData
5 | import kotlinx.coroutines.flow.Flow
6 | import nl.eduvpn.app.livedata.ByteCount
7 | import nl.eduvpn.app.livedata.IPs
8 | import org.eduvpn.common.Protocol
9 |
10 | abstract class VPNService : LiveData() {
11 |
12 | enum class VPNStatus {
13 | DISCONNECTED, CONNECTING, CONNECTED, PAUSED, FAILED
14 | }
15 |
16 | abstract val byteCountFlow: Flow
17 |
18 | abstract val ipFlow: Flow
19 |
20 | /**
21 | * User should call this after showing a notification.
22 | *
23 | * @param id The identifier for this notification as per
24 | * {@link NotificationManager#notify(int, Notification)
25 | * NotificationManager.notify(int, Notification)};
26 | * @param notification The Notification to be displayed.
27 | */
28 | abstract fun startForeground(id: Int, notification: Notification)
29 |
30 | /**
31 | * Disconnects the current VPN connection.
32 | */
33 | abstract fun disconnect()
34 |
35 | /**
36 | * Returns the error string.
37 | *
38 | * @return The description of the error.
39 | */
40 | abstract fun getErrorString(): String?
41 |
42 | /**
43 | * @return The current status of the VPN.
44 | */
45 | abstract fun getStatus(): VPNStatus
46 |
47 | /**
48 | * Type of the VPN protocol this service implements.
49 | */
50 | abstract fun getProtocol(): Protocol
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/OpenVpnLogsActivity.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app
2 |
3 | import android.os.Bundle
4 | import android.view.MenuItem
5 | import androidx.activity.viewModels
6 | import androidx.core.view.isVisible
7 | import de.blinkt.openvpn.fragments.LogFragment
8 | import nl.eduvpn.app.base.BaseActivity
9 | import nl.eduvpn.app.databinding.ActivityApiLogsBinding
10 | import nl.eduvpn.app.databinding.ActivityOpenvpnLogsBinding
11 | import nl.eduvpn.app.viewmodel.ApiLogsViewModel
12 | import nl.eduvpn.app.viewmodel.ViewModelFactory
13 | import javax.inject.Inject
14 |
15 | class OpenVpnLogsActivity : BaseActivity() {
16 |
17 | override val layout = R.layout.activity_openvpn_logs
18 |
19 | @Inject
20 | protected lateinit var viewModelFactory: ViewModelFactory
21 |
22 | override fun onCreate(savedInstanceState: Bundle?) {
23 | super.onCreate(savedInstanceState)
24 | EduVPNApplication.get(this).component().inject(this)
25 | setSupportActionBar(binding.toolbar.toolbar)
26 | supportActionBar?.setDisplayHomeAsUpEnabled(true)
27 | binding.toolbar.settingsButton.isVisible = false
28 | supportFragmentManager.beginTransaction()
29 | .add(binding.fragmentContainer.id, LogFragment())
30 | .commit()
31 | }
32 |
33 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
34 | return if (item.itemId == android.R.id.home) {
35 | onBackPressedDispatcher.onBackPressed()
36 | true
37 | } else {
38 | super.onOptionsItemSelected(item)
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_licenses.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
26 |
27 |
33 |
34 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/viewmodel/AddServerViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.viewmodel
20 |
21 | import android.content.Context
22 | import androidx.lifecycle.MutableLiveData
23 | import androidx.lifecycle.map
24 | import nl.eduvpn.app.service.*
25 | import javax.inject.Inject
26 |
27 | class AddServerViewModel @Inject constructor(
28 | preferencesService: PreferencesService,
29 | context: Context,
30 | historyService: HistoryService,
31 | backendService: BackendService,
32 | vpnConnectionService: VPNConnectionService,
33 | ) : BaseConnectionViewModel(
34 | context,
35 | backendService,
36 | historyService,
37 | preferencesService,
38 | vpnConnectionService,
39 | ) {
40 |
41 | val serverUrl = MutableLiveData("")
42 |
43 | val addButtonEnabled = serverUrl.map { url ->
44 | url != null && url.contains(".") && url.length > 3
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/res/values/content_description.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 | Secure Internet
21 | Institute Access
22 | Connection status
23 | Provider icon
24 | Application logo
25 | Settings button
26 | Message icon
27 | Warning icon
28 | Expand / collapse arrow
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item_provider.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
19 |
20 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/nl/eduvpn/app/UnitTestSuite.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 |
18 | package nl.eduvpn.app;
19 |
20 | import nl.eduvpn.app.service.HistoryServiceTest;
21 | import nl.eduvpn.app.service.PreferencesServiceTest;
22 | import nl.eduvpn.app.service.SerializerServiceTest;
23 | import nl.eduvpn.app.utils.FormattingUtilsTest;
24 |
25 | import org.junit.runner.RunWith;
26 | import org.junit.runners.Suite;
27 |
28 | /**
29 | * Suite used to run all unit tests.
30 | * Created by Daniel Zolnai on 2016-10-18.
31 | */
32 | @RunWith(Suite.class)
33 | @Suite.SuiteClasses({SerializerServiceTest.class, PreferencesServiceTest.class,
34 | HistoryServiceTest.class, FormattingUtilsTest.class})
35 | public class UnitTestSuite {
36 | // Test suite used to run all unit tests at once.
37 | // To run the tests, right click on the class name, and select "Run 'UnitTestSuite'".
38 | // The tests will run on your device.
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/res/values-de/content_description.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 | Sicheres Internet
21 | Organisations-Zugang
22 | Verbindungsstatus
23 | Anbieter-Symbol
24 | Anwendungs-Symbol
25 | Schaltfläche Einstellungen
26 | Nachrichten-Symbol
27 | Warnungs-Symbol
28 | Pfeil zum aus-/einklappen
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ca/content_description.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 | Secure Internet
21 | Access Institucional
22 | Estat de la Connexió
23 | Icona del Proveïdor
24 | Logotip de l\'Aplicació
25 | Botó de Preferències
26 | Icona de Missatge
27 | Icona d\'Advertència
28 | Fletxa d\'expandir / colapsar
29 |
--------------------------------------------------------------------------------
/app/src/main/res/values-es/content_description.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 | Internet Seguro
21 | Acceso Institucional
22 | Estado de conexión
23 | Icono de proveedor
24 | Logo de aplicación
25 | Botón de configuraciones
26 | Icono de mensaje
27 | Icono de advertencia
28 | Flecha de expandir / colapsar
29 |
30 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/nl/eduvpn/app/utils/ParcelableTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 |
18 | package nl.eduvpn.app.utils
19 |
20 | import android.os.Parcel
21 | import androidx.test.ext.junit.runners.AndroidJUnit4
22 | import nl.eduvpn.app.entity.TranslatableString
23 | import org.junit.Assert
24 | import org.junit.Test
25 | import org.junit.runner.RunWith
26 |
27 | @RunWith(AndroidJUnit4::class)
28 | class ParcelableTest {
29 |
30 | @Test
31 | fun testTranslatableStringParcelable() {
32 | val expected = TranslatableString(
33 | mapOf("en" to "Hello", "es" to "Hola", "nl" to "Hallo")
34 | )
35 | val parcel = Parcel.obtain()
36 | expected.writeToParcel(parcel, 0)
37 | // Reset parcel for reading
38 | parcel.setDataPosition(0)
39 | val actual = TranslatableString.CREATOR.createFromParcel(parcel)
40 | parcel.recycle()
41 | Assert.assertEquals(expected, actual)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_secure_internet.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/home/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #1193F5
4 | #1193F5
5 | #0666AF
6 | #1193F5
7 | #1193F5
8 | #808080
9 | #101010
10 | #505050
11 | #FFFFFF
12 | #FFFFFF
13 | #101010
14 | #E0E0E0
15 | #FFFFFF
16 | #E9E9E9
17 | #D0D0D0
18 | #C0C0C0
19 | #00A2C8
20 | #505050
21 | #FFFFFF
22 | #CCCCCC
23 | #00FFFFFF
24 | #FFFFFF
25 | #216aed
26 | #7DA7F3
27 | #F0F0F0
28 |
29 | #16a566
30 | #b2b2b2
31 | #E4E4E4
32 | #FFFFFF
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #E24301
4 | #E24301
5 | #9A2E00
6 | #EC5D22
7 | #E24301
8 | #808080
9 | #101010
10 | #505050
11 | #FFFFFF
12 | #216aed
13 | #FFFFFF
14 | #101010
15 | #E0E0E0
16 | #FFFFFF
17 | #E9E9E9
18 | #D0D0D0
19 | #C0C0C0
20 | #00A2C8
21 | #505050
22 | #FFFFFF
23 | #CCCCCC
24 | #00FFFFFF
25 | #FFFFFF
26 | #216aed
27 | #7DA7F3
28 | #F0F0F0
29 |
30 | #16a566
31 | #b2b2b2
32 | #E4E4E4
33 | #FFFFFF
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/viewmodel/ViewModelFactory.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.viewmodel
20 |
21 | import androidx.lifecycle.ViewModel
22 | import androidx.lifecycle.ViewModelProvider
23 | import javax.inject.Inject
24 | import javax.inject.Provider
25 |
26 | /**
27 | * Factory for [ViewModel]'s
28 | */
29 | class ViewModelFactory @Inject constructor(
30 | private val viewModelsMap: Map, @JvmSuppressWildcards Provider>
31 | ) : ViewModelProvider.Factory {
32 | override fun create(modelClass: Class): T {
33 | val creator = viewModelsMap[modelClass]
34 | ?: viewModelsMap.entries.firstOrNull {
35 | modelClass.isAssignableFrom(it.key)
36 | }?.value ?: throw IllegalArgumentException("Unknown ViewModel class $modelClass")
37 |
38 | return try {
39 | @Suppress("UNCHECKED_CAST")
40 | creator.get() as T
41 | } catch (e: Exception) {
42 | throw RuntimeException(e)
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/livedata/UnlessDisconnectedLiveData.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 |
18 | package nl.eduvpn.app.livedata
19 |
20 | import androidx.lifecycle.LiveData
21 | import androidx.lifecycle.MediatorLiveData
22 | import nl.eduvpn.app.service.VPNService
23 |
24 | /**
25 | * Live data unless VPN disconnected.
26 | */
27 | object UnlessDisconnectedLiveData {
28 | fun create(
29 | liveData: LiveData,
30 | vpnStatusLiveData: LiveData
31 | ): LiveData {
32 | val mediator = MediatorLiveData()
33 | mediator.addSource(liveData) { value ->
34 | mediator.value = if (vpnStatusLiveData.value == VPNService.VPNStatus.DISCONNECTED) {
35 | null
36 | } else {
37 | value
38 | }
39 | }
40 | mediator.addSource(vpnStatusLiveData) { vpnStatus ->
41 | if (vpnStatus == VPNService.VPNStatus.DISCONNECTED) {
42 | mediator.value = null
43 | }
44 | }
45 | return mediator
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/base/BaseFragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.base
20 |
21 | import android.os.Bundle
22 | import android.view.LayoutInflater
23 | import android.view.View
24 | import android.view.ViewGroup
25 | import androidx.annotation.LayoutRes
26 | import androidx.databinding.DataBindingUtil
27 | import androidx.databinding.ViewDataBinding
28 | import androidx.fragment.app.Fragment
29 | import nl.eduvpn.app.viewmodel.ViewModelFactory
30 | import javax.inject.Inject
31 |
32 | abstract class BaseFragment : Fragment() {
33 |
34 | protected lateinit var binding: B
35 |
36 | @Inject
37 | protected lateinit var viewModelFactory : ViewModelFactory
38 |
39 | @get:LayoutRes
40 | protected abstract val layout: Int
41 |
42 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
43 | binding = DataBindingUtil.inflate(inflater, layout, container, false).also {
44 | it.lifecycleOwner = this.viewLifecycleOwner
45 | }
46 | return binding.root
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/res/anim/fade_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
37 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_server.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
18 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/switch_track.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 | -
21 |
22 |
23 |
24 |
25 |
26 |
27 | -
28 |
29 |
30 |
31 |
32 |
33 |
34 | -
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/home/res/drawable/ic_application_logo.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_api_logs.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
26 |
27 |
33 |
34 |
41 |
42 |
43 |
44 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/adapter/viewholder/ProfileViewHolder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 |
18 | package nl.eduvpn.app.adapter.viewholder
19 |
20 |
21 | import android.text.TextUtils
22 | import androidx.recyclerview.widget.RecyclerView
23 | import com.squareup.picasso.Picasso
24 | import nl.eduvpn.app.R
25 | import nl.eduvpn.app.databinding.ListItemProfileBinding
26 | import nl.eduvpn.app.entity.Instance
27 | import nl.eduvpn.app.entity.Profile
28 | import nl.eduvpn.app.utils.FormattingUtils
29 |
30 | /**
31 | * View holder for the provider instance list.
32 | * Created by Daniel Zolnai on 2016-10-07.
33 | */
34 | class ProfileViewHolder(private val binding: ListItemProfileBinding) : RecyclerView.ViewHolder(binding.root) {
35 |
36 | fun bind(instance: Instance, profile: Profile) {
37 | binding.profileName.text = profile.displayName.bestTranslation
38 | binding.profileProvider.text = FormattingUtils.formatDisplayName(instance)
39 | if (!TextUtils.isEmpty(instance.logoUri)) {
40 | Picasso.get()
41 | .load(instance.logoUri)
42 | .fit()
43 | .into(binding.profileIcon)
44 | } else {
45 | binding.profileIcon.setImageResource(R.drawable.ic_vpn_profile)
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/dev/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 | #A0A0A0
21 | #A0A0A0
22 | #808080
23 | #FF9800
24 | #D0D0D0
25 | #FFFFFF
26 | #FFFFFF
27 | #808080
28 | #FF5722
29 | #000000
30 | #202020
31 | #C0C0C0
32 | #FFFFFF
33 | #CF0000
34 | #F0F0F0
35 | #00000000
36 | #000000
37 | #FF8700
38 | #303030
39 | #505050
40 | #606060
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/LicenseActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app
20 |
21 | import android.content.Intent
22 | import android.net.Uri
23 | import android.os.Bundle
24 | import android.view.MenuItem
25 | import androidx.core.view.isVisible
26 | import nl.eduvpn.app.base.BaseActivity
27 | import nl.eduvpn.app.databinding.ActivityLicensesBinding
28 |
29 | class LicenseActivity : BaseActivity() {
30 |
31 | override val layout = R.layout.activity_licenses
32 |
33 | override fun onCreate(savedInstanceState: Bundle?) {
34 | super.onCreate(savedInstanceState)
35 | setSupportActionBar(binding.toolbar.toolbar)
36 | supportActionBar?.setDisplayHomeAsUpEnabled(true)
37 | binding.webView.loadUrl("file:///android_asset/licenses.html");
38 | binding.toolbar.settingsButton.isVisible = false
39 | binding.toolbar.helpButton.setOnClickListener {
40 | startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.HELP_URI)))
41 | }
42 | }
43 |
44 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
45 | return if (item.itemId == android.R.id.home) {
46 | onBackPressedDispatcher.onBackPressed()
47 | true
48 | } else {
49 | super.onOptionsItemSelected(item)
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_profile_selection.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
17 |
18 |
24 |
25 |
29 |
30 |
31 |
42 |
43 |
44 |
45 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/gov/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 | #A0A0A0
21 | #A0A0A0
22 | #808080
23 | #a0a0a0
24 | #D0D0D0
25 | #303030
26 | #FFFFFF
27 | #808080
28 | #22B9FF
29 | #f0f0f0
30 | #202020
31 | #C8C8C8
32 | #FFFFFF
33 | #CF0000
34 | #808080
35 | #00000000
36 | #000000
37 | #808080
38 | #A0A0A0
39 | #303030
40 | #505050
41 | #606060
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/utils/serializer/TranslatableStringSerializer.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.utils.serializer
2 |
3 | import kotlinx.serialization.ExperimentalSerializationApi
4 | import kotlinx.serialization.KSerializer
5 | import kotlinx.serialization.SerializationException
6 | import kotlinx.serialization.descriptors.SerialDescriptor
7 | import kotlinx.serialization.encoding.Decoder
8 | import kotlinx.serialization.encoding.Encoder
9 | import kotlinx.serialization.json.JsonElement
10 | import kotlinx.serialization.json.JsonObject
11 | import kotlinx.serialization.json.JsonPrimitive
12 | import nl.eduvpn.app.entity.TranslatableString
13 |
14 | object TranslatableStringSerializer : KSerializer {
15 |
16 | @OptIn(ExperimentalSerializationApi::class)
17 | override val descriptor: SerialDescriptor =
18 | SerialDescriptor("TranslatableString", JsonObject.serializer().descriptor)
19 |
20 | override fun serialize(encoder: Encoder, value: TranslatableString) {
21 | val jsonObject = JsonObject(value.translations.mapValues { (_, v) -> JsonPrimitive(v) })
22 | encoder.encodeSerializableValue(
23 | JsonObject.serializer(),
24 | jsonObject
25 | )
26 | }
27 |
28 | override fun deserialize(decoder: Decoder): TranslatableString {
29 | return when (val jsonElement = decoder.decodeSerializableValue(JsonElement.serializer())) {
30 | // Plain string was previously used to store displayName in Instance and in Profile. If
31 | // this is removed from the deserializer, a migration is necessary.
32 | is JsonPrimitive -> if (jsonElement.isString) TranslatableString(jsonElement.content) else null
33 | is JsonObject -> TranslatableString(jsonElement.filterValues { v -> v is JsonPrimitive && v.isString }
34 | .mapValues { m ->
35 | val translation = m.value as JsonPrimitive
36 | translation.content
37 | })
38 | else -> null
39 | } ?: throw SerializationException("Invalid translatable string")
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/EduVPNApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 |
18 | package nl.eduvpn.app;
19 |
20 | import android.content.Context;
21 | import android.os.StrictMode;
22 |
23 | import de.blinkt.openvpn.core.ICSOpenVPNApplication;
24 | import nl.eduvpn.app.inject.EduVPNComponent;
25 |
26 | /**
27 | * Application object which keeps track of the app lifecycle.
28 | * Created by Daniel Zolnai on 2016-09-14.
29 | */
30 | public class EduVPNApplication extends ICSOpenVPNApplication {
31 |
32 | private EduVPNComponent _component;
33 |
34 | @Override
35 | public void onCreate() {
36 | super.onCreate();
37 | // Set up the injector
38 | _component = EduVPNComponent.Initializer.init(this);
39 |
40 | // The base class sets a strict VM policy for debug builds, which do not work well with OkHttp
41 | // (see this issue: https://github.com/square/okhttp/issues/3537)
42 | // For now, the best solution seems to be disabling strict mode
43 | StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder().build();
44 | StrictMode.setVmPolicy(policy);
45 |
46 | }
47 |
48 | public EduVPNComponent component() {
49 | return _component;
50 | }
51 |
52 | public static EduVPNApplication get(Context context) {
53 | return (EduVPNApplication)context.getApplicationContext();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/Instance.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 | package nl.eduvpn.app.entity
18 |
19 | import kotlinx.serialization.SerialName
20 | import kotlinx.serialization.Serializable
21 |
22 | /**
23 | * A configuration for an instance.
24 | * Created by Daniel Zolnai on 2016-10-07.
25 | */
26 | @Serializable
27 | data class Instance(
28 |
29 | @SerialName("base_url")
30 | val baseURI: String,
31 |
32 | @SerialName("display_name")
33 | val displayName: TranslatableString = TranslatableString(),
34 |
35 | @SerialName("keyword_list")
36 | val keywords: TranslatableString? = TranslatableString(),
37 |
38 | @SerialName("logo")
39 | val logoUri: String? = null,
40 |
41 | @SerialName("server_type")
42 | val authorizationType: AuthorizationType = AuthorizationType.Local,
43 |
44 | @SerialName("country_code")
45 | val countryCode: String? = null,
46 |
47 | @SerialName("is_custom")
48 | val isCustom: Boolean = false,
49 |
50 | @SerialName("authentication_url_template")
51 | val authenticationUrlTemplate: String? = null,
52 |
53 | @SerialName("support_contact")
54 | val supportContact: List = emptyList()
55 | ) {
56 |
57 | val sanitizedBaseURI: String
58 | get() = if (baseURI.endsWith("/")) {
59 | baseURI.substring(0, baseURI.length - 1)
60 | } else baseURI
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/service/OrganizationService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 | package nl.eduvpn.app.service
18 |
19 | import kotlinx.coroutines.Dispatchers
20 | import kotlinx.coroutines.withContext
21 | import nl.eduvpn.app.entity.OrganizationList
22 | import nl.eduvpn.app.entity.ServerList
23 |
24 | /**
25 | * Service which provides the configurations for organization related data model.
26 | * Created by Daniel Zolnai on 2016-10-07.
27 | */
28 | class OrganizationService(
29 | private val serializerService: SerializerService,
30 | private val backendService: BackendService
31 | ) {
32 |
33 | suspend fun fetchServerList(searchFilter: String) : Result = withContext(Dispatchers.IO) {
34 | try {
35 | val serverListString = backendService.discoverServers(searchFilter)
36 | val result = serializerService.deserializeServerList(serverListString)
37 | return@withContext Result.success(result)
38 | } catch (throwable: Throwable) {
39 | return@withContext Result.failure(throwable)
40 | }
41 | }
42 |
43 | suspend fun fetchOrganizations(searchFilter: String): OrganizationList = withContext(Dispatchers.IO) {
44 | val organizationListString = backendService.discoverOrganizations(searchFilter)
45 | serializerService.deserializeOrganizationList(organizationListString)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/home/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/CertExpiredBroadcastReceiver.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app
2 |
3 | import android.app.NotificationManager
4 | import android.app.PendingIntent
5 | import android.content.BroadcastReceiver
6 | import android.content.Context
7 | import android.content.Intent
8 | import androidx.core.app.NotificationCompat
9 | import nl.eduvpn.app.service.VPNService
10 | import nl.eduvpn.app.utils.pendingIntentImmutableFlag
11 | import javax.inject.Inject
12 |
13 | class CertExpiredBroadcastReceiver : BroadcastReceiver() {
14 |
15 | @Inject
16 | protected lateinit var vpnService: VPNService
17 |
18 | override fun onReceive(context: Context, intent: Intent) {
19 | EduVPNApplication.get(context).component().inject(this)
20 | if (intent.action != ACTION) {
21 | return
22 | }
23 | if (vpnService.getStatus() == VPNService.VPNStatus.DISCONNECTED) {
24 | return
25 | }
26 | val channelID = Constants.CERT_EXPIRY_NOTIFICATION_CHANNEL_ID
27 | val notification = NotificationCompat.Builder(context, channelID)
28 | .setSmallIcon(R.drawable.logo_black)
29 | .setContentTitle(context.getString(R.string.cert_expiry_notification_title))
30 | .setContentText(context.getString(R.string.cert_expiry_notification_text))
31 | .setContentIntent(
32 | PendingIntent.getActivity(
33 | context,
34 | 0,
35 | Intent(context, MainActivity::class.java),
36 | pendingIntentImmutableFlag
37 | )
38 | )
39 | .setAutoCancel(true)
40 | .setPriority(NotificationCompat.PRIORITY_DEFAULT) // Only used on Android <= 7.1
41 | .build()
42 |
43 | val notificationManager =
44 | context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
45 |
46 | notificationManager.notify(Constants.CERT_EXPIRY_NOTIFICATION_ID, notification)
47 | }
48 |
49 | companion object {
50 | val ACTION = this::class.qualifiedName!!.plus(".cert_expiry")
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_progress_indeterminate_layers.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
25 |
29 |
33 |
37 |
41 |
42 |
46 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/logmenu.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_help.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
24 |
30 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
24 |
28 |
32 |
36 |
40 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item_message.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
22 |
23 |
36 |
37 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/CurrentServer.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 | import org.eduvpn.common.ServerType
6 |
7 | @Serializable
8 | data class CurrentServer(
9 | @SerialName("custom_server")
10 | val customServer: CurrentServerInfo? = null,
11 | @SerialName("institute_access_server")
12 | val instituteAccessServer: CurrentServerInfo? = null,
13 | @SerialName("secure_internet_server")
14 | val secureInternetServer: CurrentServerInfo? = null,
15 | @SerialName("server_type")
16 | val serverType: Int?
17 | ) {
18 |
19 | private val info : CurrentServerInfo? = customServer ?: instituteAccessServer ?: secureInternetServer
20 | fun getUniqueId(): String? {
21 | return info?.identifier
22 | }
23 |
24 | fun getDisplayName(): TranslatableString? {
25 | return info?.displayName
26 | }
27 |
28 | fun getProfiles(): List? {
29 | return info?.profiles?.getProfileList()
30 | }
31 |
32 | val currentProfile: Profile? = info?.profiles?.currentProfile
33 |
34 | fun asInstance() : Instance? {
35 | if (info == null) {
36 | return null
37 | }
38 | val authorizationType = when (serverType) {
39 | ServerType.Custom.nativeValue -> AuthorizationType.Organization
40 | ServerType.SecureInternet.nativeValue -> AuthorizationType.Distributed
41 | ServerType.InstituteAccess.nativeValue -> AuthorizationType.Local
42 | else -> return null
43 | }
44 | return Instance(
45 | baseURI = getUniqueId() ?: return null,
46 | displayName = getDisplayName() ?: TranslatableString(),
47 | authorizationType = authorizationType,
48 | supportContact = info.supportContacts
49 | )
50 | }
51 | }
52 |
53 | @Serializable
54 | data class CurrentServerInfo (
55 | val identifier: String,
56 |
57 | @SerialName("display_name")
58 | val displayName: TranslatableString,
59 |
60 | val profiles: ProfileWithoutIdMap? = null,
61 |
62 | @SerialName("support_contacts")
63 | val supportContacts: List = emptyList()
64 | )
65 |
66 |
67 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/adapter/ProfileAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 |
18 | package nl.eduvpn.app.adapter
19 |
20 | import android.view.LayoutInflater
21 | import android.view.ViewGroup
22 | import androidx.recyclerview.widget.DiffUtil
23 | import androidx.recyclerview.widget.ListAdapter
24 | import nl.eduvpn.app.adapter.viewholder.ProfileViewHolder
25 | import nl.eduvpn.app.databinding.ListItemProfileBinding
26 | import nl.eduvpn.app.entity.Instance
27 | import nl.eduvpn.app.entity.Profile
28 |
29 | /**
30 | * Adapter for the profile list.
31 | * Created by Daniel Zolnai on 2016-10-11.
32 | */
33 | class ProfileAdapter(private val instance: Instance) : ListAdapter(object : DiffUtil.ItemCallback() {
34 | override fun areItemsTheSame(oldItem: Profile, newItem: Profile): Boolean {
35 | return oldItem.profileId == newItem.profileId
36 | }
37 |
38 | override fun areContentsTheSame(oldItem: Profile, newItem: Profile): Boolean {
39 | return oldItem == newItem
40 | }
41 | }) {
42 |
43 |
44 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileViewHolder {
45 | return ProfileViewHolder(ListItemProfileBinding.inflate(LayoutInflater.from(parent.context), parent, false))
46 | }
47 |
48 | public override fun getItem(position: Int): Profile {
49 | return super.getItem(position)
50 | }
51 |
52 | override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) {
53 | val profile = getItem(position)
54 | holder.bind(instance, profile)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_error.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
23 |
24 |
36 |
37 |
43 |
44 |
57 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/nl/eduvpn/app/WaitUntilGoneAction.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | * Taken from: https://stackoverflow.com/a/63454552/1395437
18 | */
19 |
20 | package nl.eduvpn.app
21 |
22 | import android.view.View
23 | import androidx.test.espresso.PerformException
24 | import androidx.test.espresso.UiController
25 | import androidx.test.espresso.ViewAction
26 | import androidx.test.espresso.util.HumanReadables
27 | import org.hamcrest.CoreMatchers.any
28 | import org.hamcrest.Matcher
29 | import java.util.concurrent.TimeoutException
30 |
31 | class WaitUntilGoneAction(private val timeout: Long) : ViewAction {
32 |
33 | override fun getConstraints(): Matcher {
34 | return any(View::class.java)
35 | }
36 |
37 | override fun getDescription(): String {
38 | return "wait up to $timeout milliseconds for the view to be gone"
39 | }
40 |
41 | override fun perform(uiController: UiController, view: View) {
42 |
43 | val endTime = System.currentTimeMillis() + timeout
44 |
45 | do {
46 | if (view.visibility == View.GONE) return
47 | uiController.loopMainThreadForAtLeast(50)
48 | } while (System.currentTimeMillis() < endTime)
49 |
50 | throw PerformException.Builder()
51 | .withActionDescription(description)
52 | .withCause(TimeoutException("Waited $timeout milliseconds"))
53 | .withViewDescription(HumanReadables.describe(view))
54 | .build()
55 | }
56 | }
57 |
58 | /**
59 | * @return a [WaitUntilGoneAction] instance created with the given [timeout] parameter.
60 | */
61 | fun waitUntilGone(timeout: Long): ViewAction {
62 | return WaitUntilGoneAction(timeout)
63 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/nl/eduvpn/app/ui_test/BrowserTest.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.ui_test
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.uiautomator.UiDevice
5 | import androidx.test.uiautomator.UiObjectNotFoundException
6 | import androidx.test.uiautomator.UiSelector
7 | import nl.eduvpn.app.utils.Log
8 |
9 | abstract class BrowserTest {
10 |
11 | companion object {
12 | private val TAG = BrowserTest::class.java.name
13 | }
14 | fun prepareBrowser() {
15 | // Switch over to UI Automator now, to control the browser
16 | val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
17 | // Wait for the browser to open and load
18 | Thread.sleep(2_000L)
19 | try {
20 | // Newer Chrome versions ask if you want to log in
21 | val acceptButton = device.findObject(UiSelector().text("Use without an account"))
22 | acceptButton.click()
23 | } catch (ex: UiObjectNotFoundException) {
24 | Log.w(TAG, "No Chrome user account shown, continuing", ex)
25 | }
26 | try {
27 | // Chrome asks at first launch to accept data usage
28 | val acceptButton = device.findObject(UiSelector().className("android.widget.Button").text("Accept & continue"))
29 | acceptButton.click()
30 | } catch (ex: UiObjectNotFoundException) {
31 | Log.w(TAG, "No Chrome accept window shown, continuing", ex)
32 | }
33 | try {
34 | // Do not send all our web traffic to Google
35 | val liteModeToggle = device.findObject(UiSelector().className("android.widget.Switch"))
36 | if(liteModeToggle.isChecked) {
37 | liteModeToggle.click()
38 | }
39 | val nextButton = device.findObject(UiSelector().className("android.widget.Button").text("Next"))
40 | nextButton.click()
41 | } catch (ex: UiObjectNotFoundException) {
42 | Log.w(TAG, "No lite mode window shown, continuing", ex)
43 | }
44 | try {
45 | // Now it wants us to Sign in...
46 | val noThanksButton = device.findObject(UiSelector().text("No thanks"))
47 | noThanksButton.click()
48 | } catch (ex: UiObjectNotFoundException) {
49 | Log.w(TAG, "No request for sign in, continung", ex)
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_connection_status_connecting.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
24 |
28 |
32 |
36 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/livedata/ConnectionTimeLiveData.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 |
18 | package nl.eduvpn.app.livedata
19 |
20 | import androidx.lifecycle.LiveData
21 | import androidx.lifecycle.MediatorLiveData
22 | import nl.eduvpn.app.service.VPNService
23 |
24 | /**
25 | * Amount of seconds connected to the VPN.
26 | */
27 | object ConnectionTimeLiveData {
28 |
29 | fun create(
30 | vpnStatusLiveData: LiveData,
31 | timer: LiveData
32 | ): LiveData {
33 | var connectionTime = 0L
34 |
35 | val connectionTimeLiveData = MediatorLiveData()
36 |
37 | val update = {
38 | connectionTimeLiveData.value = (System.currentTimeMillis() - connectionTime) / 1000L
39 | }
40 |
41 | // we do not want to miss connected / disconnected events when the user puts the app in the
42 | // background, so observeForever
43 | vpnStatusLiveData.observeForever { vpnStatus ->
44 | if (vpnStatus == VPNService.VPNStatus.CONNECTED) {
45 | connectionTime = System.currentTimeMillis()
46 | connectionTimeLiveData.value = 0
47 | try {
48 | // the timer will be automatically stopped onPause and will be restarted onResume
49 | connectionTimeLiveData.addSource(timer) { update() }
50 | } catch (ex: IllegalArgumentException) {
51 | // timer already added as source
52 | }
53 | } else if (vpnStatus == VPNService.VPNStatus.DISCONNECTED) {
54 | connectionTimeLiveData.removeSource(timer)
55 | connectionTimeLiveData.value = -1
56 | }
57 | }
58 |
59 | return connectionTimeLiveData
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item_profile.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
21 |
22 |
30 |
31 |
42 |
43 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/inject/EduVPNComponent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 | package nl.eduvpn.app.inject
18 |
19 | import dagger.Component
20 | import nl.eduvpn.app.ApiLogsActivity
21 | import nl.eduvpn.app.CertExpiredBroadcastReceiver
22 | import nl.eduvpn.app.DisconnectVPNBroadcastReceiver
23 | import nl.eduvpn.app.EduVPNApplication
24 | import nl.eduvpn.app.MainActivity
25 | import nl.eduvpn.app.OpenVpnLogsActivity
26 | import nl.eduvpn.app.fragment.*
27 | import javax.inject.Singleton
28 |
29 | /**
30 | * The Dagger component which executes the injections.
31 | * Created by Daniel Zolnai on 2016-10-07.
32 | */
33 | @Singleton
34 | @Component(modules = [ApplicationModule::class])
35 | interface EduVPNComponent {
36 | object Initializer {
37 | @JvmStatic
38 | fun init(application: EduVPNApplication?): EduVPNComponent { // Don't worry if you see an error here, DaggerEduVPNComponent is generated while building.
39 | return DaggerEduVPNComponent.builder()
40 | .applicationModule(ApplicationModule(application!!)).build()
41 | }
42 | }
43 |
44 | fun inject(organizationSelectionFragment: OrganizationSelectionFragment)
45 | fun inject(mainActivity: MainActivity)
46 | fun inject(apiLogsActivity: ApiLogsActivity)
47 | fun inject(apiLogsActivity: OpenVpnLogsActivity)
48 | fun inject(connectionStatusFragment: ConnectionStatusFragment)
49 | fun inject(homeFragment: ProfileSelectionFragment)
50 | fun inject(settingsFragment: SettingsFragment)
51 | fun inject(serverSelectionFragment: ServerSelectionFragment)
52 | fun inject(addServerFragment: AddServerFragment)
53 | fun inject(certExpiredBroadcastReceiver: CertExpiredBroadcastReceiver)
54 | fun inject(disconnectVPNBroadcastReceiver: DisconnectVPNBroadcastReceiver)
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/inject/ViewModelModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | *
17 | */
18 |
19 | package nl.eduvpn.app.inject
20 |
21 | import android.view.View
22 | import androidx.lifecycle.ViewModel
23 | import dagger.Binds
24 | import dagger.Module
25 | import dagger.multibindings.IntoMap
26 | import nl.eduvpn.app.viewmodel.*
27 |
28 | @Module
29 | interface ViewModelModule {
30 |
31 | @Binds
32 | @IntoMap
33 | @ViewModelKey(OrganizationSelectionViewModel::class)
34 | fun bindOrganizationSelectionViewModel(organizationSelectionViewModel: OrganizationSelectionViewModel): ViewModel
35 |
36 | @Binds
37 | @IntoMap
38 | @ViewModelKey(ServerSelectionViewModel::class)
39 | fun bindServerSelectionViewModel(serverSelectionViewModel: ServerSelectionViewModel): ViewModel
40 |
41 | @Binds
42 | @IntoMap
43 | @ViewModelKey(ConnectionStatusViewModel::class)
44 | fun bindConnectionStatusViewModel(connectionStatusViewModel: ConnectionStatusViewModel): ViewModel
45 |
46 | @Binds
47 | @IntoMap
48 | @ViewModelKey(ProfileSelectionViewModel::class)
49 | fun bindProfileSelectionViewModel(profileSelectionViewModel: ProfileSelectionViewModel): ViewModel
50 |
51 | @Binds
52 | @IntoMap
53 | @ViewModelKey(AddServerViewModel::class)
54 | fun bindAddServerViewModel(addServerViewModel: AddServerViewModel): ViewModel
55 |
56 | @Binds
57 | @IntoMap
58 | @ViewModelKey(MainViewModel::class)
59 | fun bindMainViewModel(mainViewModel: MainViewModel): ViewModel
60 |
61 | @Binds
62 | @IntoMap
63 | @ViewModelKey(SettingsViewModel::class)
64 | fun bindSettingsViewModel(settingsViewModel: SettingsViewModel): ViewModel
65 |
66 | @Binds
67 | @IntoMap
68 | @ViewModelKey(ApiLogsViewModel::class)
69 | fun bindApiLogsViewModel(apiLogsViewModel: ApiLogsViewModel): ViewModel
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/SettingsActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of eduVPN.
3 | *
4 | * eduVPN is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * eduVPN is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with eduVPN. If not, see .
16 | */
17 | package nl.eduvpn.app
18 |
19 | import android.content.Intent
20 | import android.content.res.ColorStateList
21 | import android.net.Uri
22 | import android.os.Bundle
23 | import android.view.MenuItem
24 | import android.view.View
25 | import androidx.core.content.ContextCompat
26 | import androidx.core.view.isVisible
27 | import nl.eduvpn.app.base.BaseActivity
28 | import nl.eduvpn.app.databinding.ActivitySettingsBinding
29 | import nl.eduvpn.app.fragment.SettingsFragment
30 |
31 | /**
32 | * Activity which displays the settings fragment.
33 | * Created by Daniel Zolnai on 2016-10-22.
34 | */
35 | class SettingsActivity : BaseActivity() {
36 | override val layout: Int get() = R.layout.activity_settings
37 |
38 | override fun onCreate(savedInstanceState: Bundle?) {
39 | super.onCreate(savedInstanceState)
40 | supportFragmentManager.beginTransaction()
41 | .replace(R.id.content_frame, SettingsFragment())
42 | .commit()
43 | setSupportActionBar(binding.toolbar.toolbar)
44 | supportActionBar?.setDisplayHomeAsUpEnabled(true)
45 | binding.toolbar.settingsButton.isVisible = false
46 | binding.toolbar.helpButton.setOnClickListener { _: View ->
47 | startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.HELP_URI)))
48 | }
49 | }
50 |
51 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
52 | return if (item.itemId == android.R.id.home) {
53 | onBackPressedDispatcher.onBackPressed()
54 | true
55 | } else {
56 | super.onOptionsItemSelected(item)
57 | }
58 | }
59 |
60 | companion object {
61 | const val RESULT_APP_DATA_CLEARED = 101
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/nl/eduvpn/app/entity/AddedServers.kt:
--------------------------------------------------------------------------------
1 | package nl.eduvpn.app.entity
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 |
6 | @Serializable
7 | data class AddedServers(
8 | @SerialName("custom_servers")
9 | val customServers: List? = emptyList(),
10 | @SerialName("secure_internet_server")
11 | val secureInternetServer: AddedServer? = null,
12 | @SerialName("institute_access_servers")
13 | val instituteAccessServers: List? = emptyList()
14 | ) {
15 | fun hasServers() : Boolean {
16 | return !customServers.isNullOrEmpty() || secureInternetServer != null || !instituteAccessServers.isNullOrEmpty()
17 | }
18 |
19 | fun asInstances() : List {
20 | val result = mutableListOf()
21 | result += customServers?.map {
22 | Instance(
23 | baseURI = it.identifier,
24 | displayName = it.displayName,
25 | authorizationType = AuthorizationType.Organization,
26 | countryCode = it.countryCode,
27 | supportContact = it.supportContacts,
28 | isCustom = true
29 | )
30 | } ?: emptyList()
31 | result += instituteAccessServers?.map {
32 | Instance(
33 | baseURI = it.identifier,
34 | displayName = it.displayName,
35 | authorizationType = AuthorizationType.Local,
36 | countryCode = it.countryCode,
37 | supportContact = it.supportContacts,
38 | isCustom = false
39 | )
40 | } ?: emptyList()
41 | secureInternetServer?.let {
42 | result += listOf(Instance(
43 | baseURI = it.identifier,
44 | displayName = it.displayName,
45 | authorizationType = AuthorizationType.Distributed,
46 | countryCode = it.countryCode,
47 | supportContact = it.supportContacts,
48 | isCustom = false
49 | ))
50 | }
51 | return result
52 | }
53 | }
54 |
55 | @Serializable
56 | data class AddedServer(
57 | @SerialName("display_name")
58 | val displayName: TranslatableString,
59 | @SerialName("identifier")
60 | val identifier: String,
61 | @SerialName("country_code")
62 | val countryCode: String? = null,
63 | @SerialName("support_contacts")
64 | val supportContacts: List = emptyList(),
65 | @SerialName("locations")
66 | val locations: List = emptyList()
67 | )
--------------------------------------------------------------------------------