eduvpn-client 4.3.0__2-py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eduvpn/__init__.py +1 -0
- eduvpn/__main__.py +4 -0
- eduvpn/app.py +628 -0
- eduvpn/cli.py +720 -0
- eduvpn/config.py +68 -0
- eduvpn/connection.py +244 -0
- eduvpn/data/share/applications/org.eduvpn.client.desktop +10 -0
- eduvpn/data/share/applications/org.letsconnect-vpn.client.desktop +10 -0
- eduvpn/data/share/eduvpn/builder/mainwindow.ui +1811 -0
- eduvpn/data/share/eduvpn/country_codes.json +1001 -0
- eduvpn/data/share/eduvpn/eduvpn.png +0 -0
- eduvpn/data/share/eduvpn/images/app-icon-circle.svg +16 -0
- eduvpn/data/share/eduvpn/images/app-icon-circle@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/app-icon-circle@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/back.png +0 -0
- eduvpn/data/share/eduvpn/images/back@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/back@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/chevron-down.png +0 -0
- eduvpn/data/share/eduvpn/images/chevron-down@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/chevron-down@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/chevron-right-white.png +0 -0
- eduvpn/data/share/eduvpn/images/chevron-right-white@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/chevron-right-white@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/chevron-right.png +0 -0
- eduvpn/data/share/eduvpn/images/chevron-right@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/chevron-right@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/cross.png +0 -0
- eduvpn/data/share/eduvpn/images/cross@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/cross@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-connected.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-connected@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-connected@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-connecting.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-connecting@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-connecting@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-default.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-default@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-default@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-not-connected.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-not-connected@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/desktop-not-connected@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/earth-icon-dark.png +0 -0
- eduvpn/data/share/eduvpn/images/earth-icon-dark@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/earth-icon-dark@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/earth-icon.png +0 -0
- eduvpn/data/share/eduvpn/images/earth-icon@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/earth-icon@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/edu-vpn-logo-dark.png +0 -0
- eduvpn/data/share/eduvpn/images/edu-vpn-logo-dark@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/edu-vpn-logo-dark@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/edu-vpn-logo.png +0 -0
- eduvpn/data/share/eduvpn/images/edu-vpn-logo@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/edu-vpn-logo@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AD@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AD@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AD@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AF@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AF@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AF@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AI@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AI@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AI@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AL@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AL@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AL@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AQ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AQ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AQ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AW@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AW@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AW@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AX@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AX@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AX@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AZ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AZ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/AZ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Artsakh@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Artsakh@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Artsakh@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BB@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BB@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BB@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BD@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BD@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BD@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BF@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BF@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BF@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BH@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BH@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BH@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BI@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BI@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BI@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BJ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BJ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BJ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BQ-BO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BQ-BO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BQ-BO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BQ-SA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BQ-SA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BQ-SA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BQ-SE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BQ-SE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BQ-SE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BW@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BW@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BW@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BY@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BY@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BY@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BZ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BZ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/BZ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-AB@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-AB@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-AB@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-BC@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-BC@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-BC@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-MB@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-MB@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-MB@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NB@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NB@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NB@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NL@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NL@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NL@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-NU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-ON@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-ON@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-ON@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-PE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-PE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-PE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-QC@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-QC@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-QC@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-SK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-SK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-SK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-YT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-YT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA-YT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CC@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CC@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CC@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CD@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CD@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CD@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CF@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CF@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CF@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CH@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CH@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CH@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CI@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CI@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CI@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CL@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CL@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CL@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CV@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CV@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CV@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CW@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CW@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CW@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CX@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CX@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CX@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CY@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CY@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CY@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CZ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CZ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/CZ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Chechnya@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Chechnya@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Chechnya@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DJ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DJ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DJ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DZ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DZ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/DZ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EC@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EC@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EC@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EH@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EH@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EH@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ER@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ER@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ER@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ES-CT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ES-CT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ES-CT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ES@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ES@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ES@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ET@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ET@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ET@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/EU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/England-Symbol@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/England-Symbol@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/England-Symbol@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FI@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FI@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FI@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FJ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FJ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FJ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR-MQ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR-MQ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR-MQ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR-TF@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR-TF@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR-TF@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR-YT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR-YT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR-YT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/FR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/France-Symbol@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/France-Symbol@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/France-Symbol@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-ENG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-ENG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-ENG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-SCT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-SCT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-SCT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-Symbol@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-Symbol@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-Symbol@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-WLS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-WLS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB-WLS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GB@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GD@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GD@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GD@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GE-AB@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GE-AB@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GE-AB@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GH@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GH@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GH@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GI@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GI@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GI@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GL@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GL@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GL@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GQ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GQ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GQ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GW@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GW@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GW@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GY@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GY@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/GY@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/HU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ID@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ID@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ID@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IL@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IL@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IL@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IQ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IQ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IQ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/IT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JP@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JP@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/JP@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KH@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KH@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KH@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KI@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KI@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KI@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KP@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KP@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KP@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KW@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KW@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KW@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KY@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KY@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KY@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KZ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KZ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/KZ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Kurdistan@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Kurdistan@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Kurdistan@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LB@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LB@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LB@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LC@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LC@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LC@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LI@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LI@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LI@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LV@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LV@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LV@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LY@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LY@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/LY@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MC@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MC@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MC@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MD@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MD@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MD@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ME@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ME@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ME@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MH@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MH@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MH@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ML@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ML@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ML@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MP@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MP@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MP@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MV@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MV@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MV@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MW@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MW@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MW@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MX@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MX@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MX@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MY@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MY@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MY@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MZ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MZ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/MZ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NC@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NC@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NC@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NF@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NF@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NF@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NI@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NI@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NI@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NL@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NL@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NL@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NP@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NP@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NP@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NZ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NZ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/NZ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Netherlands Antilles@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Netherlands Antilles@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Netherlands Antilles@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/OM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/OM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/OM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Overlay@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Overlay@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Overlay@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PF@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PF@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PF@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PH@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PH@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PH@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PL@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PL@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PL@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PW@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PW@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PW@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PY@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PY@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/PY@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/QA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/QA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/QA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RW@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RW@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/RW@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Red Peak Flag (NZ)@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Red Peak Flag (NZ)@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Red Peak Flag (NZ)@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SB@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SB@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SB@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SC@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SC@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SC@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SD@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SD@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SD@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SH-HL@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SH-HL@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SH-HL@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SI@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SI@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SI@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SL@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SL@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SL@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ST@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ST@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ST@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SV@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SV@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SV@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SX@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SX@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SX@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SY@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SY@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SY@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SZ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SZ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/SZ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Sealand@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Sealand@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Sealand@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Serb Republic@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Serb Republic@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Serb Republic@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/South Ossetia@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/South Ossetia@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/South Ossetia@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TC@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TC@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TC@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TD@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TD@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TD@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TH@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TH@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TH@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TJ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TJ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TJ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TL@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TL@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TL@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TO@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TO@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TO@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TR@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TR@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TR@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TT@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TT@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TT@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TV@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TV@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TV@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TW@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TW@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TW@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TZ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TZ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/TZ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Transnistria@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Transnistria@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Transnistria@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Turkish Republic of Northern Cyprus@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Turkish Republic of Northern Cyprus@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/Turkish Republic of Northern Cyprus@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/US@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/US@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/US@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UY@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UY@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UY@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UZ@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UZ@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/UZ@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VC@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VC@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VC@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VG@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VG@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VG@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VI@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VI@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VI@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VN@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VN@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VN@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VU@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VU@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/VU@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/WS@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/WS@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/WS@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/XK@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/XK@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/XK@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/YE@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/YE@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/YE@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ZA@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ZA@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ZA@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ZM@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ZM@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ZM@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ZW@1,5x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ZW@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/flags/png/ZW@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/group.png +0 -0
- eduvpn/data/share/eduvpn/images/group@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/group@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/institute-icon-dark.png +0 -0
- eduvpn/data/share/eduvpn/images/institute-icon-dark@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/institute-icon-dark@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/institute-icon.png +0 -0
- eduvpn/data/share/eduvpn/images/institute-icon@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/institute-icon@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/institute.png +0 -0
- eduvpn/data/share/eduvpn/images/institute@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/institute@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/question-icon-dark.png +0 -0
- eduvpn/data/share/eduvpn/images/question-icon-dark@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/question-icon-dark@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/question-icon.png +0 -0
- eduvpn/data/share/eduvpn/images/question-icon@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/question-icon@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/server-icon-dark.png +0 -0
- eduvpn/data/share/eduvpn/images/server-icon-dark@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/server-icon-dark@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/server-icon.png +0 -0
- eduvpn/data/share/eduvpn/images/server-icon@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/server-icon@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/settings-dark.png +0 -0
- eduvpn/data/share/eduvpn/images/settings-dark@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/settings-dark@3x.png +0 -0
- eduvpn/data/share/eduvpn/images/settings.png +0 -0
- eduvpn/data/share/eduvpn/images/settings@2x.png +0 -0
- eduvpn/data/share/eduvpn/images/settings@3x.png +0 -0
- eduvpn/data/share/icons/hicolor/128x128/apps/org.eduvpn.client.png +0 -0
- eduvpn/data/share/icons/hicolor/128x128/apps/org.letsconnect-vpn.client.png +0 -0
- eduvpn/data/share/icons/hicolor/256x256/apps/org.eduvpn.client.png +0 -0
- eduvpn/data/share/icons/hicolor/256x256/apps/org.letsconnect-vpn.client.png +0 -0
- eduvpn/data/share/icons/hicolor/48x48/apps/org.eduvpn.client.png +0 -0
- eduvpn/data/share/icons/hicolor/48x48/apps/org.letsconnect-vpn.client.png +0 -0
- eduvpn/data/share/icons/hicolor/512x512/apps/org.eduvpn.client.png +0 -0
- eduvpn/data/share/icons/hicolor/512x512/apps/org.letsconnect-vpn.client.png +0 -0
- eduvpn/data/share/letsconnect/images/app-icon-circle.svg +6 -0
- eduvpn/data/share/letsconnect/images/letsconnect.png +0 -0
- eduvpn/data/share/letsconnect/images/letsconnect@2x.png +0 -0
- eduvpn/data/share/letsconnect/images/letsconnect@3x.png +0 -0
- eduvpn/data/share/letsconnect/images/server-illustration.png +0 -0
- eduvpn/data/share/letsconnect/images/server-illustration@2x.png +0 -0
- eduvpn/data/share/letsconnect/images/server-illustration@3x.png +0 -0
- eduvpn/data/share/locale/Makefile +34 -0
- eduvpn/data/share/locale/de_DE/LC_MESSAGES/eduVPN.mo +0 -0
- eduvpn/data/share/locale/de_DE/LC_MESSAGES/eduVPN.po +228 -0
- eduvpn/data/share/locale/eduVPN.pot +226 -0
- eduvpn/data/share/locale/es_LA/LC_MESSAGES/eduVPN.mo +0 -0
- eduvpn/data/share/locale/es_LA/LC_MESSAGES/eduVPN.po +228 -0
- eduvpn/discovery.py +95 -0
- eduvpn/i18n.py +104 -0
- eduvpn/keyring.py +155 -0
- eduvpn/nm.py +916 -0
- eduvpn/notify.py +34 -0
- eduvpn/ovpn.py +99 -0
- eduvpn/server.py +313 -0
- eduvpn/settings.py +29 -0
- eduvpn/storage.py +71 -0
- eduvpn/ui/__init__.py +0 -0
- eduvpn/ui/__main__.py +56 -0
- eduvpn/ui/app.py +146 -0
- eduvpn/ui/search.py +197 -0
- eduvpn/ui/stats.py +106 -0
- eduvpn/ui/ui.py +1490 -0
- eduvpn/ui/utils.py +167 -0
- eduvpn/utils.py +253 -0
- eduvpn/variants.py +72 -0
- eduvpn_client-4.3.0.dist-info/LICENSE +674 -0
- eduvpn_client-4.3.0.dist-info/LICENSE.spdx +20 -0
- eduvpn_client-4.3.0.dist-info/METADATA +52 -0
- eduvpn_client-4.3.0.dist-info/RECORD +951 -0
- eduvpn_client-4.3.0.dist-info/WHEEL +5 -0
- eduvpn_client-4.3.0.dist-info/entry_points.txt +7 -0
- eduvpn_client-4.3.0.dist-info/top_level.txt +1 -0
eduvpn/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "4.3.0"
|
eduvpn/__main__.py
ADDED
eduvpn/app.py
ADDED
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import signal
|
|
5
|
+
import time
|
|
6
|
+
import webbrowser
|
|
7
|
+
from typing import Any, Callable, Iterator, Optional, TextIO
|
|
8
|
+
|
|
9
|
+
from eduvpn_common.main import EduVPN, ServerType, WrappedError
|
|
10
|
+
from eduvpn_common.state import State, StateType
|
|
11
|
+
from eduvpn_common.types import ProxyReady, ProxySetup, ReadRxBytes
|
|
12
|
+
|
|
13
|
+
from eduvpn import nm
|
|
14
|
+
from eduvpn.config import Configuration
|
|
15
|
+
from eduvpn.connection import Config, Connection, Protocol, parse_config, parse_expiry, parse_tokens
|
|
16
|
+
from eduvpn.keyring import DBusKeyring, InsecureFileKeyring, TokenKeyring
|
|
17
|
+
from eduvpn.server import ServerDatabase, parse_profiles, parse_required_transition
|
|
18
|
+
from eduvpn.utils import (
|
|
19
|
+
handle_exception,
|
|
20
|
+
model_transition,
|
|
21
|
+
run_in_background_thread,
|
|
22
|
+
run_in_glib_thread,
|
|
23
|
+
set_failovered,
|
|
24
|
+
set_online_detecting,
|
|
25
|
+
)
|
|
26
|
+
from eduvpn.variants import ApplicationVariant
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ApplicationModelTransitions:
|
|
32
|
+
def __init__(self, common: EduVPN, variant: ApplicationVariant) -> None:
|
|
33
|
+
self.common = common
|
|
34
|
+
self.common.register_class_callbacks(self)
|
|
35
|
+
self.server_db = ServerDatabase(common, variant.use_predefined_servers)
|
|
36
|
+
|
|
37
|
+
@model_transition(State.MAIN, StateType.ENTER)
|
|
38
|
+
def get_previous_servers(self, old_state: State, data):
|
|
39
|
+
logger.debug(f"Transition: MAIN, old state: {old_state}")
|
|
40
|
+
return self.server_db.configured
|
|
41
|
+
|
|
42
|
+
@model_transition(State.DEREGISTERED, StateType.ENTER)
|
|
43
|
+
def deregistered(self, old_state: State, data: str):
|
|
44
|
+
logger.debug(f"Transition: DEREGISTERED, old state: {old_state}")
|
|
45
|
+
return data
|
|
46
|
+
|
|
47
|
+
@model_transition(State.ADDING_SERVER, StateType.ENTER)
|
|
48
|
+
def adding_server(self, old_state: State, data: str):
|
|
49
|
+
logger.debug(f"Transition: ADDING_SERVER, old state: {old_state}")
|
|
50
|
+
return data
|
|
51
|
+
|
|
52
|
+
@model_transition(State.GETTING_CONFIG, StateType.ENTER)
|
|
53
|
+
def getting_config(self, old_state: State, data: str):
|
|
54
|
+
logger.debug(f"Transition: GETTING_CONFIG, old state: {old_state}")
|
|
55
|
+
return data
|
|
56
|
+
|
|
57
|
+
@model_transition(State.DISCONNECTED, StateType.ENTER)
|
|
58
|
+
def disconnected_server(self, old_state: State, data: str):
|
|
59
|
+
logger.debug(f"Transition: DISCONNECTED, old state: {old_state}")
|
|
60
|
+
return self.server_db.current
|
|
61
|
+
|
|
62
|
+
@model_transition(State.DISCONNECTING, StateType.ENTER)
|
|
63
|
+
def disconnecting(self, old_state: State, data):
|
|
64
|
+
logger.debug(f"Transition: DISCONNECTING, old state: {old_state}")
|
|
65
|
+
return self.server_db.current
|
|
66
|
+
|
|
67
|
+
@model_transition(State.ASK_PROFILE, StateType.ENTER)
|
|
68
|
+
def ask_profile(self, old_state: State, data: str):
|
|
69
|
+
logger.debug(f"Transition: ASK_PROFILE, old state: {old_state}")
|
|
70
|
+
cookie, profiles = parse_required_transition(data, get=parse_profiles)
|
|
71
|
+
|
|
72
|
+
def set_profile(prof):
|
|
73
|
+
self.common.cookie_reply(cookie, prof)
|
|
74
|
+
|
|
75
|
+
return (set_profile, profiles)
|
|
76
|
+
|
|
77
|
+
@model_transition(State.ASK_LOCATION, StateType.ENTER)
|
|
78
|
+
def ask_location(self, old_state: State, data):
|
|
79
|
+
cookie, locations = parse_required_transition(data)
|
|
80
|
+
|
|
81
|
+
def set_location(loc):
|
|
82
|
+
self.common.cookie_reply(cookie, loc)
|
|
83
|
+
|
|
84
|
+
return (set_location, locations)
|
|
85
|
+
|
|
86
|
+
@model_transition(State.OAUTH_STARTED, StateType.ENTER)
|
|
87
|
+
def start_oauth(self, old_state: State, url: str):
|
|
88
|
+
logger.debug(f"Transition: OAUTH_STARTED, old state: {old_state}")
|
|
89
|
+
self.open_browser(url)
|
|
90
|
+
return url
|
|
91
|
+
|
|
92
|
+
@model_transition(State.GOT_CONFIG, StateType.ENTER)
|
|
93
|
+
def parse_config(self, old_state: State, data):
|
|
94
|
+
logger.debug(f"Transition: GOT_CONFIG, old state: {old_state}")
|
|
95
|
+
return self.server_db.current
|
|
96
|
+
|
|
97
|
+
@run_in_background_thread("open-browser")
|
|
98
|
+
def open_browser(self, url):
|
|
99
|
+
logger.debug(f"Opening web browser with url: {url}")
|
|
100
|
+
webbrowser.open(url)
|
|
101
|
+
# Explicitly wait to not have zombie processes
|
|
102
|
+
# See https://bugs.python.org/issue5993
|
|
103
|
+
logger.debug("Running os.wait for browser")
|
|
104
|
+
try:
|
|
105
|
+
os.wait()
|
|
106
|
+
except ChildProcessError:
|
|
107
|
+
pass
|
|
108
|
+
logger.debug("Done waiting for browser")
|
|
109
|
+
|
|
110
|
+
@model_transition(State.CONNECTED, StateType.ENTER)
|
|
111
|
+
def parse_connected(self, old_state: State, data):
|
|
112
|
+
logger.debug(f"Transition: CONNECTED, old state: {old_state}")
|
|
113
|
+
server = self.server_db.current
|
|
114
|
+
expire_times = parse_expiry(self.common.get_expiry_times())
|
|
115
|
+
return (server, expire_times)
|
|
116
|
+
|
|
117
|
+
@model_transition(State.CONNECTING, StateType.ENTER)
|
|
118
|
+
def parse_connecting(self, old_state: State, data):
|
|
119
|
+
logger.debug(f"Transition: CONNECTING, old state: {old_state}")
|
|
120
|
+
return self.server_db.current
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class ApplicationModel:
|
|
124
|
+
def __init__(
|
|
125
|
+
self,
|
|
126
|
+
common: EduVPN,
|
|
127
|
+
config,
|
|
128
|
+
variant: ApplicationVariant,
|
|
129
|
+
nm_manager,
|
|
130
|
+
) -> None:
|
|
131
|
+
self.common = common
|
|
132
|
+
self.config = config
|
|
133
|
+
self._keyring: TokenKeyring | None = None
|
|
134
|
+
self.transitions = ApplicationModelTransitions(common, variant)
|
|
135
|
+
self.variant = variant
|
|
136
|
+
self.nm_manager = nm_manager
|
|
137
|
+
self._was_tcp = False
|
|
138
|
+
self._should_failover = False
|
|
139
|
+
self._peer_ips_proxy = None
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def keyring(self):
|
|
143
|
+
if self._keyring is not None:
|
|
144
|
+
return self._keyring
|
|
145
|
+
keyring = DBusKeyring(self.variant)
|
|
146
|
+
if not keyring.available:
|
|
147
|
+
logger.warning("Secure keyring not available, reverting to insecure file keyring!")
|
|
148
|
+
keyring = InsecureFileKeyring(self.variant)
|
|
149
|
+
self._keyring = keyring
|
|
150
|
+
return self._keyring
|
|
151
|
+
|
|
152
|
+
def register(self, debug: bool):
|
|
153
|
+
self.common.register(debug=debug)
|
|
154
|
+
self.common.set_token_handler(self.load_tokens, self.save_tokens)
|
|
155
|
+
|
|
156
|
+
def cancel(self):
|
|
157
|
+
# Cancel any eduvpn-common operation
|
|
158
|
+
self.common.cancel()
|
|
159
|
+
|
|
160
|
+
# Cancel any NetworkManager operation
|
|
161
|
+
self.nm_manager.cancel()
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def server_db(self):
|
|
165
|
+
return self.transitions.server_db
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def current_server(self):
|
|
169
|
+
return self.server_db.current
|
|
170
|
+
|
|
171
|
+
def get_failover_rx(self, filehandler: Optional[TextIO]) -> int:
|
|
172
|
+
rx_bytes = self.nm_manager.get_stats_bytes(filehandler)
|
|
173
|
+
if rx_bytes is None:
|
|
174
|
+
return -1
|
|
175
|
+
return rx_bytes
|
|
176
|
+
|
|
177
|
+
def should_failover(self):
|
|
178
|
+
if self._should_failover:
|
|
179
|
+
logger.debug("eduvpn-common reports we should failover")
|
|
180
|
+
|
|
181
|
+
if self._was_tcp:
|
|
182
|
+
logger.debug("TCP was not previously triggered, failover should not continue")
|
|
183
|
+
return False
|
|
184
|
+
return True
|
|
185
|
+
|
|
186
|
+
logger.debug("Failover should not continue")
|
|
187
|
+
return False
|
|
188
|
+
|
|
189
|
+
def reconnect_tcp(self, callback: Callable):
|
|
190
|
+
def on_reconnected(success: bool):
|
|
191
|
+
callback(success)
|
|
192
|
+
|
|
193
|
+
self.reconnect(on_reconnected, prefer_tcp=True)
|
|
194
|
+
|
|
195
|
+
@run_in_background_thread("start-failover")
|
|
196
|
+
def start_failover(self, callback: Callable):
|
|
197
|
+
try:
|
|
198
|
+
rx_bytes_file = self.nm_manager.open_stats_file("rx_bytes")
|
|
199
|
+
if rx_bytes_file is None:
|
|
200
|
+
logger.error("Failed to initialize failover, failed to open rx bytes file")
|
|
201
|
+
callback(False)
|
|
202
|
+
return
|
|
203
|
+
endpoint = self.nm_manager.failover_endpoint_ip
|
|
204
|
+
if endpoint is None:
|
|
205
|
+
logger.error("Failed to initialize failover, failed to get endpoint")
|
|
206
|
+
callback(False)
|
|
207
|
+
return
|
|
208
|
+
mtu = self.nm_manager.mtu
|
|
209
|
+
if mtu is None:
|
|
210
|
+
logger.debug("failed to get MTU for failover, setting MTU to 1000")
|
|
211
|
+
mtu = 1000
|
|
212
|
+
logger.debug(
|
|
213
|
+
f"starting failover with gateway {endpoint} and MTU {mtu} for protocol {self.nm_manager.protocol}"
|
|
214
|
+
)
|
|
215
|
+
failover_delay = float(os.getenv("EDUVPN_FAILOVER_DELAY", 1))
|
|
216
|
+
logger.debug(f"Sleeping for {failover_delay}s to begin failover")
|
|
217
|
+
time.sleep(failover_delay)
|
|
218
|
+
dropped = self.common.start_failover(
|
|
219
|
+
endpoint,
|
|
220
|
+
mtu,
|
|
221
|
+
ReadRxBytes(lambda: self.get_failover_rx(rx_bytes_file)),
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
if dropped:
|
|
225
|
+
logger.debug("Failover exited, connection is dropped")
|
|
226
|
+
callback(True)
|
|
227
|
+
else:
|
|
228
|
+
logger.debug("Failover exited, connection is NOT dropped")
|
|
229
|
+
callback(False)
|
|
230
|
+
except WrappedError as e:
|
|
231
|
+
logger.debug(f"Failed failover, error: {e}")
|
|
232
|
+
callback(False)
|
|
233
|
+
|
|
234
|
+
def change_secure_location(self, country_code: str):
|
|
235
|
+
server = self.server_db.secure_internet
|
|
236
|
+
if server.country_code == country_code:
|
|
237
|
+
return
|
|
238
|
+
self.common.set_secure_location(server.org_id, country_code)
|
|
239
|
+
self.common.set_state(State.MAIN)
|
|
240
|
+
|
|
241
|
+
def go_back(self):
|
|
242
|
+
self.cancel()
|
|
243
|
+
self.common.set_state(State.MAIN)
|
|
244
|
+
|
|
245
|
+
def add(self, server, callback=None):
|
|
246
|
+
self.common.add_server(server.category_id, server.identifier)
|
|
247
|
+
if callback:
|
|
248
|
+
callback(server)
|
|
249
|
+
|
|
250
|
+
def remove(self, server):
|
|
251
|
+
self.common.remove_server(server.category_id, server.identifier)
|
|
252
|
+
# Delete tokens from the keyring
|
|
253
|
+
self.clear_tokens(server.category_id, server.identifier)
|
|
254
|
+
self.common.set_state(State.MAIN)
|
|
255
|
+
|
|
256
|
+
def connect_get_config(self, server, prefer_tcp: bool = False) -> Config:
|
|
257
|
+
# We prefer TCP if the user has set it or UDP is determined to be blocked
|
|
258
|
+
config = self.common.get_config(server.category_id, server.identifier, prefer_tcp)
|
|
259
|
+
return parse_config(config)
|
|
260
|
+
|
|
261
|
+
def clear_tokens(self, server_type: int, server_id: str):
|
|
262
|
+
attributes = {
|
|
263
|
+
"server": server_id,
|
|
264
|
+
"category": str(ServerType(server_type)),
|
|
265
|
+
}
|
|
266
|
+
try:
|
|
267
|
+
cleared = self.keyring.clear(attributes)
|
|
268
|
+
if not cleared:
|
|
269
|
+
logger.debug("Tokens were not cleared")
|
|
270
|
+
except Exception as e:
|
|
271
|
+
logger.debug("Failed clearing tokens with exception")
|
|
272
|
+
logger.debug(e, exc_info=True)
|
|
273
|
+
|
|
274
|
+
def load_tokens(self, server_id: str, server_type: int) -> Optional[str]:
|
|
275
|
+
attributes = {"server": server_id, "category": str(ServerType(server_type))}
|
|
276
|
+
try:
|
|
277
|
+
tokens_json = self.keyring.load(attributes)
|
|
278
|
+
if tokens_json is None:
|
|
279
|
+
logger.debug("No tokens available")
|
|
280
|
+
return None
|
|
281
|
+
tokens = json.loads(tokens_json)
|
|
282
|
+
expires = tokens.get("expires_at", None)
|
|
283
|
+
if expires is None:
|
|
284
|
+
expires = tokens.get("expires", None)
|
|
285
|
+
if expires is None:
|
|
286
|
+
logger.warning("failed to parse expires")
|
|
287
|
+
return None
|
|
288
|
+
d = {
|
|
289
|
+
"access_token": tokens["access"],
|
|
290
|
+
"refresh_token": tokens["refresh"],
|
|
291
|
+
"expires_at": int(expires),
|
|
292
|
+
}
|
|
293
|
+
return json.dumps(d)
|
|
294
|
+
except Exception as e:
|
|
295
|
+
logger.debug("Failed loading tokens with exception:")
|
|
296
|
+
logger.debug(e, exc_info=True)
|
|
297
|
+
return None
|
|
298
|
+
|
|
299
|
+
def save_tokens(self, server_id: str, server_type: int, tokens: str):
|
|
300
|
+
tokens_parsed = parse_tokens(tokens)
|
|
301
|
+
if tokens is None or (tokens_parsed.access == "" and tokens_parsed.refresh == ""):
|
|
302
|
+
logger.warning("Got empty tokens, not saving them to the keyring")
|
|
303
|
+
return
|
|
304
|
+
tokens_dict = {}
|
|
305
|
+
tokens_dict["access"] = tokens_parsed.access
|
|
306
|
+
tokens_dict["refresh"] = tokens_parsed.refresh
|
|
307
|
+
tokens_dict["expires_at"] = str(tokens_parsed.expires)
|
|
308
|
+
attributes = {"server": server_id, "category": str(ServerType(server_type))}
|
|
309
|
+
label = f"{server_id} - OAuth Tokens"
|
|
310
|
+
try:
|
|
311
|
+
self.keyring.save(label, attributes, json.dumps(tokens_dict))
|
|
312
|
+
except Exception as e:
|
|
313
|
+
logger.error("Failed saving tokens with exception:")
|
|
314
|
+
logger.error(e, exc_info=True)
|
|
315
|
+
|
|
316
|
+
def on_proxy_setup(self, fd, peer_ips):
|
|
317
|
+
logger.debug(f"got proxy fd: {fd}, peer_ips: {peer_ips}")
|
|
318
|
+
self._peer_ips_proxy = json.loads(peer_ips)
|
|
319
|
+
|
|
320
|
+
@run_in_background_thread("start-proxy")
|
|
321
|
+
def start_proxy(self, proxy, callback):
|
|
322
|
+
try:
|
|
323
|
+
self.common.start_proxyguard(
|
|
324
|
+
proxy.listen,
|
|
325
|
+
proxy.source_port,
|
|
326
|
+
proxy.peer,
|
|
327
|
+
ProxySetup(self.on_proxy_setup),
|
|
328
|
+
ProxyReady(lambda: callback()),
|
|
329
|
+
)
|
|
330
|
+
except Exception as e:
|
|
331
|
+
handle_exception(self.common, e)
|
|
332
|
+
|
|
333
|
+
def connect(
|
|
334
|
+
self,
|
|
335
|
+
server,
|
|
336
|
+
callback: Optional[Callable] = None,
|
|
337
|
+
prefer_tcp: bool = False,
|
|
338
|
+
) -> None:
|
|
339
|
+
# Variable to be used as a last resort or for debugging
|
|
340
|
+
# to override the prefer TCP setting
|
|
341
|
+
if os.environ.get("EDUVPN_PREFER_TCP", "0") == "1":
|
|
342
|
+
prefer_tcp = True
|
|
343
|
+
config = self.connect_get_config(server, prefer_tcp=prefer_tcp)
|
|
344
|
+
if not config:
|
|
345
|
+
logger.warning("no configuration available")
|
|
346
|
+
if callback:
|
|
347
|
+
callback(False)
|
|
348
|
+
return
|
|
349
|
+
|
|
350
|
+
self._was_tcp = prefer_tcp or config.protocol == Protocol.WIREGUARDTCP
|
|
351
|
+
self._should_failover = config.should_failover
|
|
352
|
+
|
|
353
|
+
def on_fail():
|
|
354
|
+
if self.common.in_state(State.CONNECTED):
|
|
355
|
+
self.common.set_state(State.DISCONNECTING)
|
|
356
|
+
self.common.set_state(State.DISCONNECTED)
|
|
357
|
+
if callback:
|
|
358
|
+
callback(False)
|
|
359
|
+
|
|
360
|
+
def on_success():
|
|
361
|
+
# failed to disconnected
|
|
362
|
+
if self.common.in_state(State.CONNECTING):
|
|
363
|
+
self.common.set_state(State.CONNECTED)
|
|
364
|
+
if callback:
|
|
365
|
+
callback(True)
|
|
366
|
+
|
|
367
|
+
def final_connected(dropped: bool, error: str = ""):
|
|
368
|
+
# failover reports not dropped, return to connected if we are still in connecting
|
|
369
|
+
if not dropped:
|
|
370
|
+
if self.common.in_state(State.CONNECTING):
|
|
371
|
+
on_success()
|
|
372
|
+
else:
|
|
373
|
+
on_fail()
|
|
374
|
+
return
|
|
375
|
+
|
|
376
|
+
# Connection is dropped!
|
|
377
|
+
def on_reconnected(success: bool):
|
|
378
|
+
if not success:
|
|
379
|
+
handle_exception(self.common, Exception("failed to reconnect with TCP"))
|
|
380
|
+
if success:
|
|
381
|
+
set_failovered(self.common)
|
|
382
|
+
# When an error happens we always set success now as the previous
|
|
383
|
+
# protocol might be connected to
|
|
384
|
+
# TODO: differentiate between disconnect and new connect errors
|
|
385
|
+
on_success()
|
|
386
|
+
|
|
387
|
+
# reconnect with TCP
|
|
388
|
+
self.reconnect_tcp(on_reconnected)
|
|
389
|
+
|
|
390
|
+
def on_connected(success: bool):
|
|
391
|
+
if success:
|
|
392
|
+
# failover should not continue
|
|
393
|
+
if not self.should_failover():
|
|
394
|
+
on_success()
|
|
395
|
+
else:
|
|
396
|
+
set_online_detecting(self.common)
|
|
397
|
+
# failover should start
|
|
398
|
+
self.start_failover(final_connected)
|
|
399
|
+
else:
|
|
400
|
+
on_fail()
|
|
401
|
+
|
|
402
|
+
def on_connect(success: bool):
|
|
403
|
+
if success:
|
|
404
|
+
self.nm_manager.activate_connection(on_connected)
|
|
405
|
+
else:
|
|
406
|
+
on_fail()
|
|
407
|
+
|
|
408
|
+
@run_in_glib_thread
|
|
409
|
+
def connect(config):
|
|
410
|
+
if not self.common.in_state(State.CONNECTING):
|
|
411
|
+
self.common.set_state(State.CONNECTING)
|
|
412
|
+
connection = Connection.parse(config)
|
|
413
|
+
connection.connect(
|
|
414
|
+
self.nm_manager,
|
|
415
|
+
config.default_gateway,
|
|
416
|
+
self.config.allow_wg_lan,
|
|
417
|
+
config.dns_search_domains,
|
|
418
|
+
config.proxy,
|
|
419
|
+
self._peer_ips_proxy,
|
|
420
|
+
on_connect,
|
|
421
|
+
)
|
|
422
|
+
self._peer_ips_proxy = None
|
|
423
|
+
|
|
424
|
+
if config.proxy:
|
|
425
|
+
self.start_proxy(config.proxy, lambda: connect(config))
|
|
426
|
+
else:
|
|
427
|
+
connect(config)
|
|
428
|
+
|
|
429
|
+
def reconnect(self, callback: Optional[Callable] = None, prefer_tcp: bool = False):
|
|
430
|
+
def on_disconnected(success: bool):
|
|
431
|
+
if success:
|
|
432
|
+
self.activate_connection(callback, prefer_tcp=prefer_tcp)
|
|
433
|
+
|
|
434
|
+
# Reconnect
|
|
435
|
+
self.deactivate_connection(on_disconnected)
|
|
436
|
+
|
|
437
|
+
# https://github.com/eduvpn/documentation/blob/v3/API.md#session-expiry
|
|
438
|
+
def renew_session(self, callback: Optional[Callable] = None):
|
|
439
|
+
was_connected = self.common.in_state(State.CONNECTED)
|
|
440
|
+
|
|
441
|
+
@run_in_background_thread("reconnect")
|
|
442
|
+
def reconnect(success: bool = True):
|
|
443
|
+
if not success:
|
|
444
|
+
if callback:
|
|
445
|
+
callback(False)
|
|
446
|
+
return
|
|
447
|
+
# Delete the OAuth access and refresh token
|
|
448
|
+
# Start the OAuth authorization flow
|
|
449
|
+
self.common.renew_session()
|
|
450
|
+
# Automatically reconnect to the server
|
|
451
|
+
self.activate_connection(callback)
|
|
452
|
+
|
|
453
|
+
if was_connected:
|
|
454
|
+
# Call /disconnect and reconnect with callback
|
|
455
|
+
self.deactivate_connection(reconnect)
|
|
456
|
+
else:
|
|
457
|
+
reconnect()
|
|
458
|
+
|
|
459
|
+
def disconnect(self, callback: Optional[Callable] = None) -> None:
|
|
460
|
+
self.nm_manager.deactivate_connection(callback)
|
|
461
|
+
|
|
462
|
+
def set_profile(self, profile: str, connect=False):
|
|
463
|
+
was_connected = self.common.in_state(State.CONNECTED)
|
|
464
|
+
|
|
465
|
+
def do_profile(success: bool = True):
|
|
466
|
+
if not success:
|
|
467
|
+
return
|
|
468
|
+
# Set the profile ID
|
|
469
|
+
self.common.set_profile(profile)
|
|
470
|
+
|
|
471
|
+
# Connect if we should and if we were previously connected
|
|
472
|
+
if connect and was_connected:
|
|
473
|
+
self.activate_connection()
|
|
474
|
+
|
|
475
|
+
# Deactivate connection if we are connected
|
|
476
|
+
# and the connection should be modified
|
|
477
|
+
# the do_profile will be called in the callback
|
|
478
|
+
if was_connected and connect:
|
|
479
|
+
self.deactivate_connection(do_profile)
|
|
480
|
+
else:
|
|
481
|
+
do_profile()
|
|
482
|
+
|
|
483
|
+
def activate_connection(self, callback: Optional[Callable] = None, prefer_tcp: bool = False):
|
|
484
|
+
if (
|
|
485
|
+
not self.common.in_state(State.GOT_CONFIG)
|
|
486
|
+
and not self.common.in_state(State.DISCONNECTED)
|
|
487
|
+
and not self.common.in_state(State.MAIN)
|
|
488
|
+
):
|
|
489
|
+
if callback:
|
|
490
|
+
logger.error("invalid state to activate connection")
|
|
491
|
+
callback(False)
|
|
492
|
+
return
|
|
493
|
+
if not self.current_server:
|
|
494
|
+
if callback:
|
|
495
|
+
logger.error("failed to get current server")
|
|
496
|
+
callback(False)
|
|
497
|
+
return
|
|
498
|
+
|
|
499
|
+
def on_connected(success: bool):
|
|
500
|
+
if callback:
|
|
501
|
+
callback(success)
|
|
502
|
+
|
|
503
|
+
self.connect(self.current_server, on_connected, prefer_tcp=prefer_tcp)
|
|
504
|
+
|
|
505
|
+
@run_in_background_thread("cleanup")
|
|
506
|
+
def cleanup(self, callback: Optional[Callable] = None):
|
|
507
|
+
# We retry this cleanup 2 times
|
|
508
|
+
retries = 2
|
|
509
|
+
|
|
510
|
+
# Try to cleanup with a number of retries
|
|
511
|
+
for i in range(retries):
|
|
512
|
+
logger.debug("Cleaning up tokens...")
|
|
513
|
+
try:
|
|
514
|
+
self.common.cleanup()
|
|
515
|
+
except Exception as e:
|
|
516
|
+
# We can try again
|
|
517
|
+
if i < retries - 1:
|
|
518
|
+
logger.debug(
|
|
519
|
+
f"Got an error: {str(e)} while cleaning up, try number: {i+1}. This could mean the connection was not fully disconnected yet. Trying again..."
|
|
520
|
+
)
|
|
521
|
+
else:
|
|
522
|
+
# All retries are done
|
|
523
|
+
logger.debug(f"Got an error: {str(e)} while cleaning up, after full retries: {i+1}.")
|
|
524
|
+
else:
|
|
525
|
+
break
|
|
526
|
+
if self.common.in_state(State.DISCONNECTING):
|
|
527
|
+
self.common.set_state(State.DISCONNECTED)
|
|
528
|
+
if callback:
|
|
529
|
+
callback()
|
|
530
|
+
|
|
531
|
+
def deactivate_connection(self, callback: Optional[Callable] = None, cleanup=True) -> None:
|
|
532
|
+
curr = None
|
|
533
|
+
if self.common.in_state(State.CONNECTED):
|
|
534
|
+
curr = State.CONNECTED
|
|
535
|
+
|
|
536
|
+
if self.common.in_state(State.CONNECTING):
|
|
537
|
+
curr = State.CONNECTING
|
|
538
|
+
|
|
539
|
+
if not curr:
|
|
540
|
+
return
|
|
541
|
+
self.common.set_state(State.DISCONNECTING)
|
|
542
|
+
|
|
543
|
+
def on_disconnected(success: bool):
|
|
544
|
+
if success:
|
|
545
|
+
|
|
546
|
+
def on_cleaned():
|
|
547
|
+
self.common.cancel()
|
|
548
|
+
if callback:
|
|
549
|
+
callback(True)
|
|
550
|
+
|
|
551
|
+
if cleanup:
|
|
552
|
+
self.cleanup(on_cleaned)
|
|
553
|
+
else:
|
|
554
|
+
if self.common.in_state(State.DISCONNECTING):
|
|
555
|
+
self.common.set_state(State.DISCONNECTED)
|
|
556
|
+
on_cleaned()
|
|
557
|
+
else:
|
|
558
|
+
try:
|
|
559
|
+
self.common.set_state(curr)
|
|
560
|
+
except WrappedError as e:
|
|
561
|
+
logger.debug(f"set_state error in deactivate connection: {str(e)}")
|
|
562
|
+
if callback:
|
|
563
|
+
callback(False)
|
|
564
|
+
|
|
565
|
+
self.disconnect(on_disconnected)
|
|
566
|
+
|
|
567
|
+
def search_predefined(self, query: str) -> Iterator[Any]:
|
|
568
|
+
return self.server_db.search_predefined(query)
|
|
569
|
+
|
|
570
|
+
def search_custom(self, query: str) -> Iterator[Any]:
|
|
571
|
+
return self.server_db.search_custom(query)
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
class Application:
|
|
575
|
+
def __init__(self, variant: ApplicationVariant, common: EduVPN) -> None:
|
|
576
|
+
self.variant = variant
|
|
577
|
+
self.nm_manager = nm.NMManager(variant)
|
|
578
|
+
self.common = common
|
|
579
|
+
directory = variant.config_prefix
|
|
580
|
+
self.config = Configuration.load(directory)
|
|
581
|
+
self.model = ApplicationModel(common, self.config, variant, self.nm_manager)
|
|
582
|
+
|
|
583
|
+
signal.signal(signal.SIGINT, lambda s, f: self.cleanup_sigint(s, f))
|
|
584
|
+
|
|
585
|
+
def cleanup_sigint(self, _signal, _frame):
|
|
586
|
+
self.model.cancel()
|
|
587
|
+
self.common.deregister()
|
|
588
|
+
|
|
589
|
+
def on_network_update_callback(self, state, initial=False):
|
|
590
|
+
try:
|
|
591
|
+
if state == nm.ConnectionState.CONNECTED:
|
|
592
|
+
if (
|
|
593
|
+
not self.common.in_state(State.DISCONNECTED)
|
|
594
|
+
and not self.common.in_state(State.GOT_CONFIG)
|
|
595
|
+
and not initial
|
|
596
|
+
):
|
|
597
|
+
return
|
|
598
|
+
if not initial:
|
|
599
|
+
self.common.set_state(State.CONNECTING)
|
|
600
|
+
# Already connected
|
|
601
|
+
self.common.set_state(State.CONNECTED)
|
|
602
|
+
elif state == nm.ConnectionState.CONNECTING:
|
|
603
|
+
self.common.set_state(State.CONNECTING)
|
|
604
|
+
elif state == nm.ConnectionState.DISCONNECTED:
|
|
605
|
+
if not self.common.in_state(State.CONNECTED) and not self.common.in_state(State.CONNECTING):
|
|
606
|
+
return
|
|
607
|
+
self.common.set_state(State.DISCONNECTING)
|
|
608
|
+
self.model.cancel()
|
|
609
|
+
self.model.cleanup()
|
|
610
|
+
self.model.disconnect()
|
|
611
|
+
except Exception as e:
|
|
612
|
+
logger.debug(f"error occurred: {str(e)}")
|
|
613
|
+
return
|
|
614
|
+
|
|
615
|
+
def initialize_network(self, needs_update=True) -> None:
|
|
616
|
+
"""
|
|
617
|
+
Determine the current network state.
|
|
618
|
+
"""
|
|
619
|
+
# Check if a previous network configuration exists.
|
|
620
|
+
uuid = self.nm_manager.existing_connection
|
|
621
|
+
if uuid:
|
|
622
|
+
self.on_network_update_callback(self.nm_manager.connection_state, needs_update)
|
|
623
|
+
|
|
624
|
+
@run_in_background_thread("on-network-update")
|
|
625
|
+
def update(state):
|
|
626
|
+
self.on_network_update_callback(state, False)
|
|
627
|
+
|
|
628
|
+
self.nm_manager.subscribe_to_status_changes(update)
|