summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml4
-rw-r--r--.tx/config8
-rw-r--r--CHANGELOG22
-rw-r--r--app/build.gradle6
-rw-r--r--app/src/custom/java/se/leap/bitmaskclient/providersetup/helpers/QrScannerHelper.java16
-rw-r--r--app/src/main/AndroidManifest.xml5
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java79
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java2
-rw-r--r--app/src/main/java/io/swagger/client/model/ModelsGateway.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java8
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Introducer.java54
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java8
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/views/IconTextEntry.java6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java126
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java47
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java40
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/helpers/AbstractQrScannerHelper.java16
-rw-r--r--app/src/main/res/values-ja/strings.xml4
-rw-r--r--app/src/main/res/values-pt-rBR/strings.xml7
-rw-r--r--app/src/normal/AndroidManifest.xml6
-rw-r--r--app/src/normal/java/se/leap/bitmaskclient/providersetup/helpers/QrScannerHelper.java39
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/base/models/IntroducerTest.java83
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/TestSetupHelper.java20
m---------bitmask-core-android0
-rw-r--r--fastlane/.env.custom2
-rw-r--r--fastlane/Fastfile4
-rwxr-xr-xscripts/buildSwaggerClient.sh2
-rw-r--r--scripts/fetch-play-metadata.py4
-rwxr-xr-xscripts/pullTranslations.py8
-rw-r--r--src/README.md4
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ar/full_description.txt (renamed from src/custom/fastlane/metadata/android/ar/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ar/short_description.txt (renamed from src/custom/fastlane/metadata/android/ar/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ar/store-meta-ar.json (renamed from src/custom/fastlane/metadata/android/ar/store-meta-ar.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ar/title.txt (renamed from src/custom/fastlane/metadata/android/ar/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/cs/full_description.txt (renamed from src/custom/fastlane/metadata/android/cs/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/cs/short_description.txt (renamed from src/custom/fastlane/metadata/android/cs/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/cs/store-meta-cs.json (renamed from src/custom/fastlane/metadata/android/cs/store-meta-cs.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/cs/title.txt (renamed from src/custom/fastlane/metadata/android/cs/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/de/full_description.txt (renamed from src/custom/fastlane/metadata/android/de/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/de/short_description.txt (renamed from src/custom/fastlane/metadata/android/de/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/de/store-meta-de.json (renamed from src/custom/fastlane/metadata/android/de/store-meta-de.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/de/title.txt (renamed from src/custom/fastlane/metadata/android/de/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/el/full_description.txt (renamed from src/custom/fastlane/metadata/android/el/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/el/short_description.txt (renamed from src/custom/fastlane/metadata/android/el/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/el/store-meta-el.json (renamed from src/custom/fastlane/metadata/android/el/store-meta-el.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/el/title.txt (renamed from src/custom/fastlane/metadata/android/el/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/changelogs/169000.txt (renamed from src/custom/fastlane/metadata/android/en-US/changelogs/169000.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/changelogs/170000.txt (renamed from src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/full_description.txt (renamed from src/custom/fastlane/metadata/android/en-US/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/images/icon.png (renamed from src/custom/fastlane/metadata/android/en-US/images/icon.png)bin17062 -> 17062 bytes
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png (renamed from src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png)bin162001 -> 162001 bytes
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png (renamed from src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png)bin269807 -> 269807 bytes
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png (renamed from src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png)bin248841 -> 248841 bytes
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/short_description.txt (renamed from src/custom/fastlane/metadata/android/en-US/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/store-meta-en-US.json (renamed from src/custom/fastlane/metadata/android/en-US/store-meta-en-US.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/title.txt (renamed from src/custom/fastlane/metadata/android/en-US/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/en-US/video.txt (renamed from src/custom/fastlane/metadata/android/en-US/video.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/es-CU/full_description.txt (renamed from src/custom/fastlane/metadata/android/es-CU/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/es-CU/short_description.txt (renamed from src/custom/fastlane/metadata/android/es-CU/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/es-CU/store-meta-es-CU.json (renamed from src/custom/fastlane/metadata/android/es-CU/store-meta-es-CU.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/es-CU/title.txt (renamed from src/custom/fastlane/metadata/android/es-CU/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/es/full_description.txt (renamed from src/custom/fastlane/metadata/android/es/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/es/short_description.txt (renamed from src/custom/fastlane/metadata/android/es/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/es/store-meta-es.json (renamed from src/custom/fastlane/metadata/android/es/store-meta-es.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/es/title.txt (renamed from src/custom/fastlane/metadata/android/es/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/fr/full_description.txt (renamed from src/custom/fastlane/metadata/android/fr/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/fr/short_description.txt (renamed from src/custom/fastlane/metadata/android/fr/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/fr/store-meta-fr.json (renamed from src/custom/fastlane/metadata/android/fr/store-meta-fr.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/fr/title.txt (renamed from src/custom/fastlane/metadata/android/fr/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/it/full_description.txt (renamed from src/custom/fastlane/metadata/android/it/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/it/short_description.txt (renamed from src/custom/fastlane/metadata/android/it/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/it/store-meta-it.json (renamed from src/custom/fastlane/metadata/android/it/store-meta-it.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/it/title.txt (renamed from src/custom/fastlane/metadata/android/it/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ja/full_description.txt (renamed from src/custom/fastlane/metadata/android/ja/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ja/short_description.txt (renamed from src/custom/fastlane/metadata/android/ja/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ja/store-meta-ja.json (renamed from src/custom/fastlane/metadata/android/ja/store-meta-ja.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ja/title.txt (renamed from src/custom/fastlane/metadata/android/ja/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/lt/full_description.txt (renamed from src/custom/fastlane/metadata/android/lt/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/lt/short_description.txt (renamed from src/custom/fastlane/metadata/android/lt/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/lt/store-meta-lt.json (renamed from src/custom/fastlane/metadata/android/lt/store-meta-lt.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/lt/title.txt (renamed from src/custom/fastlane/metadata/android/lt/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/nl/full_description.txt (renamed from src/custom/fastlane/metadata/android/nl/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/nl/short_description.txt (renamed from src/custom/fastlane/metadata/android/nl/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/nl/store-meta-nl.json (renamed from src/custom/fastlane/metadata/android/nl/store-meta-nl.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/nl/title.txt (renamed from src/custom/fastlane/metadata/android/nl/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/pt-BR/full_description.txt (renamed from src/custom/fastlane/metadata/android/pt-BR/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/pt-BR/short_description.txt (renamed from src/custom/fastlane/metadata/android/pt-BR/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json (renamed from src/custom/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/pt-BR/title.txt (renamed from src/custom/fastlane/metadata/android/pt-BR/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ru/full_description.txt (renamed from src/custom/fastlane/metadata/android/ru/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ru/short_description.txt (renamed from src/custom/fastlane/metadata/android/ru/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ru/store-meta-ru.json (renamed from src/custom/fastlane/metadata/android/ru/store-meta-ru.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/ru/title.txt (renamed from src/custom/fastlane/metadata/android/ru/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/tr/full_description.txt (renamed from src/custom/fastlane/metadata/android/tr/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/tr/short_description.txt (renamed from src/custom/fastlane/metadata/android/tr/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/tr/store-meta-tr.json (renamed from src/custom/fastlane/metadata/android/tr/store-meta-tr.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/tr/title.txt (renamed from src/custom/fastlane/metadata/android/tr/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/uk/full_description.txt (renamed from src/custom/fastlane/metadata/android/uk/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/uk/short_description.txt (renamed from src/custom/fastlane/metadata/android/uk/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/uk/store-meta-uk.json (renamed from src/custom/fastlane/metadata/android/uk/store-meta-uk.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/uk/title.txt (renamed from src/custom/fastlane/metadata/android/uk/title.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/zh-TW/full_description.txt (renamed from src/custom/fastlane/metadata/android/zh-TW/full_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/zh-TW/short_description.txt (renamed from src/custom/fastlane/metadata/android/zh-TW/short_description.txt)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json (renamed from src/custom/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json)0
-rw-r--r--src/customProductionFat/fastlane/metadata/android/zh-TW/title.txt (renamed from src/custom/fastlane/metadata/android/zh-TW/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ar/full_description.txt (renamed from src/normal/fastlane/metadata/android/ar/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ar/short_description.txt (renamed from src/normal/fastlane/metadata/android/ar/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ar/store-meta-ar.json (renamed from src/normal/fastlane/metadata/android/ar/store-meta-ar.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ar/title.txt (renamed from src/normal/fastlane/metadata/android/ar/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/cs/full_description.txt (renamed from src/normal/fastlane/metadata/android/cs/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/cs/short_description.txt (renamed from src/normal/fastlane/metadata/android/cs/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/cs/store-meta-cs.json (renamed from src/normal/fastlane/metadata/android/cs/store-meta-cs.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/cs/title.txt (renamed from src/normal/fastlane/metadata/android/cs/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/de-DE/full_description.txt (renamed from src/normal/fastlane/metadata/android/de-DE/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/de-DE/short_description.txt (renamed from src/normal/fastlane/metadata/android/de-DE/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/de-DE/title.txt (renamed from src/normal/fastlane/metadata/android/de-DE/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/de/full_description.txt (renamed from src/normal/fastlane/metadata/android/de/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/de/short_description.txt (renamed from src/normal/fastlane/metadata/android/de/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/de/store-meta-de.json (renamed from src/normal/fastlane/metadata/android/de/store-meta-de.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/de/title.txt (renamed from src/normal/fastlane/metadata/android/de/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/el-GR/full_description.txt (renamed from src/normal/fastlane/metadata/android/el-GR/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/el-GR/short_description.txt (renamed from src/normal/fastlane/metadata/android/el-GR/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/el-GR/title.txt (renamed from src/normal/fastlane/metadata/android/el-GR/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/el/full_description.txt (renamed from src/normal/fastlane/metadata/android/el/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/el/short_description.txt (renamed from src/normal/fastlane/metadata/android/el/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/el/store-meta-el.json (renamed from src/normal/fastlane/metadata/android/el/store-meta-el.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/el/title.txt (renamed from src/normal/fastlane/metadata/android/el/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/en-US/changelogs/168000.txt (renamed from src/normal/fastlane/metadata/android/en-US/changelogs/168000.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/en-US/changelogs/170000.txt (renamed from src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/en-US/full_description.txt (renamed from src/normal/fastlane/metadata/android/en-US/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/en-US/images/icon.png (renamed from src/normal/fastlane/metadata/android/en-US/images/icon.png)bin39579 -> 39579 bytes
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/en-US/short_description.txt (renamed from src/normal/fastlane/metadata/android/en-US/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/en-US/title.txt (renamed from src/normal/fastlane/metadata/android/en-US/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/en-US/video.txt (renamed from src/normal/fastlane/metadata/android/en-US/video.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es-419/full_description.txt (renamed from src/normal/fastlane/metadata/android/es-419/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es-419/short_description.txt (renamed from src/normal/fastlane/metadata/android/es-419/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es-419/title.txt (renamed from src/normal/fastlane/metadata/android/es-419/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es-CU/full_description.txt (renamed from src/normal/fastlane/metadata/android/es-CU/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es-CU/short_description.txt (renamed from src/normal/fastlane/metadata/android/es-CU/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es-CU/store-meta-es-CU.json (renamed from src/normal/fastlane/metadata/android/es-CU/store-meta-es-CU.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es-CU/title.txt (renamed from src/normal/fastlane/metadata/android/es-CU/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es/full_description.txt (renamed from src/normal/fastlane/metadata/android/es/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es/short_description.txt (renamed from src/normal/fastlane/metadata/android/es/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es/store-meta-es.json (renamed from src/normal/fastlane/metadata/android/es/store-meta-es.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/es/title.txt (renamed from src/normal/fastlane/metadata/android/es/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/fr/full_description.txt12
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/fr/short_description.txt2
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/fr/store-meta-fr.json (renamed from src/normal/fastlane/metadata/android/fr/store-meta-fr.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/fr/title.txt (renamed from src/normal/fastlane/metadata/android/it/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/it/full_description.txt (renamed from src/normal/fastlane/metadata/android/it/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/it/short_description.txt (renamed from src/normal/fastlane/metadata/android/it/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/it/store-meta-it.json (renamed from src/normal/fastlane/metadata/android/it/store-meta-it.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/it/title.txt (renamed from src/normal/fastlane/metadata/android/lt/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/lt/full_description.txt (renamed from src/normal/fastlane/metadata/android/lt/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/lt/short_description.txt (renamed from src/normal/fastlane/metadata/android/lt/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/lt/store-meta-lt.json (renamed from src/normal/fastlane/metadata/android/lt/store-meta-lt.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/lt/title.txt (renamed from src/normal/fastlane/metadata/android/nl-NL/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/nl-NL/full_description.txt (renamed from src/normal/fastlane/metadata/android/nl-NL/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/nl-NL/short_description.txt (renamed from src/normal/fastlane/metadata/android/nl-NL/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/nl-NL/title.txt (renamed from src/normal/fastlane/metadata/android/nl/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/nl/full_description.txt (renamed from src/normal/fastlane/metadata/android/nl/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/nl/short_description.txt (renamed from src/normal/fastlane/metadata/android/nl/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/nl/store-meta-nl.json (renamed from src/normal/fastlane/metadata/android/nl/store-meta-nl.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/nl/title.txt (renamed from src/normal/fastlane/metadata/android/pt-BR/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/pt-BR/full_description.txt (renamed from src/normal/fastlane/metadata/android/pt-BR/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/pt-BR/short_description.txt (renamed from src/normal/fastlane/metadata/android/pt-BR/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json (renamed from src/normal/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/pt-BR/title.txt (renamed from src/normal/fastlane/metadata/android/ru-RU/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ru-RU/full_description.txt (renamed from src/normal/fastlane/metadata/android/ru-RU/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ru-RU/short_description.txt (renamed from src/normal/fastlane/metadata/android/ru-RU/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ru-RU/title.txt (renamed from src/normal/fastlane/metadata/android/ru/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ru/full_description.txt (renamed from src/normal/fastlane/metadata/android/ru/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ru/short_description.txt (renamed from src/normal/fastlane/metadata/android/ru/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ru/store-meta-ru.json (renamed from src/normal/fastlane/metadata/android/ru/store-meta-ru.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/ru/title.txt (renamed from src/normal/fastlane/metadata/android/tr-TR/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/tr-TR/full_description.txt (renamed from src/normal/fastlane/metadata/android/tr-TR/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/tr-TR/short_description.txt (renamed from src/normal/fastlane/metadata/android/tr-TR/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/tr-TR/title.txt (renamed from src/normal/fastlane/metadata/android/tr/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/tr/full_description.txt (renamed from src/normal/fastlane/metadata/android/tr/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/tr/short_description.txt (renamed from src/normal/fastlane/metadata/android/tr/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/tr/store-meta-tr.json (renamed from src/normal/fastlane/metadata/android/tr/store-meta-tr.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/tr/title.txt (renamed from src/normal/fastlane/metadata/android/uk/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/uk/full_description.txt (renamed from src/normal/fastlane/metadata/android/uk/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/uk/short_description.txt (renamed from src/normal/fastlane/metadata/android/uk/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/uk/store-meta-uk.json (renamed from src/normal/fastlane/metadata/android/uk/store-meta-uk.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/uk/title.txt (renamed from src/normal/fastlane/metadata/android/zh-TW/title.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/zh-TW/full_description.txt (renamed from src/normal/fastlane/metadata/android/zh-TW/full_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/zh-TW/short_description.txt (renamed from src/normal/fastlane/metadata/android/zh-TW/short_description.txt)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json (renamed from src/normal/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json)0
-rw-r--r--src/normalProductionFat/fastlane/metadata/android/zh-TW/title.txt1
195 files changed, 509 insertions, 160 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 36988fb2..2f9508dc 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -93,8 +93,8 @@ screenshot:
- ./scripts/fastlane.sh custom
artifacts:
paths:
- - src/custom/
- - src/normal/
+ - src/customProductionFat/
+ - src/normalProductionFat/
when: always
expire_in: 3 days
allow_failure: true
diff --git a/.tx/config b/.tx/config
index 1cb3557e..a92c7184 100644
--- a/.tx/config
+++ b/.tx/config
@@ -22,16 +22,16 @@ resource_name = RiseupVPN Android
[o:otf:p:bitmask:r:bitmask-playstore-listing]
lang_map = en: en-US, es_AR: es-AR, es_CU: es-CU, fa_IR: fa-IR, kn_IN: kn-IN, pt_BR: pt-BR, pt_PT: pt-PT, zh_TW: zh-TW, nb: no
-source_file = src/normal/fastlane/metadata/android/en-US/store-meta-en-US.json
+source_file = src/normalProductionFat/fastlane/metadata/android/en-US/store-meta-en-US.json
type = KEYVALUEJSON
resource_name = Bitmask details in Appstore
-file_filter = src/normal/fastlane/metadata/android/<lang>/store-meta-<lang>.json
+file_filter = src/normalProductionFat/fastlane/metadata/android/<lang>/store-meta-<lang>.json
minimum_perc = 98
[o:otf:p:bitmask:r:riseupvpn-playstore-listing]
lang_map = en: en-US, es_AR: es-AR, es_CU: es-CU, fa_IR: fa-IR, kn_IN: kn-IN, pt_BR: pt-BR, pt_PT: pt-PT, zh_TW: zh-TW, nb: no
-source_file = src/custom/fastlane/metadata/android/en-US/store-meta-en-US.json
+source_file = src/customProductionFat/fastlane/metadata/android/en-US/store-meta-en-US.json
type = KEYVALUEJSON
resource_name = RiseupVPN details in Appstore
-file_filter = src/custom/fastlane/metadata/android/<lang>/store-meta-<lang>.json
+file_filter = src/customProductionFat/fastlane/metadata/android/<lang>/store-meta-<lang>.json
minimum_perc = 98
diff --git a/CHANGELOG b/CHANGELOG
index dbd67804..381ed06b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,25 @@
+1.5.3 Obfuscation update release
+features:
+- provide support for quic as obfuscation protocol
+- improve bridge hopping mode
+bugfixes:
+- reduce obfuscated connection failure rates after changing settings
+- fix updating VPN certificate via APIv5
+- improve invite code validation
+- fix minor UI bugs in location selection and censorship circumvention settings
+- remove camera permission for custom branded clients
+
+1.5.2RC2 Obfuscation Update beta release
+bugfixes:
+- fix parsing invite code parameters, fixes bucket authentication
+
+1.5.2RC1 Obfuscation Update beta release
+features:
+- handle Quic as obfuscation protocol
+bugfixes:
+- fix parsing of hopping mode
+- fix fastlane directory structure, should fix meta data being picked up correctly by f-droid (thanks @lhr)
+
1.5.1 stable
features:
- see 1.5.0RC2 API-v5 beta and 1.5.0RC1 API-v5 beta
diff --git a/app/build.gradle b/app/build.gradle
index b953df1f..b6553fd4 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -32,8 +32,8 @@ android {
// the factor 1000 is used so that gplay users can upgrade from split apks ((current version number - 1) * 1000) + n
// to extracted bundle apks, supplied by google
// however we don't calculate the versionCode here, because F-Droid doesn't like that
- versionCode 179000
- versionName "1.5.1"
+ versionCode 182000
+ versionName "1.5.3"
compileSdk 34
minSdkVersion 21
targetSdkVersion 34
@@ -437,7 +437,7 @@ dependencies {
implementation 'org.threeten:threetenbp:1.3.5'
// Start:: QR Code Scanner
- implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
+ normalImplementation 'com.journeyapps:zxing-android-embedded:4.3.0'
// End:: QR Code Scanner
//implementation 'info.guardianproject:tor-android:0.4.5.7'
diff --git a/app/src/custom/java/se/leap/bitmaskclient/providersetup/helpers/QrScannerHelper.java b/app/src/custom/java/se/leap/bitmaskclient/providersetup/helpers/QrScannerHelper.java
new file mode 100644
index 00000000..8483549a
--- /dev/null
+++ b/app/src/custom/java/se/leap/bitmaskclient/providersetup/helpers/QrScannerHelper.java
@@ -0,0 +1,16 @@
+package se.leap.bitmaskclient.providersetup.helpers;
+
+import androidx.fragment.app.Fragment;
+
+import se.leap.bitmaskclient.providersetup.fragments.helpers.AbstractQrScannerHelper;
+
+public class QrScannerHelper extends AbstractQrScannerHelper {
+
+ public QrScannerHelper(Fragment fragment, ScanResultCallback callback) {
+ super(fragment, callback);
+ }
+
+ @Override
+ public void startScan() {
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6759862e..254f38d6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -20,10 +20,7 @@
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" /> <!-- Used to show all apps in the allowed Apps selection -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
- <uses-feature
- android:name="android.hardware.camera"
- android:required="false" />
- <uses-permission android:name="android.permission.CAMERA"/>
+
<application
android:name=".base.BitmaskApp"
android:allowBackup="false"
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index c8ac965f..a82a87d9 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -182,6 +182,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
synchronized (mProcessLock) {
mProcessThread = null;
}
+ stopObfsvpn();
VpnStatus.removeByteCountListener(this);
unregisterDeviceStateReceiver(mDeviceStateReceiver);
mDeviceStateReceiver = null;
@@ -230,15 +231,20 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mDeviceStateReceiver.userPause(shouldBePaused);
}
+ private boolean stopObfsvpn() {
+ if (obfsVpnClient == null || !obfsVpnClient.isStarted()) {
+ return true;
+ }
+ boolean success = obfsVpnClient.stop();
+ obfsVpnClient = null;
+ return success;
+ }
@Override
public boolean stopVPN(boolean replaceConnection) {
+ stopObfsvpn();
if(isVpnRunning()) {
if (getManagement() != null && getManagement().stopVPN(replaceConnection)) {
if (!replaceConnection) {
- if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
- obfsVpnClient.stop();
- obfsVpnClient = null;
- }
VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED);
}
return true;
@@ -369,24 +375,53 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
}
private void startOpenVPN() {
- //TODO: investigate how connections[n] with n>0 get called during vpn setup (on connection refused?)
- // Do we need to check if there's any obfs4 connection in mProfile.mConnections and start
- // the dispatcher here? Can we start the dispatcher at a later point of execution, e.g. when
- // connections[n], n>0 gets choosen?
-
Connection connection = mProfile.mConnections[0];
VpnStatus.setCurrentlyConnectingProfile(mProfile);
+ // stop old running obfsvpn client
+ if (!stopObfsvpn()) {
+ VpnStatus.logError("Failed to stop already running obfsvpn client");
+ endVpnService();
+ VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED);
+ return;
+ }
+
+ // Set a flag that we are starting a new VPN
+ mStarting = true;
+ // Stop the previous session by interrupting the thread.
+ stopOldOpenVPNProcess();
+ // An old running VPN should now be exited
+ mStarting = false;
+
+ // optionally start start obfsvpn and adapt openvpn config to the port obfsvpn is listening to
+ Connection.TransportType transportType = connection.getTransportType();
+ if (mProfile.usePluggableTransports() && transportType.isPluggableTransport()) {
+ try {
+ obfsVpnClient = new ObfsvpnClient(((Obfs4Connection) connection).getObfs4Options());
+ obfsVpnClient.start();
+ int port = obfsVpnClient.getPort();
+ connection.setServerPort(String.valueOf(port));
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ VpnStatus.logException(e);
+ endVpnService();
+ VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED);
+ return;
+ }
+ }
+
+ // write openvpn config
VpnStatus.logInfo(R.string.building_configration);
VpnStatus.updateStateString("VPN_GENERATE_CONFIG", "", R.string.building_configration, ConnectionStatus.LEVEL_START);
-
try {
mProfile.writeConfigFile(this);
} catch (IOException e) {
VpnStatus.logException("Error writing config file", e);
endVpnService();
+ VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED);
return;
}
+
String nativeLibraryDirectory = getApplicationInfo().nativeLibraryDir;
String tmpDir;
try {
@@ -399,25 +434,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
// Write OpenVPN binary
String[] argv = VPNLaunchHelper.buildOpenvpnArgv(this);
-
- // Set a flag that we are starting a new VPN
- mStarting = true;
- // Stop the previous session by interrupting the thread.
-
- stopOldOpenVPNProcess();
- // An old running VPN should now be exited
- mStarting = false;
- Connection.TransportType transportType = connection.getTransportType();
- if (mProfile.usePluggableTransports() && transportType.isPluggableTransport()) {
- if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
- obfsVpnClient.stop();
- }
- obfsVpnClient = new ObfsvpnClient(((Obfs4Connection) connection).getObfs4Options());
- obfsVpnClient.start();
- Log.d(TAG, "obfsvpn client started");
- }
-
-
// Start a new session by creating a new thread.
boolean useOpenVPN3 = VpnProfile.doUseOpenVPN3(this);
@@ -471,11 +487,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if (mOpenVPNThread != null)
((OpenVPNThread) mOpenVPNThread).setReplaceConnection();
if (mManagement.stopVPN(true)) {
- if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
- Log.d(TAG, "-> stop obfsvpnClient");
- obfsVpnClient.stop();
- obfsVpnClient = null;
- }
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
index 0fe6bff2..e2c596ac 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
@@ -15,7 +15,7 @@ public class Obfs4Connection extends Connection {
public Obfs4Connection(Obfs4Options options) {
setServerName(ObfsvpnClient.IP);
- setServerPort(String.valueOf(ObfsvpnClient.PORT));
+ setServerPort(String.valueOf(ObfsvpnClient.DEFAULT_PORT));
setUseUdp(true);
setProxyType(ProxyType.NONE);
setProxyName("");
diff --git a/app/src/main/java/io/swagger/client/model/ModelsGateway.java b/app/src/main/java/io/swagger/client/model/ModelsGateway.java
index 3da72aa9..8c020eb1 100644
--- a/app/src/main/java/io/swagger/client/model/ModelsGateway.java
+++ b/app/src/main/java/io/swagger/client/model/ModelsGateway.java
@@ -273,10 +273,10 @@ public class ModelsGateway {
}
/**
- * TCP, UDP or KCP. This was called \&quot;protocol\&quot; in previous versions of the API.
+ * TCP, UDP, KCP or Quic. This was called \&quot;protocol\&quot; in previous versions of the API.
* @return transport
**/
- @ApiModelProperty(value = "TCP, UDP or KCP. This was called \"protocol\" in previous versions of the API.")
+ @ApiModelProperty(value = "TCP, UDP, KCP or Quic. This was called \"protocol\" in previous versions of the API.")
public String getTransport() {
return transport;
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java
index bb5a06c4..5cd6c2a0 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java
@@ -48,8 +48,6 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.ref.WeakReference;
import java.util.List;
-import java.util.Observable;
-import java.util.Observer;
import de.blinkt.openvpn.core.VpnStatus;
import de.blinkt.openvpn.core.connection.Connection;
@@ -144,10 +142,11 @@ public class GatewaySelectionFragment extends Fragment implements PropertyChange
}
private void initBridgesHint(@NonNull View view) {
+ boolean allowResettingBridges = getUseBridges() && gatewaysManager.hasLocationsForOpenVPN();
bridgesHint = view.findViewById(R.id.manual_subtitle);
- bridgesHint.setVisibility(getUseBridges() ? VISIBLE : GONE);
+ bridgesHint.setVisibility(allowResettingBridges ? VISIBLE : GONE);
disableBridges = view.findViewById(R.id.disable_bridges);
- disableBridges.setVisibility(getUseBridges() ? VISIBLE : GONE);
+ disableBridges.setVisibility(allowResettingBridges ? VISIBLE : GONE);
disableBridges.setOnClickListener(v -> {
useBridges(false);
});
@@ -218,6 +217,7 @@ public class GatewaySelectionFragment extends Fragment implements PropertyChange
locationListAdapter.updateTransport(selectedTransport, gatewaysManager);
bridgesHint.setVisibility(showBridges ? VISIBLE : GONE);
disableBridges.setVisibility(showBridges ? VISIBLE : GONE);
+ updateRecommendedLocation();
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
index 598f9908..d4d72812 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
@@ -153,6 +153,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh
//bridges can be enabled not only from here but also from error handling
boolean useUDP = getPreferUDP() && useUdpEntry.isEnabled();
manualConfiguration.setEnabled(!useUDP);
+ manualConfigurationSwitch.setVisibility(useUDP ? GONE : VISIBLE);
manualConfiguration.setSubtitle(getString(useUDP ? R.string.disabled_while_udp_on : R.string.manual_bridge_description));
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Introducer.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Introducer.java
index 7048c48d..e3175010 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Introducer.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Introducer.java
@@ -1,21 +1,22 @@
package se.leap.bitmaskclient.base.models;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import java.io.UnsupportedEncodingException;
-import java.net.URI;
+import java.net.IDN;
import java.net.URISyntaxException;
import java.net.URLEncoder;
+import java.util.Locale;
public class Introducer implements Parcelable {
- private String type;
- private String address;
- private String certificate;
- private String fullyQualifiedDomainName;
- private boolean kcpEnabled;
-
- private String auth;
+ private final String type;
+ private final String address;
+ private final String certificate;
+ private final String fullyQualifiedDomainName;
+ private final boolean kcpEnabled;
+ private final String auth;
public Introducer(String type, String address, String certificate, String fullyQualifiedDomainName, boolean kcpEnabled, String auth) {
this.type = type;
@@ -87,38 +88,45 @@ public class Introducer implements Parcelable {
}
public static Introducer fromUrl(String introducerUrl) throws URISyntaxException, IllegalArgumentException {
- URI uri = new URI(introducerUrl);
- String fqdn = getQueryParam(uri, "fqdn");
+ Uri uri = Uri.parse(introducerUrl);
+ String fqdn = uri.getQueryParameter("fqdn");
if (fqdn == null || fqdn.isEmpty()) {
throw new IllegalArgumentException("FQDN not found in the introducer URL");
}
- boolean kcp = "1".equals(getQueryParam(uri, "kcp"));
+ if (!isAscii(fqdn)) {
+ throw new IllegalArgumentException("FQDN is not ASCII: " + fqdn);
+ }
+
+ boolean kcp = "1".equals(uri.getQueryParameter( "kcp"));
- String cert = getQueryParam(uri, "cert");
+ String cert = uri.getQueryParameter( "cert");
if (cert == null || cert.isEmpty()) {
throw new IllegalArgumentException("Cert not found in the introducer URL");
}
- String auth = getQueryParam(uri, "auth");
+ String auth = uri.getQueryParameter( "auth");
if (auth == null || auth.isEmpty()) {
throw new IllegalArgumentException("Authentication token not found in the introducer URL");
}
return new Introducer(uri.getScheme(), uri.getAuthority(), cert, fqdn, kcp, auth);
}
- public String toUrl() throws UnsupportedEncodingException {
- return String.format("%s://%s?fqdn=%s&kcp=%d&cert=%s&auth=%s", type, address, URLEncoder.encode(fullyQualifiedDomainName, "UTF-8"), kcpEnabled ? 1 : 0, URLEncoder.encode(certificate, "UTF-8"), URLEncoder.encode(auth, "UTF-8"));
+ public String getAuthToken() {
+ return auth;
}
- private static String getQueryParam(URI uri, String param) {
- String[] queryParams = uri.getQuery().split("&");
- for (String queryParam : queryParams) {
- String[] keyValue = queryParam.split("=");
- if (keyValue.length == 2 && keyValue[0].equals(param)) {
- return keyValue[1];
- }
+ private static boolean isAscii(String fqdn) {
+ try {
+ String asciiFQDN = IDN.toASCII(fqdn, IDN.USE_STD3_ASCII_RULES);
+ return fqdn.equals(asciiFQDN);
+ } catch (IllegalArgumentException e) {
+ return false;
}
- return null;
}
+
+ public String toUrl() throws UnsupportedEncodingException {
+ return String.format(Locale.US, "%s://%s?fqdn=%s&kcp=%d&cert=%s&auth=%s", type, address, URLEncoder.encode(fullyQualifiedDomainName, "UTF-8"), kcpEnabled ? 1 : 0, URLEncoder.encode(certificate, "UTF-8"), URLEncoder.encode(auth, "UTF-8"));
+ }
+
} \ No newline at end of file
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
index e056ada9..b4ec23e6 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
@@ -983,7 +983,7 @@ public final class Provider implements Parcelable {
return introducer;
}
- public void setIntroducer(String introducerUrl) throws URISyntaxException {
+ public void setIntroducer(String introducerUrl) throws URISyntaxException, IllegalArgumentException {
this.introducer = Introducer.fromUrl(introducerUrl);
}
@@ -1000,7 +1000,7 @@ public final class Provider implements Parcelable {
certificatePin = "";
certificatePinEncoding = "";
caCert = "";
- apiVersion = 3;
+ apiVersion = BuildConfig.preferred_client_api_version;
privateKeyString = "";
vpnCertificate = "";
allowRegistered = false;
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java
index 3b695692..d0149a3f 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java
@@ -122,8 +122,14 @@ public class Transport implements Serializable {
private static int getIntOption(Map<String, Object> options, String key, int defaultValue) {
try {
Object o = options.get(key);
+ if (o == null) {
+ return defaultValue;
+ }
+ if (o instanceof String) {
+ return Integer.parseInt((String) o);
+ }
return (int) o;
- } catch (NullPointerException | ClassCastException e){
+ } catch (NullPointerException | ClassCastException | NumberFormatException e){
e.printStackTrace();
return defaultValue;
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java
index c7087b67..74328f45 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java
@@ -224,7 +224,9 @@ public class ConfigHelper {
}
public static boolean isNetworkUrl(String url) {
- return url != null && URLUtil.isNetworkUrl(url) && Patterns.WEB_URL.matcher(url).matches();
+ return url != null && URLUtil.isNetworkUrl(url)
+ && URLUtil.isHttpsUrl(url)
+ && Patterns.WEB_URL.matcher(url).matches();
}
public static boolean isDomainName(String url) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/IconTextEntry.java b/app/src/main/java/se/leap/bitmaskclient/base/views/IconTextEntry.java
index 7aefd089..57a33bf4 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/views/IconTextEntry.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/views/IconTextEntry.java
@@ -108,4 +108,10 @@ public class IconTextEntry extends LinearLayout {
iconView.setImageResource(id);
}
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ textView.setTextColor(getResources().getColor(enabled ? android.R.color.black : R.color.colorDisabled));
+ iconView.setImageAlpha(enabled ? 255 : 128);
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
index 16f12e02..b207fb14 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
@@ -314,6 +314,15 @@ public class GatewaysManager {
return null;
}
+ public boolean hasLocationsForOpenVPN() {
+ for (Gateway gateway : gateways.values()) {
+ if (gateway.supportsTransport(OPENVPN, null)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public Load getLoadForLocation(@Nullable String name, TransportType transportType) {
Location location = getLocation(name);
if (location == null) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
index 0288ab25..76e32349 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
@@ -379,7 +379,7 @@ public class VpnConfigGenerator {
}
stringBuilder.append(getRouteString(ipAddress, transport));
- String transparentProxyRemote = REMOTE + " " + ObfsvpnClient.IP + " " + ObfsvpnClient.PORT + " udp" + newLine;
+ String transparentProxyRemote = REMOTE + " " + ObfsvpnClient.IP + " " + ObfsvpnClient.DEFAULT_PORT + " udp" + newLine;
stringBuilder.append(transparentProxyRemote);
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java
index 625bbfd8..2e216015 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java
@@ -5,12 +5,16 @@ import static se.leap.bitmaskclient.base.models.Constants.QUIC;
import android.util.Log;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
import client.Client;
import client.Client_;
import client.EventLogger;
import de.blinkt.openvpn.core.VpnStatus;
import de.blinkt.openvpn.core.connection.Connection;
-import se.leap.bitmaskclient.base.models.Constants;
import se.leap.bitmaskclient.pluggableTransports.models.HoppingConfig;
import se.leap.bitmaskclient.pluggableTransports.models.KcpConfig;
import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
@@ -19,20 +23,20 @@ import se.leap.bitmaskclient.pluggableTransports.models.QuicConfig;
public class ObfsvpnClient implements EventLogger {
- public static final int PORT = 8080;
+ public static final int DEFAULT_PORT = 8080;
public static final String IP = "127.0.0.1";
+ private static final String ERROR_BIND = "bind: address already in use";
+ private static final String STATE_RUNNING = "RUNNING";
private final Object LOCK = new Object();
-
+ private final AtomicInteger currentPort = new AtomicInteger(DEFAULT_PORT);
+ private CountDownLatch startCallback = null;
private static final String TAG = ObfsvpnClient.class.getSimpleName();
public final Client_ client;
public ObfsvpnClient(Obfs4Options options) throws IllegalStateException {
-
- //FIXME: use a different strategy here
- //Basically we would want to track if the more performant transport protocol (KCP?/TCP?) usage was successful
- //if so, we stick to it, otherwise we flip the flag
+ // each obfuscation transport has only 1 protocol
String protocol = options.transport.getProtocols()[0];
boolean kcpEnabled = KCP.equals(protocol);
boolean quicEnabled = QUIC.equals(protocol);
@@ -42,57 +46,135 @@ public class ObfsvpnClient implements EventLogger {
}
KcpConfig kcpConfig = new KcpConfig(kcpEnabled);
QuicConfig quicConfig = new QuicConfig(quicEnabled);
- HoppingConfig hoppingConfig = new HoppingConfig(hoppingEnabled,IP+":"+PORT, options);
- ObfsvpnConfig obfsvpnConfig = new ObfsvpnConfig(IP+":"+PORT, hoppingConfig, kcpConfig, quicConfig, options.bridgeIP, options.transport.getPorts()[0], options.transport.getOptions().getCert() );
+ HoppingConfig hoppingConfig = new HoppingConfig(hoppingEnabled,IP+":"+ DEFAULT_PORT, options);
+ ObfsvpnConfig obfsvpnConfig = new ObfsvpnConfig(IP+":"+ DEFAULT_PORT, hoppingConfig, kcpConfig, quicConfig, options.bridgeIP, options.transport.getPorts()[0], options.transport.getOptions().getCert() );
try {
- Log.d(TAG, obfsvpnConfig.toString());
+ Log.d(TAG, "create new obfsvpn client: " + obfsvpnConfig);
client = Client.newFFIClient(obfsvpnConfig.toString());
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
- public int start() {
+ public void start() throws RuntimeException {
synchronized (LOCK) {
+ client.setEventLogger(this);
+
+ // this CountDownLatch stops blocking if:
+ // a) obfsvpn changed its state to RUNNING
+ // b) an unrecoverable error happened
+ final CountDownLatch callback = new CountDownLatch(1);
+ this.startCallback = callback;
+ AtomicReference<Exception> err = new AtomicReference<>();
new Thread(() -> {
try {
- if (client.isStarted()) {
- return;
- }
- client.setEventLogger(this);
- client.start();
- } catch (Exception e) {
+ start(0);
+ } catch (RuntimeException e) {
+ // save exception and stop blocking
e.printStackTrace();
+ err.set(e);
+ callback.countDown();
}
}).start();
- return PORT;
+
+ try {
+ boolean completedBeforeTimeout = callback.await(35, TimeUnit.SECONDS);
+ Exception startException = err.get();
+ this.startCallback = null;
+ if (!completedBeforeTimeout) {
+ client.setEventLogger(null);
+ throw new RuntimeException("failed to start obfsvpn: timeout error");
+ } else if (startException != null) {
+ client.setEventLogger(null);
+ throw new RuntimeException("failed to start obfsvpn: ", startException);
+ }
+ } catch (InterruptedException e) {
+ this.startCallback = null;
+ client.setEventLogger(null);
+ throw new RuntimeException("failed to start obfsvpn: ", e);
+ }
+ }
+ }
+
+ private void start(int portOffset) throws RuntimeException {
+ currentPort.set(DEFAULT_PORT + portOffset);
+ Log.d(TAG, "listen to 127.0.0.1:"+ (currentPort.get()));
+ final CountDownLatch errOnStartCDL = new CountDownLatch(1);
+ AtomicReference<Exception> err = new AtomicReference<>();
+ new Thread(() -> {
+ try {
+ client.setProxyAddr(IP + ":" + (DEFAULT_PORT+portOffset));
+ client.start();
+ } catch (Exception e) {
+ err.set(e);
+ errOnStartCDL.countDown();
+ }
+ }).start();
+
+ try {
+ // wait for 250 ms, in case there is an immediate error due to misconfiguration
+ // or bound ports the CountDownLatch is set to 0 and thus the return value of await is true
+ boolean receivedErr = errOnStartCDL.await(250, TimeUnit.MILLISECONDS);
+ if (receivedErr) {
+ Exception e = err.get();
+ // attempt to restart the client with a different local proxy port in case
+ // there's a port binding error
+ if (e != null &&
+ e.getMessage() != null &&
+ e.getMessage().contains(ERROR_BIND) &&
+ portOffset < 10) {
+ start(portOffset + 1);
+ return;
+ } else {
+ resetAndThrow(new RuntimeException("Failed to start obfsvpn: " + e));
+ }
+ }
+ } catch (InterruptedException e) {
+ resetAndThrow(new RuntimeException(e));
}
}
- public void stop() {
+ private void resetAndThrow(RuntimeException e) throws RuntimeException{
+ startCallback.countDown();
+ startCallback = null;
+ client.setEventLogger(null);
+ throw e;
+ }
+
+ public boolean stop() {
synchronized (LOCK) {
try {
client.stop();
} catch (Exception e) {
e.printStackTrace();
+ return false;
} finally {
client.setEventLogger(null);
}
+ return true;
}
}
+ public int getPort() {
+ return currentPort.get();
+ }
+
public boolean isStarted() {
return client.isStarted();
}
@Override
public void error(String s) {
- VpnStatus.logError("[obfs4-client] " + s);
-
+ VpnStatus.logError("[obfsvpn-client] error: " + s);
}
@Override
public void log(String state, String message) {
- VpnStatus.logDebug("[obfs4-client] " + state + ": " + message);
+ VpnStatus.logDebug("[obfsvpn-client] " + state + ": " + message);
+ CountDownLatch startCallback = this.startCallback;
+ if (startCallback != null && STATE_RUNNING.equals(state)) {
+ startCallback.countDown();
+ this.startCallback = null;
+ }
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java
index 2e2497d5..2680f612 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerV5.java
@@ -9,9 +9,11 @@ import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.base.models.Constants.COUNTRYCODE;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_EIP_SERVICE;
+import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.DOWNLOAD_SERVICE_JSON;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_EIP_SERVICE;
+import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.PROVIDER_NOK;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.PROVIDER_OK;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.QUIETLY_UPDATE_VPN_CERTIFICATE;
@@ -19,8 +21,8 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.SET_UP_PROVIDER;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_INVALID_CERTIFICATE;
import static se.leap.bitmaskclient.providersetup.ProviderSetupObservable.DOWNLOADED_V5_BRIDGES;
-import static se.leap.bitmaskclient.providersetup.ProviderSetupObservable.DOWNLOADED_V5_SERVICE_JSON;
import static se.leap.bitmaskclient.providersetup.ProviderSetupObservable.DOWNLOADED_V5_GATEWAYS;
+import static se.leap.bitmaskclient.providersetup.ProviderSetupObservable.DOWNLOADED_V5_SERVICE_JSON;
import static se.leap.bitmaskclient.providersetup.ProviderSetupObservable.DOWNLOADED_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.tor.TorStatusObservable.TorStatus.OFF;
@@ -84,7 +86,6 @@ public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IPro
break;
case QUIETLY_UPDATE_VPN_CERTIFICATE:
- case UPDATE_INVALID_VPN_CERTIFICATE:
result = updateVpnCertificate(provider);
if (result.getBoolean(BROADCAST_RESULT_KEY)) {
Log.d(TAG, "successfully downloaded VPN certificate");
@@ -93,6 +94,14 @@ public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IPro
ProviderObservable.getInstance().updateProvider(provider);
}
break;
+ case UPDATE_INVALID_VPN_CERTIFICATE:
+ result = updateVpnCertificate(provider);
+ if (result.getBoolean(BROADCAST_RESULT_KEY)) {
+ eventSender.sendToReceiverOrBroadcast(receiver, CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE, result, provider);
+ } else {
+ eventSender.sendToReceiverOrBroadcast(receiver, INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE, result, provider);
+ }
+ break;
}
}
@@ -103,6 +112,7 @@ public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IPro
BitmaskMobile bm;
try {
bm = new BitmaskMobile(provider.getMainUrl(), new PreferenceHelper.SharedPreferenceStore());
+ bm.setDebug(BuildConfig.DEBUG);
} catch (IllegalStateException e) {
return eventSender.setErrorResult(currentDownload, R.string.config_error_found, null);
}
@@ -120,12 +130,21 @@ public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IPro
return eventSender.setErrorResult(currentDownload, R.string.config_error_found, null);
}
+ try {
+ if (provider.hasIntroducer()) {
+ bm.setIntroducer(provider.getIntroducer().toUrl());
+ }
+ } catch (Exception e) {
+ return eventSender.setErrorResult(currentDownload, R.string.config_error_found, null);
+ }
+
if (PreferenceHelper.getUseBridges()) {
try {
String bridgesJson = bm.getAllBridges("", "", "", "");
provider.setBridges(bridgesJson);
} catch (Exception e) {
// TODO: send failed to fetch bridges event
+ return eventSender.setErrorResult(currentDownload, R.string.config_error_found, null);
}
} else {
try {
@@ -137,7 +156,7 @@ public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IPro
}
}
-
+ currentDownload.putBoolean(BROADCAST_RESULT_KEY, true);
return currentDownload;
}
@@ -191,7 +210,6 @@ public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IPro
}
try {
- // TODO: check if provider supports this API endpoint?
String gatewaysJson = bm.getAllGateways("", "", "");
Log.d(TAG, "gateways Json reponse: " + gatewaysJson);
provider.setGateways(gatewaysJson);
@@ -203,7 +221,6 @@ public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IPro
}
try {
- // TODO: check if provider supports this API endpoint?
String bridgesJson = bm.getAllBridges("", "", "", "");
Log.d(TAG, "bridges Json reponse: " + bridgesJson);
provider.setBridges(bridgesJson);
@@ -313,7 +330,25 @@ public class ProviderApiManagerV5 extends ProviderApiManagerBase implements IPro
}
protected Bundle updateVpnCertificate(Provider provider) {
- return null;
+ Bundle currentDownload = new Bundle();
+ BitmaskMobile bm;
+ try {
+ bm = new BitmaskMobile(provider.getMainUrl(), new PreferenceHelper.SharedPreferenceStore());
+ bm.setDebug(BuildConfig.DEBUG);
+ } catch (IllegalStateException e) {
+ return eventSender.setErrorResult(currentDownload, R.string.config_error_found, null);
+ }
+
+ try {
+ String cert = bm.getOpenVPNCert();
+ currentDownload = loadCredentials(provider, cert);
+ currentDownload = validateCertificateForProvider(currentDownload, provider);
+ ProviderSetupObservable.updateProgress(DOWNLOADED_VPN_CERTIFICATE);
+ } catch (Exception e) {
+ return eventSender.setErrorResult(currentDownload, R.string.error_json_exception_user_message, null);
+ }
+
+ return currentDownload;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java
index c4b3cd02..f3da117b 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java
@@ -12,14 +12,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
-import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
-import com.journeyapps.barcodescanner.ScanContract;
-import com.journeyapps.barcodescanner.ScanOptions;
-
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
@@ -29,17 +25,18 @@ import se.leap.bitmaskclient.base.models.Provider;
import se.leap.bitmaskclient.base.utils.ViewHelper;
import se.leap.bitmaskclient.databinding.FProviderSelectionBinding;
import se.leap.bitmaskclient.providersetup.activities.CancelCallback;
+import se.leap.bitmaskclient.providersetup.fragments.helpers.AbstractQrScannerHelper;
+import se.leap.bitmaskclient.providersetup.helpers.QrScannerHelper;
import se.leap.bitmaskclient.providersetup.fragments.viewmodel.ProviderSelectionViewModel;
import se.leap.bitmaskclient.providersetup.fragments.viewmodel.ProviderSelectionViewModelFactory;
-public class ProviderSelectionFragment extends BaseSetupFragment implements CancelCallback {
-
- private ActivityResultLauncher<ScanOptions> scannerActivityResultLauncher;
+public class ProviderSelectionFragment extends BaseSetupFragment implements CancelCallback, AbstractQrScannerHelper.ScanResultCallback {
private ProviderSelectionViewModel viewModel;
private ArrayList<RadioButton> radioButtons;
private FProviderSelectionBinding binding;
+ private QrScannerHelper qrScannerHelper;
public static ProviderSelectionFragment newInstance(int position) {
ProviderSelectionFragment fragment = new ProviderSelectionFragment();
@@ -56,17 +53,7 @@ public class ProviderSelectionFragment extends BaseSetupFragment implements Canc
getContext().getApplicationContext().getAssets())).
get(ProviderSelectionViewModel.class);
- scannerActivityResultLauncher = registerForActivityResult(new ScanContract(), result -> {
- if(result.getContents() != null) {
- try {
- Introducer introducer = Introducer.fromUrl(result.getContents());
- binding.editCustomProvider.setText(introducer.toUrl());
- } catch (Exception e) {
- e.printStackTrace();
- //binding.editCustomProvider.setText(result.getContents());
- }
- }
- });
+ qrScannerHelper = new QrScannerHelper(this, this);
}
@Override
@@ -112,13 +99,7 @@ public class ProviderSelectionFragment extends BaseSetupFragment implements Canc
}
private void initQrScanner() {
- binding.btnQrScanner.setOnClickListener(v -> {
- ScanOptions options = new ScanOptions();
- options.setBeepEnabled(false);
- options.setBarcodeImageEnabled(false);
- options.setOrientationLocked(false);
- scannerActivityResultLauncher.launch(options);
- });
+ binding.btnQrScanner.setOnClickListener(v -> qrScannerHelper.startScan());
}
@@ -241,4 +222,13 @@ public class ProviderSelectionFragment extends BaseSetupFragment implements Canc
public void onCanceled() {
binding.providerRadioGroup.check(0);
}
+
+ @Override
+ public void onScanResult(Introducer introducer) {
+ try {
+ binding.editCustomProvider.setText(introducer.toUrl());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
} \ No newline at end of file
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/helpers/AbstractQrScannerHelper.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/helpers/AbstractQrScannerHelper.java
new file mode 100644
index 00000000..132d8cc9
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/helpers/AbstractQrScannerHelper.java
@@ -0,0 +1,16 @@
+package se.leap.bitmaskclient.providersetup.fragments.helpers;
+
+import androidx.fragment.app.Fragment;
+
+import se.leap.bitmaskclient.base.models.Introducer;
+
+public abstract class AbstractQrScannerHelper {
+ public interface ScanResultCallback {
+ void onScanResult(Introducer introducer);
+ }
+
+ public AbstractQrScannerHelper(Fragment fragment, ScanResultCallback callback) {
+ }
+
+ public abstract void startScan();
+}
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index c55b150f..d845bae1 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -104,7 +104,7 @@
<string name="warning_corrupted_provider_cert">保存されたプロバイダーの証明書が無効です。 商用CA証明書を使用して%sを更新する(推奨)か、プロバイダーの証明書を更新することができます。</string>
<string name="warning_expired_provider_cert">保存されたプロバイダーの証明書が有効期限切れです。 商用CA証明書を使用して%sを更新する(推奨)か、プロバイダー証明書を更新することができます。</string>
<string name="downloading_vpn_certificate_failed">VPN証明書のダウンロードに失敗しました。 もう一度やり直すか、別のプロバイダーを選択してください。</string>
- <string name="vpn_certificate_is_invalid">VPN証明書が不正です。 新しくダウンロードし直してください。</string>
+ <string name="vpn_certificate_is_invalid">VPN証明書を更新する時間です。接続を安全にするために、新しい証明書をダウンロードしてください。これは、通常の繰り返し行われる処理です。</string>
<string name="vpn_certificate_user_message">VPN証明書が不正です。 ログインして新しくダウンロードし直してください。</string>
<string name="save_battery">電池節約</string>
<string name="subtitle_save_battery">VPNホットスポットがオンの間無効にします</string>
@@ -210,7 +210,7 @@
<string name="select_provider_description">VPNを使用するとインターネットサービスプロバイダーからVPNプロバイダーへ、信頼されなければならない組織が移ります。Bitmaskは、プライバシーの保護と擁護の明瞭な歴史があるプロバイダーに限って接続します。</string>
<string name="provider_description_riseup">プロバイダーRiseupは、解放的社会変革に粘り強く取り組む事業団体です。我々は新方式の民主主義を創り、通信の安全を意図して自己制御による自己決定を実践します。</string>
<string name="next">次へ</string>
- <string name="add_provider_description">Bitmaskは公開一覧に記載されていない信用されたプロバイダーに接続します。以下に、プロバイダーのurlを入力してください。</string>
+ <string name="add_provider_description">Bitmaskは、公開一覧に記載されていないプロバイダーに接続できます。追加するプロバイダーは、あなたが知っていて、信頼しているものであることを確かめてください。</string>
<string name="add_provider_prompt">ここに、プロバイダーのURLを入力してください。</string>
<string name="invite_code_provider_description">Bitmaskは非公開の招待文字列を使用してプロバイダーに接続できます。</string>
<string name="invite_code_provider_prompt">ここに、信用する招待文字列を入力してください。</string>
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 23c00d4f..81f77a0a 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -212,7 +212,7 @@
<string name="select_provider_description">Ao usar uma VPN, você está transferindo sua confiança do seu provedor de serviços de Internet para o seu provedor de VPN. O Bitmask se conecta apenas a provedores com um histórico claro de proteção e defesa da privacidade.</string>
<string name="provider_description_riseup">Riseup fornece ferramentas de comunicação online para pessoas e grupos que trabalham em mudanças sociais libertadoras. Somos um projeto para criar alternativas democráticas e praticar a autodeterminação, controlando os nossos próprios meios de comunicação seguros.</string>
<string name="next">Próximo</string>
- <string name="add_provider_description">Bitmask se conecta a provedores confiáveis ​​que não estão listados publicamente. Insira o URL do seu provedor abaixo.</string>
+ <string name="add_provider_description">O Bitmask permite que você se conecte a provedores que não estão listados publicamente. Certifique-se de conhecer e confiar no provedor que você está adicionando.</string>
<string name="add_provider_prompt">Digite o URL do provedor aqui.</string>
<string name="invite_code_provider_description">O Bitmask permite que você se conecte a provedores usando um código de convite privado. </string>
<string name="invite_code_provider_prompt">Digite seu código de convite confiável aqui.</string>
@@ -235,6 +235,11 @@
<string name="snowflake_broker_success">Encontro do proxy Snowflake bem-sucedido</string>
<string name="snowflake_sending_data">Enviando dados via Snowflake</string>
<string name="title_upcoming_connection_request">Próxima solicitação de conexão</string>
+ <string name="title_upcoming_request">Próximas solicitações</string>
+ <string name="title_upcoming_request_summary">Nos próximos painéis, o Android pedirá sua permissão na forma de uma Solicitação de Conexão e Solicitação de Notificação.</string>
+ <string name="title_upcoming_connection_request_summary_custom">Aceitar a Solicitação de Conexão é essencial para usar a funcionalidade principal de %s.</string>
+ <string name="title_upcoming_connection_request_summary">Para a solicitação de conexão, é importante saber que a Bitmask só faz parceria com provedores parceiros confiáveis que aderem às práticas recomendadas para VPNs e têm um histórico verificável de proteção dos dados e identidades do usuário. No entanto, se você estiver se conectando manualmente a um provedor não público, certifique-se de confiar neles.</string>
+ <string name="title_upcoming_notification_request_summary">Aceitar a solicitação de notificação permite que o aplicativo seja executado em segundo plano e permite que você veja o uso de dados no centro de notificações do Android.</string>
<string name="title_upcoming_notifications_request">Próxima solicitação de notificações</string>
<string name="title_setup_success">Está tudo pronto!</string>
<string name="setup_success_description">Clique no botão abaixo para conectar</string>
diff --git a/app/src/normal/AndroidManifest.xml b/app/src/normal/AndroidManifest.xml
new file mode 100644
index 00000000..3987d95d
--- /dev/null
+++ b/app/src/normal/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-feature
+ android:name="android.hardware.camera"
+ android:required="false" />
+ <uses-permission android:name="android.permission.CAMERA"/>
+</manifest> \ No newline at end of file
diff --git a/app/src/normal/java/se/leap/bitmaskclient/providersetup/helpers/QrScannerHelper.java b/app/src/normal/java/se/leap/bitmaskclient/providersetup/helpers/QrScannerHelper.java
new file mode 100644
index 00000000..88046360
--- /dev/null
+++ b/app/src/normal/java/se/leap/bitmaskclient/providersetup/helpers/QrScannerHelper.java
@@ -0,0 +1,39 @@
+package se.leap.bitmaskclient.providersetup.helpers;
+
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.fragment.app.Fragment;
+
+import com.journeyapps.barcodescanner.ScanContract;
+import com.journeyapps.barcodescanner.ScanOptions;
+
+import se.leap.bitmaskclient.base.models.Introducer;
+import se.leap.bitmaskclient.providersetup.fragments.helpers.AbstractQrScannerHelper;
+
+public class QrScannerHelper extends AbstractQrScannerHelper {
+
+ private final ActivityResultLauncher<ScanOptions> scannerActivityResultLauncher;
+
+ public QrScannerHelper(Fragment fragment, ScanResultCallback callback) {
+ super(fragment, callback);
+ this.scannerActivityResultLauncher = fragment.registerForActivityResult(new ScanContract(), result -> {
+ if(result.getContents() != null) {
+ try {
+ Introducer introducer = Introducer.fromUrl(result.getContents());
+ callback.onScanResult(introducer);
+ } catch (Exception e) {
+ e.printStackTrace();
+ //binding.editCustomProvider.setText(result.getContents());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void startScan() {
+ ScanOptions options = new ScanOptions();
+ options.setBeepEnabled(false);
+ options.setBarcodeImageEnabled(false);
+ options.setOrientationLocked(false);
+ scannerActivityResultLauncher.launch(options);
+ }
+}
diff --git a/app/src/test/java/se/leap/bitmaskclient/base/models/IntroducerTest.java b/app/src/test/java/se/leap/bitmaskclient/base/models/IntroducerTest.java
new file mode 100644
index 00000000..b53f06fe
--- /dev/null
+++ b/app/src/test/java/se/leap/bitmaskclient/base/models/IntroducerTest.java
@@ -0,0 +1,83 @@
+package se.leap.bitmaskclient.base.models;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import android.net.Uri;
+import android.os.Build;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+
+
+@RunWith(RobolectricTestRunner.class)
+@Config(sdk = {Build.VERSION_CODES.P})
+public class IntroducerTest {
+
+ @Test
+ public void testGetQueryParam() {
+ try {
+ String auth = "solitech_w4gOlm+abcdefaF2DE1Q6dg==";
+ String encodedAuth = URLEncoder.encode(auth, "UTF-8");
+ Uri uri = Uri.parse("obfsvpn://example.org:443?auth=" + encodedAuth);
+ assertEquals(auth, uri.getQueryParameter("auth"));
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ @Test
+ public void testFromUrl() {
+ try {
+ Introducer intro = Introducer.fromUrl("obfsvpnintro://37.2.240.90:443?fqdn=ft1.example.org&kcp=1&cert=XXXXXXX&auth=solitech_w4gOlm%2BsbF8spFL8E1Q6dg%3D%3D");
+ assertEquals(intro.getFullyQualifiedDomainName(), "ft1.example.org");
+ assertEquals("solitech_w4gOlm+sbF8spFL8E1Q6dg==", intro.getAuthToken());
+ assertEquals("obfsvpnintro://37.2.240.90:443?fqdn=ft1.example.org&kcp=1&cert=XXXXXXX&auth=solitech_w4gOlm%2BsbF8spFL8E1Q6dg%3D%3D", intro.toUrl());
+ } catch (URISyntaxException | UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void testFromUrl_homograph_attack() {
+ String code = "obfsvpnintro://37.2.240.90:443?fqdn=ft1.bitmasк.net&kcp=0&cert=XXXXXXX&auth=solitech_w4gOlm%2BseC5spDL8E1Q6dg";
+ assertThrows(IllegalArgumentException.class, () -> Introducer.fromUrl(code));
+ }
+
+ @Test
+ public void testFromUrl_invalid_fqdn() {
+ String code = "obfsvpnintro://37.2.240.90:443?fqdn=file://var/wwww&kcp=0&cert=XXXXXXX&auth=solitech_w4gOlm%2BseC5spDL8E1Q6dg";
+ assertThrows(IllegalArgumentException.class, () -> Introducer.fromUrl(code));
+ }
+
+ @Test
+ public void testFromUrl_missing_fqdn() {
+ String code = "obfsvpnintro://37.2.240.90:443?fqdn=&kcp=0&cert=XXXXXXX&auth=solitech_w4gOlm%2BseC5spDL8E1Q6dg";
+ assertThrows(IllegalArgumentException.class, () -> Introducer.fromUrl(code));
+
+ String code2 = "obfsvpnintro://37.2.240.90:443?kcp=0&cert=XXXXXXX&auth=solitech_w4gOlm%2BseC5spDL8E1Q6dg";
+ assertThrows(IllegalArgumentException.class, () -> Introducer.fromUrl(code2));
+ }
+
+ @Test
+ public void testFromUrl_missing_cert() {
+ String code = "obfsvpnintro://37.2.240.90:443?fqdn=ft1.bitmask.net&kcp=0&cert=&auth=solitech_w4gOlm%2BseC5spDL8E1Q6dg";
+ assertThrows(IllegalArgumentException.class, () -> Introducer.fromUrl(code));
+ }
+
+ @Test
+ public void testFromUrl_missing_auth() {
+ String code = "obfsvpnintro://37.2.240.90:443?fqdn=ft1.bitmask.net&kcp=0&cert=XXXXXXX&auth=";
+ assertThrows(IllegalArgumentException.class, () -> Introducer.fromUrl(code));
+
+ String code2 = "obfsvpnintro://37.2.240.90:443?fqdn=ft1.bitmask.net&kcp=0&cert=XXXXXXX";
+ assertThrows(IllegalArgumentException.class, () -> Introducer.fromUrl(code2));
+ }
+}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/TestSetupHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/TestSetupHelper.java
index 97420203..752a5336 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/TestSetupHelper.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/TestSetupHelper.java
@@ -119,16 +119,6 @@ public class TestSetupHelper {
}
@Override
- public String getBestBridge() throws Exception {
- return null;
- }
-
- @Override
- public String getBestGateway() throws Exception {
- return null;
- }
-
- @Override
public String getGeolocation() throws Exception {
return null;
}
@@ -159,6 +149,11 @@ public class TestSetupHelper {
}
@Override
+ public void setCountryCodeLookupURL(String s) throws Exception {
+
+ }
+
+ @Override
public void setDebug(boolean b) {
}
@@ -179,6 +174,11 @@ public class TestSetupHelper {
}
@Override
+ public void setStunServers(String s) throws Exception {
+
+ }
+
+ @Override
public void setUseTls(boolean b) {
}
diff --git a/bitmask-core-android b/bitmask-core-android
-Subproject 491e7fcbb9490b0ff285d272899f2a177f14a68
+Subproject 64fab2f1727d147d473d33761eeb7be94a354ea
diff --git a/fastlane/.env.custom b/fastlane/.env.custom
index 5ec9ffd0..5b984b44 100644
--- a/fastlane/.env.custom
+++ b/fastlane/.env.custom
@@ -1,4 +1,4 @@
SCREENGRAB_APP_PACKAGE_NAME="se.leap.riseupvpn"
SCREENGRAB_APP_APK_PATH="app/build/outputs/apk/customProductionFat/debug/RiseupVPN_debug.apk"
SCREENGRAB_TESTS_APK_PATH="app/build/outputs/apk/androidTest/customProductionFat/debug/app-custom-production-fat-debug-androidTest.apk"
-SCREENGRAB_OUTPUT_DIRECTORY="src/custom/fastlane/metadata/android" \ No newline at end of file
+SCREENGRAB_OUTPUT_DIRECTORY="src/customProductionFat/fastlane/metadata/android"
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 99d540ed..6e6ff88d 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -59,7 +59,7 @@ platform :android do
# Prepare builds for Automatic UI Tests
build_bitmask_for_screengrab
capture_android_screenshots
- Dir.chdir("../src/normal/fastlane/metadata") do
+ Dir.chdir("../src/normalProductionFat/fastlane/metadata") do
frameit(
white: true,
path: "."
@@ -72,7 +72,7 @@ platform :android do
# Prepare builds for Automatic UI Tests
build_custom_for_screengrab
capture_android_screenshots
- Dir.chdir("../src/custom/fastlane/metadata") do
+ Dir.chdir("../src/customProductionFat/fastlane/metadata") do
frameit(
white: true,
path: "."
diff --git a/scripts/buildSwaggerClient.sh b/scripts/buildSwaggerClient.sh
index b7a68378..3afe6fb9 100755
--- a/scripts/buildSwaggerClient.sh
+++ b/scripts/buildSwaggerClient.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-SWAGGER_MENSHEN_COMMIT=8c93c8208256097b2f1d18f2395755320b9743ee
+SWAGGER_MENSHEN_COMMIT=da64a69b26b4ca4eaa3ed865df7c01216a07cc54
SCRIPT_DIR=$(dirname "$0")
BASE_DIR="$SCRIPT_DIR/.."
diff --git a/scripts/fetch-play-metadata.py b/scripts/fetch-play-metadata.py
index 309c3795..e94f4c73 100644
--- a/scripts/fetch-play-metadata.py
+++ b/scripts/fetch-play-metadata.py
@@ -30,9 +30,9 @@ service = build('androidpublisher', 'v3', credentials=credentials, cache_discove
# Base path for Fastlane metadata
def get_metadata_path(package_name):
if package_name == "se.leap.bitmaskclient":
- return 'src/normal/fastlane/metadata/android'
+ return 'src/normalProductionFat/fastlane/metadata/android'
elif package_name == "se.leap.riseupvpn":
- return 'src/custom/fastlane/metadata/android'
+ return 'src/customProductionFat/fastlane/metadata/android'
else:
raise ValueError(f"Unknown package name: {package_name}")
diff --git a/scripts/pullTranslations.py b/scripts/pullTranslations.py
index edfd5718..e688862a 100755
--- a/scripts/pullTranslations.py
+++ b/scripts/pullTranslations.py
@@ -46,9 +46,9 @@ def list_locales(app_type):
# If there's no file, tx will skip the translations
def create_metadata_files(locales, app_type):
if app_type == "main":
- metadata_dir = get_script_path() + "/../src/normal/fastlane/metadata/android"
+ metadata_dir = get_script_path() + "/../src/normalProductionFat/fastlane/metadata/android"
elif app_type == "custom":
- metadata_dir = get_script_path() + "/../src/custom/fastlane/metadata/android"
+ metadata_dir = get_script_path() + "/../src/customProductionFat/fastlane/metadata/android"
else:
raise ValueError("Invalid app type. Use 'main' or 'custom'.")
for locale_code in locales:
@@ -138,9 +138,9 @@ if __name__ == "__main__":
args = parser.parse_args()
if args.app_type == "main":
- metadata_dir = get_script_path() + "/../src/normal/fastlane/metadata/android"
+ metadata_dir = get_script_path() + "/../src/normalProductionFat/fastlane/metadata/android"
elif args.app_type == "custom":
- metadata_dir = get_script_path() + "/../src/custom/fastlane/metadata/android"
+ metadata_dir = get_script_path() + "/../src/customProductionFat/fastlane/metadata/android"
else:
raise ValueError("Invalid app type. Use 'main' or 'custom'.")
diff --git a/src/README.md b/src/README.md
index 5d217ad5..8875966b 100644
--- a/src/README.md
+++ b/src/README.md
@@ -8,7 +8,7 @@ Any string that will be changed in the source language (en_US) in the master br
# Metadata: F-Droid compatible fastlane metadata directory
-The src/<flavor>/fastlande/metadata folder contains the generated metadata for f-droid builds for both Bitmask and a custom flavored client.
+The src/<flavor>/fastlane/metadata folder contains the generated metadata for f-droid builds for both Bitmask and a custom flavored client.
Currently neither F-Droid nor Fastlane support metadata dirs directly within build flavor dirs of a module, like
`/<module>/src/<buildFlavor>/fastlane/metadata/android/` (which would be preferable).
Transifex wants 1 file, play store wants 1 file, fastlane uses text files.
@@ -46,7 +46,7 @@ This will fetch the existing metadata. If you updated something through your bro
You can also use this when adding a new provider.
You need an API token from the Google Play store. If you don't have one yet, we have some links below that should help you get started.
-fastlane supply init -j <YOUR-API-DETAILS.json> -p se.leap.<PROJECTNAME> -m src/custom/fastlane/metadata/
+fastlane supply init -j <YOUR-API-DETAILS.json> -p se.leap.<PROJECTNAME> -m src/customProductionFat/fastlane/metadata/
apt install pythong3-babel
diff --git a/src/custom/fastlane/metadata/android/ar/full_description.txt b/src/customProductionFat/fastlane/metadata/android/ar/full_description.txt
index e733121a..e733121a 100644
--- a/src/custom/fastlane/metadata/android/ar/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/ar/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/ar/short_description.txt b/src/customProductionFat/fastlane/metadata/android/ar/short_description.txt
index 7b330b69..7b330b69 100644
--- a/src/custom/fastlane/metadata/android/ar/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/ar/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/ar/store-meta-ar.json b/src/customProductionFat/fastlane/metadata/android/ar/store-meta-ar.json
index cca81ef7..cca81ef7 100644
--- a/src/custom/fastlane/metadata/android/ar/store-meta-ar.json
+++ b/src/customProductionFat/fastlane/metadata/android/ar/store-meta-ar.json
diff --git a/src/custom/fastlane/metadata/android/ar/title.txt b/src/customProductionFat/fastlane/metadata/android/ar/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/ar/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/ar/title.txt
diff --git a/src/custom/fastlane/metadata/android/cs/full_description.txt b/src/customProductionFat/fastlane/metadata/android/cs/full_description.txt
index a4c45f88..a4c45f88 100644
--- a/src/custom/fastlane/metadata/android/cs/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/cs/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/cs/short_description.txt b/src/customProductionFat/fastlane/metadata/android/cs/short_description.txt
index 84ac2d1f..84ac2d1f 100644
--- a/src/custom/fastlane/metadata/android/cs/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/cs/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/cs/store-meta-cs.json b/src/customProductionFat/fastlane/metadata/android/cs/store-meta-cs.json
index 2a70c1ab..2a70c1ab 100644
--- a/src/custom/fastlane/metadata/android/cs/store-meta-cs.json
+++ b/src/customProductionFat/fastlane/metadata/android/cs/store-meta-cs.json
diff --git a/src/custom/fastlane/metadata/android/cs/title.txt b/src/customProductionFat/fastlane/metadata/android/cs/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/cs/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/cs/title.txt
diff --git a/src/custom/fastlane/metadata/android/de/full_description.txt b/src/customProductionFat/fastlane/metadata/android/de/full_description.txt
index b53d9c25..b53d9c25 100644
--- a/src/custom/fastlane/metadata/android/de/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/de/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/de/short_description.txt b/src/customProductionFat/fastlane/metadata/android/de/short_description.txt
index 8ab5f289..8ab5f289 100644
--- a/src/custom/fastlane/metadata/android/de/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/de/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/de/store-meta-de.json b/src/customProductionFat/fastlane/metadata/android/de/store-meta-de.json
index c1ad30cd..c1ad30cd 100644
--- a/src/custom/fastlane/metadata/android/de/store-meta-de.json
+++ b/src/customProductionFat/fastlane/metadata/android/de/store-meta-de.json
diff --git a/src/custom/fastlane/metadata/android/de/title.txt b/src/customProductionFat/fastlane/metadata/android/de/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/de/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/de/title.txt
diff --git a/src/custom/fastlane/metadata/android/el/full_description.txt b/src/customProductionFat/fastlane/metadata/android/el/full_description.txt
index 7d96bc0e..7d96bc0e 100644
--- a/src/custom/fastlane/metadata/android/el/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/el/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/el/short_description.txt b/src/customProductionFat/fastlane/metadata/android/el/short_description.txt
index 157e767e..157e767e 100644
--- a/src/custom/fastlane/metadata/android/el/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/el/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/el/store-meta-el.json b/src/customProductionFat/fastlane/metadata/android/el/store-meta-el.json
index 35f23c9d..35f23c9d 100644
--- a/src/custom/fastlane/metadata/android/el/store-meta-el.json
+++ b/src/customProductionFat/fastlane/metadata/android/el/store-meta-el.json
diff --git a/src/custom/fastlane/metadata/android/el/title.txt b/src/customProductionFat/fastlane/metadata/android/el/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/el/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/el/title.txt
diff --git a/src/custom/fastlane/metadata/android/en-US/changelogs/169000.txt b/src/customProductionFat/fastlane/metadata/android/en-US/changelogs/169000.txt
index 9cdf3a40..9cdf3a40 100644
--- a/src/custom/fastlane/metadata/android/en-US/changelogs/169000.txt
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/changelogs/169000.txt
diff --git a/src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt b/src/customProductionFat/fastlane/metadata/android/en-US/changelogs/170000.txt
index d2dbd888..d2dbd888 100644
--- a/src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/changelogs/170000.txt
diff --git a/src/custom/fastlane/metadata/android/en-US/full_description.txt b/src/customProductionFat/fastlane/metadata/android/en-US/full_description.txt
index b8fc10b2..b8fc10b2 100644
--- a/src/custom/fastlane/metadata/android/en-US/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/en-US/images/icon.png b/src/customProductionFat/fastlane/metadata/android/en-US/images/icon.png
index 313e4a1b..313e4a1b 100644
--- a/src/custom/fastlane/metadata/android/en-US/images/icon.png
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/images/icon.png
Binary files differ
diff --git a/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png b/src/customProductionFat/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png
index 04ad4c9a..04ad4c9a 100644
--- a/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png
Binary files differ
diff --git a/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png b/src/customProductionFat/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png
index e7bd728c..e7bd728c 100644
--- a/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png
Binary files differ
diff --git a/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png b/src/customProductionFat/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png
index c8893dee..c8893dee 100644
--- a/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png
Binary files differ
diff --git a/src/custom/fastlane/metadata/android/en-US/short_description.txt b/src/customProductionFat/fastlane/metadata/android/en-US/short_description.txt
index 1df82a44..1df82a44 100644
--- a/src/custom/fastlane/metadata/android/en-US/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/en-US/store-meta-en-US.json b/src/customProductionFat/fastlane/metadata/android/en-US/store-meta-en-US.json
index 5d0a53ff..5d0a53ff 100644
--- a/src/custom/fastlane/metadata/android/en-US/store-meta-en-US.json
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/store-meta-en-US.json
diff --git a/src/custom/fastlane/metadata/android/en-US/title.txt b/src/customProductionFat/fastlane/metadata/android/en-US/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/en-US/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/title.txt
diff --git a/src/custom/fastlane/metadata/android/en-US/video.txt b/src/customProductionFat/fastlane/metadata/android/en-US/video.txt
index e69de29b..e69de29b 100644
--- a/src/custom/fastlane/metadata/android/en-US/video.txt
+++ b/src/customProductionFat/fastlane/metadata/android/en-US/video.txt
diff --git a/src/custom/fastlane/metadata/android/es-CU/full_description.txt b/src/customProductionFat/fastlane/metadata/android/es-CU/full_description.txt
index da3469dc..da3469dc 100644
--- a/src/custom/fastlane/metadata/android/es-CU/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/es-CU/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/es-CU/short_description.txt b/src/customProductionFat/fastlane/metadata/android/es-CU/short_description.txt
index 5d8da67f..5d8da67f 100644
--- a/src/custom/fastlane/metadata/android/es-CU/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/es-CU/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/es-CU/store-meta-es-CU.json b/src/customProductionFat/fastlane/metadata/android/es-CU/store-meta-es-CU.json
index 3109037e..3109037e 100644
--- a/src/custom/fastlane/metadata/android/es-CU/store-meta-es-CU.json
+++ b/src/customProductionFat/fastlane/metadata/android/es-CU/store-meta-es-CU.json
diff --git a/src/custom/fastlane/metadata/android/es-CU/title.txt b/src/customProductionFat/fastlane/metadata/android/es-CU/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/es-CU/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/es-CU/title.txt
diff --git a/src/custom/fastlane/metadata/android/es/full_description.txt b/src/customProductionFat/fastlane/metadata/android/es/full_description.txt
index 6900e146..6900e146 100644
--- a/src/custom/fastlane/metadata/android/es/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/es/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/es/short_description.txt b/src/customProductionFat/fastlane/metadata/android/es/short_description.txt
index 5e0797ce..5e0797ce 100644
--- a/src/custom/fastlane/metadata/android/es/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/es/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/es/store-meta-es.json b/src/customProductionFat/fastlane/metadata/android/es/store-meta-es.json
index a6de21e8..a6de21e8 100644
--- a/src/custom/fastlane/metadata/android/es/store-meta-es.json
+++ b/src/customProductionFat/fastlane/metadata/android/es/store-meta-es.json
diff --git a/src/custom/fastlane/metadata/android/es/title.txt b/src/customProductionFat/fastlane/metadata/android/es/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/es/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/es/title.txt
diff --git a/src/custom/fastlane/metadata/android/fr/full_description.txt b/src/customProductionFat/fastlane/metadata/android/fr/full_description.txt
index 5f7c855e..5f7c855e 100644
--- a/src/custom/fastlane/metadata/android/fr/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/fr/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/fr/short_description.txt b/src/customProductionFat/fastlane/metadata/android/fr/short_description.txt
index 7e92f7da..7e92f7da 100644
--- a/src/custom/fastlane/metadata/android/fr/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/fr/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/fr/store-meta-fr.json b/src/customProductionFat/fastlane/metadata/android/fr/store-meta-fr.json
index af63f77c..af63f77c 100644
--- a/src/custom/fastlane/metadata/android/fr/store-meta-fr.json
+++ b/src/customProductionFat/fastlane/metadata/android/fr/store-meta-fr.json
diff --git a/src/custom/fastlane/metadata/android/fr/title.txt b/src/customProductionFat/fastlane/metadata/android/fr/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/fr/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/fr/title.txt
diff --git a/src/custom/fastlane/metadata/android/it/full_description.txt b/src/customProductionFat/fastlane/metadata/android/it/full_description.txt
index 77c011b1..77c011b1 100644
--- a/src/custom/fastlane/metadata/android/it/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/it/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/it/short_description.txt b/src/customProductionFat/fastlane/metadata/android/it/short_description.txt
index cc1778a0..cc1778a0 100644
--- a/src/custom/fastlane/metadata/android/it/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/it/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/it/store-meta-it.json b/src/customProductionFat/fastlane/metadata/android/it/store-meta-it.json
index e8e3e3aa..e8e3e3aa 100644
--- a/src/custom/fastlane/metadata/android/it/store-meta-it.json
+++ b/src/customProductionFat/fastlane/metadata/android/it/store-meta-it.json
diff --git a/src/custom/fastlane/metadata/android/it/title.txt b/src/customProductionFat/fastlane/metadata/android/it/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/it/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/it/title.txt
diff --git a/src/custom/fastlane/metadata/android/ja/full_description.txt b/src/customProductionFat/fastlane/metadata/android/ja/full_description.txt
index 92a3190d..92a3190d 100644
--- a/src/custom/fastlane/metadata/android/ja/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/ja/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/ja/short_description.txt b/src/customProductionFat/fastlane/metadata/android/ja/short_description.txt
index a32f5848..a32f5848 100644
--- a/src/custom/fastlane/metadata/android/ja/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/ja/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/ja/store-meta-ja.json b/src/customProductionFat/fastlane/metadata/android/ja/store-meta-ja.json
index 5d635f1b..5d635f1b 100644
--- a/src/custom/fastlane/metadata/android/ja/store-meta-ja.json
+++ b/src/customProductionFat/fastlane/metadata/android/ja/store-meta-ja.json
diff --git a/src/custom/fastlane/metadata/android/ja/title.txt b/src/customProductionFat/fastlane/metadata/android/ja/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/ja/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/ja/title.txt
diff --git a/src/custom/fastlane/metadata/android/lt/full_description.txt b/src/customProductionFat/fastlane/metadata/android/lt/full_description.txt
index f98710d2..f98710d2 100644
--- a/src/custom/fastlane/metadata/android/lt/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/lt/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/lt/short_description.txt b/src/customProductionFat/fastlane/metadata/android/lt/short_description.txt
index b5ad8ae6..b5ad8ae6 100644
--- a/src/custom/fastlane/metadata/android/lt/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/lt/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/lt/store-meta-lt.json b/src/customProductionFat/fastlane/metadata/android/lt/store-meta-lt.json
index 8868d47d..8868d47d 100644
--- a/src/custom/fastlane/metadata/android/lt/store-meta-lt.json
+++ b/src/customProductionFat/fastlane/metadata/android/lt/store-meta-lt.json
diff --git a/src/custom/fastlane/metadata/android/lt/title.txt b/src/customProductionFat/fastlane/metadata/android/lt/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/lt/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/lt/title.txt
diff --git a/src/custom/fastlane/metadata/android/nl/full_description.txt b/src/customProductionFat/fastlane/metadata/android/nl/full_description.txt
index 0a365ed2..0a365ed2 100644
--- a/src/custom/fastlane/metadata/android/nl/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/nl/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/nl/short_description.txt b/src/customProductionFat/fastlane/metadata/android/nl/short_description.txt
index e1ee3bac..e1ee3bac 100644
--- a/src/custom/fastlane/metadata/android/nl/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/nl/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/nl/store-meta-nl.json b/src/customProductionFat/fastlane/metadata/android/nl/store-meta-nl.json
index d8481dce..d8481dce 100644
--- a/src/custom/fastlane/metadata/android/nl/store-meta-nl.json
+++ b/src/customProductionFat/fastlane/metadata/android/nl/store-meta-nl.json
diff --git a/src/custom/fastlane/metadata/android/nl/title.txt b/src/customProductionFat/fastlane/metadata/android/nl/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/nl/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/nl/title.txt
diff --git a/src/custom/fastlane/metadata/android/pt-BR/full_description.txt b/src/customProductionFat/fastlane/metadata/android/pt-BR/full_description.txt
index fc9e95d1..fc9e95d1 100644
--- a/src/custom/fastlane/metadata/android/pt-BR/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/pt-BR/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/pt-BR/short_description.txt b/src/customProductionFat/fastlane/metadata/android/pt-BR/short_description.txt
index 79efc5e9..79efc5e9 100644
--- a/src/custom/fastlane/metadata/android/pt-BR/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/pt-BR/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json b/src/customProductionFat/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json
index 974408d5..974408d5 100644
--- a/src/custom/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json
+++ b/src/customProductionFat/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json
diff --git a/src/custom/fastlane/metadata/android/pt-BR/title.txt b/src/customProductionFat/fastlane/metadata/android/pt-BR/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/pt-BR/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/pt-BR/title.txt
diff --git a/src/custom/fastlane/metadata/android/ru/full_description.txt b/src/customProductionFat/fastlane/metadata/android/ru/full_description.txt
index 1960ca05..1960ca05 100644
--- a/src/custom/fastlane/metadata/android/ru/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/ru/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/ru/short_description.txt b/src/customProductionFat/fastlane/metadata/android/ru/short_description.txt
index 0d0182c8..0d0182c8 100644
--- a/src/custom/fastlane/metadata/android/ru/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/ru/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/ru/store-meta-ru.json b/src/customProductionFat/fastlane/metadata/android/ru/store-meta-ru.json
index 90d50adc..90d50adc 100644
--- a/src/custom/fastlane/metadata/android/ru/store-meta-ru.json
+++ b/src/customProductionFat/fastlane/metadata/android/ru/store-meta-ru.json
diff --git a/src/custom/fastlane/metadata/android/ru/title.txt b/src/customProductionFat/fastlane/metadata/android/ru/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/ru/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/ru/title.txt
diff --git a/src/custom/fastlane/metadata/android/tr/full_description.txt b/src/customProductionFat/fastlane/metadata/android/tr/full_description.txt
index 8c6e27ce..8c6e27ce 100644
--- a/src/custom/fastlane/metadata/android/tr/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/tr/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/tr/short_description.txt b/src/customProductionFat/fastlane/metadata/android/tr/short_description.txt
index 83342ec2..83342ec2 100644
--- a/src/custom/fastlane/metadata/android/tr/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/tr/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/tr/store-meta-tr.json b/src/customProductionFat/fastlane/metadata/android/tr/store-meta-tr.json
index 7fd8fcc0..7fd8fcc0 100644
--- a/src/custom/fastlane/metadata/android/tr/store-meta-tr.json
+++ b/src/customProductionFat/fastlane/metadata/android/tr/store-meta-tr.json
diff --git a/src/custom/fastlane/metadata/android/tr/title.txt b/src/customProductionFat/fastlane/metadata/android/tr/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/tr/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/tr/title.txt
diff --git a/src/custom/fastlane/metadata/android/uk/full_description.txt b/src/customProductionFat/fastlane/metadata/android/uk/full_description.txt
index e3813dd8..e3813dd8 100644
--- a/src/custom/fastlane/metadata/android/uk/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/uk/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/uk/short_description.txt b/src/customProductionFat/fastlane/metadata/android/uk/short_description.txt
index 3c886f52..3c886f52 100644
--- a/src/custom/fastlane/metadata/android/uk/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/uk/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/uk/store-meta-uk.json b/src/customProductionFat/fastlane/metadata/android/uk/store-meta-uk.json
index 4451e386..4451e386 100644
--- a/src/custom/fastlane/metadata/android/uk/store-meta-uk.json
+++ b/src/customProductionFat/fastlane/metadata/android/uk/store-meta-uk.json
diff --git a/src/custom/fastlane/metadata/android/uk/title.txt b/src/customProductionFat/fastlane/metadata/android/uk/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/uk/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/uk/title.txt
diff --git a/src/custom/fastlane/metadata/android/zh-TW/full_description.txt b/src/customProductionFat/fastlane/metadata/android/zh-TW/full_description.txt
index c6a5a957..c6a5a957 100644
--- a/src/custom/fastlane/metadata/android/zh-TW/full_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/zh-TW/full_description.txt
diff --git a/src/custom/fastlane/metadata/android/zh-TW/short_description.txt b/src/customProductionFat/fastlane/metadata/android/zh-TW/short_description.txt
index 08065bc8..08065bc8 100644
--- a/src/custom/fastlane/metadata/android/zh-TW/short_description.txt
+++ b/src/customProductionFat/fastlane/metadata/android/zh-TW/short_description.txt
diff --git a/src/custom/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json b/src/customProductionFat/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json
index 3bd96a33..3bd96a33 100644
--- a/src/custom/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json
+++ b/src/customProductionFat/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json
diff --git a/src/custom/fastlane/metadata/android/zh-TW/title.txt b/src/customProductionFat/fastlane/metadata/android/zh-TW/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/android/zh-TW/title.txt
+++ b/src/customProductionFat/fastlane/metadata/android/zh-TW/title.txt
diff --git a/src/normal/fastlane/metadata/android/ar/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/ar/full_description.txt
index 6dbaa226..6dbaa226 100644
--- a/src/normal/fastlane/metadata/android/ar/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/ar/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/ar/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/ar/short_description.txt
index ed197d59..ed197d59 100644
--- a/src/normal/fastlane/metadata/android/ar/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/ar/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/ar/store-meta-ar.json b/src/normalProductionFat/fastlane/metadata/android/ar/store-meta-ar.json
index ece43856..ece43856 100644
--- a/src/normal/fastlane/metadata/android/ar/store-meta-ar.json
+++ b/src/normalProductionFat/fastlane/metadata/android/ar/store-meta-ar.json
diff --git a/src/normal/fastlane/metadata/android/ar/title.txt b/src/normalProductionFat/fastlane/metadata/android/ar/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/ar/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/ar/title.txt
diff --git a/src/normal/fastlane/metadata/android/cs/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/cs/full_description.txt
index cb613c50..cb613c50 100644
--- a/src/normal/fastlane/metadata/android/cs/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/cs/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/cs/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/cs/short_description.txt
index ce6e38ed..ce6e38ed 100644
--- a/src/normal/fastlane/metadata/android/cs/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/cs/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/cs/store-meta-cs.json b/src/normalProductionFat/fastlane/metadata/android/cs/store-meta-cs.json
index ebc79bd8..ebc79bd8 100644
--- a/src/normal/fastlane/metadata/android/cs/store-meta-cs.json
+++ b/src/normalProductionFat/fastlane/metadata/android/cs/store-meta-cs.json
diff --git a/src/normal/fastlane/metadata/android/cs/title.txt b/src/normalProductionFat/fastlane/metadata/android/cs/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/cs/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/cs/title.txt
diff --git a/src/normal/fastlane/metadata/android/de-DE/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/de-DE/full_description.txt
index d770a522..d770a522 100644
--- a/src/normal/fastlane/metadata/android/de-DE/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/de-DE/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/de-DE/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/de-DE/short_description.txt
index 0a3c3dd5..0a3c3dd5 100644
--- a/src/normal/fastlane/metadata/android/de-DE/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/de-DE/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/de-DE/title.txt b/src/normalProductionFat/fastlane/metadata/android/de-DE/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/de-DE/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/de-DE/title.txt
diff --git a/src/normal/fastlane/metadata/android/de/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/de/full_description.txt
index d770a522..d770a522 100644
--- a/src/normal/fastlane/metadata/android/de/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/de/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/de/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/de/short_description.txt
index 85cb64fe..85cb64fe 100644
--- a/src/normal/fastlane/metadata/android/de/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/de/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/de/store-meta-de.json b/src/normalProductionFat/fastlane/metadata/android/de/store-meta-de.json
index 93712845..93712845 100644
--- a/src/normal/fastlane/metadata/android/de/store-meta-de.json
+++ b/src/normalProductionFat/fastlane/metadata/android/de/store-meta-de.json
diff --git a/src/normal/fastlane/metadata/android/de/title.txt b/src/normalProductionFat/fastlane/metadata/android/de/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/de/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/de/title.txt
diff --git a/src/normal/fastlane/metadata/android/el-GR/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/el-GR/full_description.txt
index aaaaf476..aaaaf476 100644
--- a/src/normal/fastlane/metadata/android/el-GR/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/el-GR/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/el-GR/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/el-GR/short_description.txt
index f204880e..f204880e 100644
--- a/src/normal/fastlane/metadata/android/el-GR/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/el-GR/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/el-GR/title.txt b/src/normalProductionFat/fastlane/metadata/android/el-GR/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/el-GR/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/el-GR/title.txt
diff --git a/src/normal/fastlane/metadata/android/el/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/el/full_description.txt
index aaaaf476..aaaaf476 100644
--- a/src/normal/fastlane/metadata/android/el/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/el/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/el/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/el/short_description.txt
index 4ac7309e..4ac7309e 100644
--- a/src/normal/fastlane/metadata/android/el/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/el/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/el/store-meta-el.json b/src/normalProductionFat/fastlane/metadata/android/el/store-meta-el.json
index 0e32bdc9..0e32bdc9 100644
--- a/src/normal/fastlane/metadata/android/el/store-meta-el.json
+++ b/src/normalProductionFat/fastlane/metadata/android/el/store-meta-el.json
diff --git a/src/normal/fastlane/metadata/android/el/title.txt b/src/normalProductionFat/fastlane/metadata/android/el/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/el/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/el/title.txt
diff --git a/src/normal/fastlane/metadata/android/en-US/changelogs/168000.txt b/src/normalProductionFat/fastlane/metadata/android/en-US/changelogs/168000.txt
index 80766d7f..80766d7f 100644
--- a/src/normal/fastlane/metadata/android/en-US/changelogs/168000.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/en-US/changelogs/168000.txt
diff --git a/src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt b/src/normalProductionFat/fastlane/metadata/android/en-US/changelogs/170000.txt
index d2dbd888..d2dbd888 100644
--- a/src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/en-US/changelogs/170000.txt
diff --git a/src/normal/fastlane/metadata/android/en-US/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/en-US/full_description.txt
index 2fcf278a..2fcf278a 100644
--- a/src/normal/fastlane/metadata/android/en-US/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/en-US/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/en-US/images/icon.png b/src/normalProductionFat/fastlane/metadata/android/en-US/images/icon.png
index 6cf4e79b..6cf4e79b 100644
--- a/src/normal/fastlane/metadata/android/en-US/images/icon.png
+++ b/src/normalProductionFat/fastlane/metadata/android/en-US/images/icon.png
Binary files differ
diff --git a/src/normal/fastlane/metadata/android/en-US/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/en-US/short_description.txt
index 6f481599..6f481599 100644
--- a/src/normal/fastlane/metadata/android/en-US/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/en-US/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/en-US/title.txt b/src/normalProductionFat/fastlane/metadata/android/en-US/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/en-US/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/en-US/title.txt
diff --git a/src/normal/fastlane/metadata/android/en-US/video.txt b/src/normalProductionFat/fastlane/metadata/android/en-US/video.txt
index e69de29b..e69de29b 100644
--- a/src/normal/fastlane/metadata/android/en-US/video.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/en-US/video.txt
diff --git a/src/normal/fastlane/metadata/android/es-419/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/es-419/full_description.txt
index d961f6e7..d961f6e7 100644
--- a/src/normal/fastlane/metadata/android/es-419/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/es-419/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/es-419/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/es-419/short_description.txt
index f4e7b64c..f4e7b64c 100644
--- a/src/normal/fastlane/metadata/android/es-419/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/es-419/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/es-419/title.txt b/src/normalProductionFat/fastlane/metadata/android/es-419/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/es-419/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/es-419/title.txt
diff --git a/src/normal/fastlane/metadata/android/es-CU/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/es-CU/full_description.txt
index d961f6e7..d961f6e7 100644
--- a/src/normal/fastlane/metadata/android/es-CU/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/es-CU/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/es-CU/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/es-CU/short_description.txt
index e2e2d0f9..e2e2d0f9 100644
--- a/src/normal/fastlane/metadata/android/es-CU/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/es-CU/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/es-CU/store-meta-es-CU.json b/src/normalProductionFat/fastlane/metadata/android/es-CU/store-meta-es-CU.json
index 546cbffe..546cbffe 100644
--- a/src/normal/fastlane/metadata/android/es-CU/store-meta-es-CU.json
+++ b/src/normalProductionFat/fastlane/metadata/android/es-CU/store-meta-es-CU.json
diff --git a/src/normal/fastlane/metadata/android/es-CU/title.txt b/src/normalProductionFat/fastlane/metadata/android/es-CU/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/es-CU/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/es-CU/title.txt
diff --git a/src/normal/fastlane/metadata/android/es/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/es/full_description.txt
index e462923d..e462923d 100644
--- a/src/normal/fastlane/metadata/android/es/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/es/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/es/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/es/short_description.txt
index 1959bb7e..1959bb7e 100644
--- a/src/normal/fastlane/metadata/android/es/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/es/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/es/store-meta-es.json b/src/normalProductionFat/fastlane/metadata/android/es/store-meta-es.json
index ab87c4e1..ab87c4e1 100644
--- a/src/normal/fastlane/metadata/android/es/store-meta-es.json
+++ b/src/normalProductionFat/fastlane/metadata/android/es/store-meta-es.json
diff --git a/src/normal/fastlane/metadata/android/es/title.txt b/src/normalProductionFat/fastlane/metadata/android/es/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/es/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/es/title.txt
diff --git a/src/normalProductionFat/fastlane/metadata/android/fr/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/fr/full_description.txt
new file mode 100644
index 00000000..55f0f997
--- /dev/null
+++ b/src/normalProductionFat/fastlane/metadata/android/fr/full_description.txt
@@ -0,0 +1,12 @@
+Bitmask est un client RPV à configuration automatique. Il dispose de plusieurs techniques pour contourner la censure, le blocage du réseau ou éviter la surveillance. Après avoir sélectionné un fournisseur de services compatible, il cryptera et acheminera en toute sécurité l'ensemble de votre trafic réseau par l'intermédiaire de votre fournisseur de services de confiance.
+
+Et vous êtes prêt à vous lancer !
+
+Bitmask est un client RPV à code source ouvert, distribué sous licence GPLv3. Pour en savoir plus, consultez le site https://0xacab.org/leap/bitmask_android
+
+FAQ :
+
+* qui : leap.se, un collectif présent depuis 2011, amoureux du concept du droit de chuchoter.
+* Les traductions sont les bienvenues sur notre projet Transifex https://app.transifex.com/otf/bitmask/dashboard/
+
+Si vous rencontrez des problèmes ou si vous voulez des versions innovantes, rejoignez notre chat https://matrix.to/#/#leap:libera.chat ou écrivez un rapport de bug : https://0xacab.org/leap/bitmask_android/ \ No newline at end of file
diff --git a/src/normalProductionFat/fastlane/metadata/android/fr/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/fr/short_description.txt
new file mode 100644
index 00000000..72144ca3
--- /dev/null
+++ b/src/normalProductionFat/fastlane/metadata/android/fr/short_description.txt
@@ -0,0 +1,2 @@
+La communication chiffrée pour simples mortels
+(Super héros aussi bienvenus). \ No newline at end of file
diff --git a/src/normal/fastlane/metadata/android/fr/store-meta-fr.json b/src/normalProductionFat/fastlane/metadata/android/fr/store-meta-fr.json
index a53f7861..a53f7861 100644
--- a/src/normal/fastlane/metadata/android/fr/store-meta-fr.json
+++ b/src/normalProductionFat/fastlane/metadata/android/fr/store-meta-fr.json
diff --git a/src/normal/fastlane/metadata/android/it/title.txt b/src/normalProductionFat/fastlane/metadata/android/fr/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/it/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/fr/title.txt
diff --git a/src/normal/fastlane/metadata/android/it/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/it/full_description.txt
index ac380573..ac380573 100644
--- a/src/normal/fastlane/metadata/android/it/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/it/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/it/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/it/short_description.txt
index b93be5fb..b93be5fb 100644
--- a/src/normal/fastlane/metadata/android/it/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/it/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/it/store-meta-it.json b/src/normalProductionFat/fastlane/metadata/android/it/store-meta-it.json
index 17f4de3d..17f4de3d 100644
--- a/src/normal/fastlane/metadata/android/it/store-meta-it.json
+++ b/src/normalProductionFat/fastlane/metadata/android/it/store-meta-it.json
diff --git a/src/normal/fastlane/metadata/android/lt/title.txt b/src/normalProductionFat/fastlane/metadata/android/it/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/lt/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/it/title.txt
diff --git a/src/normal/fastlane/metadata/android/lt/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/lt/full_description.txt
index e5344c6f..e5344c6f 100644
--- a/src/normal/fastlane/metadata/android/lt/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/lt/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/lt/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/lt/short_description.txt
index 8e6714c7..8e6714c7 100644
--- a/src/normal/fastlane/metadata/android/lt/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/lt/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/lt/store-meta-lt.json b/src/normalProductionFat/fastlane/metadata/android/lt/store-meta-lt.json
index a77847ca..a77847ca 100644
--- a/src/normal/fastlane/metadata/android/lt/store-meta-lt.json
+++ b/src/normalProductionFat/fastlane/metadata/android/lt/store-meta-lt.json
diff --git a/src/normal/fastlane/metadata/android/nl-NL/title.txt b/src/normalProductionFat/fastlane/metadata/android/lt/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/nl-NL/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/lt/title.txt
diff --git a/src/normal/fastlane/metadata/android/nl-NL/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/nl-NL/full_description.txt
index a714dff0..a714dff0 100644
--- a/src/normal/fastlane/metadata/android/nl-NL/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/nl-NL/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/nl-NL/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/nl-NL/short_description.txt
index dd626a6c..dd626a6c 100644
--- a/src/normal/fastlane/metadata/android/nl-NL/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/nl-NL/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/nl/title.txt b/src/normalProductionFat/fastlane/metadata/android/nl-NL/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/nl/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/nl-NL/title.txt
diff --git a/src/normal/fastlane/metadata/android/nl/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/nl/full_description.txt
index a714dff0..a714dff0 100644
--- a/src/normal/fastlane/metadata/android/nl/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/nl/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/nl/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/nl/short_description.txt
index dd626a6c..dd626a6c 100644
--- a/src/normal/fastlane/metadata/android/nl/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/nl/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/nl/store-meta-nl.json b/src/normalProductionFat/fastlane/metadata/android/nl/store-meta-nl.json
index 61c9b38d..61c9b38d 100644
--- a/src/normal/fastlane/metadata/android/nl/store-meta-nl.json
+++ b/src/normalProductionFat/fastlane/metadata/android/nl/store-meta-nl.json
diff --git a/src/normal/fastlane/metadata/android/pt-BR/title.txt b/src/normalProductionFat/fastlane/metadata/android/nl/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/pt-BR/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/nl/title.txt
diff --git a/src/normal/fastlane/metadata/android/pt-BR/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/pt-BR/full_description.txt
index 562c7ebc..562c7ebc 100644
--- a/src/normal/fastlane/metadata/android/pt-BR/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/pt-BR/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/pt-BR/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/pt-BR/short_description.txt
index d37b3a1a..d37b3a1a 100644
--- a/src/normal/fastlane/metadata/android/pt-BR/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/pt-BR/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json b/src/normalProductionFat/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json
index 1b1447d8..1b1447d8 100644
--- a/src/normal/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json
+++ b/src/normalProductionFat/fastlane/metadata/android/pt-BR/store-meta-pt-BR.json
diff --git a/src/normal/fastlane/metadata/android/ru-RU/title.txt b/src/normalProductionFat/fastlane/metadata/android/pt-BR/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/ru-RU/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/pt-BR/title.txt
diff --git a/src/normal/fastlane/metadata/android/ru-RU/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/ru-RU/full_description.txt
index 1760c293..1760c293 100644
--- a/src/normal/fastlane/metadata/android/ru-RU/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/ru-RU/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/ru-RU/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/ru-RU/short_description.txt
index fb99634a..fb99634a 100644
--- a/src/normal/fastlane/metadata/android/ru-RU/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/ru-RU/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/ru/title.txt b/src/normalProductionFat/fastlane/metadata/android/ru-RU/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/ru/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/ru-RU/title.txt
diff --git a/src/normal/fastlane/metadata/android/ru/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/ru/full_description.txt
index 1760c293..1760c293 100644
--- a/src/normal/fastlane/metadata/android/ru/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/ru/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/ru/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/ru/short_description.txt
index fb99634a..fb99634a 100644
--- a/src/normal/fastlane/metadata/android/ru/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/ru/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/ru/store-meta-ru.json b/src/normalProductionFat/fastlane/metadata/android/ru/store-meta-ru.json
index 979cdf78..979cdf78 100644
--- a/src/normal/fastlane/metadata/android/ru/store-meta-ru.json
+++ b/src/normalProductionFat/fastlane/metadata/android/ru/store-meta-ru.json
diff --git a/src/normal/fastlane/metadata/android/tr-TR/title.txt b/src/normalProductionFat/fastlane/metadata/android/ru/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/tr-TR/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/ru/title.txt
diff --git a/src/normal/fastlane/metadata/android/tr-TR/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/tr-TR/full_description.txt
index 10418aa9..10418aa9 100644
--- a/src/normal/fastlane/metadata/android/tr-TR/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/tr-TR/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/tr-TR/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/tr-TR/short_description.txt
index b5e8c91f..b5e8c91f 100644
--- a/src/normal/fastlane/metadata/android/tr-TR/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/tr-TR/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/tr/title.txt b/src/normalProductionFat/fastlane/metadata/android/tr-TR/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/tr/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/tr-TR/title.txt
diff --git a/src/normal/fastlane/metadata/android/tr/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/tr/full_description.txt
index a2db5d68..a2db5d68 100644
--- a/src/normal/fastlane/metadata/android/tr/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/tr/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/tr/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/tr/short_description.txt
index 4e042739..4e042739 100644
--- a/src/normal/fastlane/metadata/android/tr/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/tr/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/tr/store-meta-tr.json b/src/normalProductionFat/fastlane/metadata/android/tr/store-meta-tr.json
index 76c4ad65..76c4ad65 100644
--- a/src/normal/fastlane/metadata/android/tr/store-meta-tr.json
+++ b/src/normalProductionFat/fastlane/metadata/android/tr/store-meta-tr.json
diff --git a/src/normal/fastlane/metadata/android/uk/title.txt b/src/normalProductionFat/fastlane/metadata/android/tr/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/uk/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/tr/title.txt
diff --git a/src/normal/fastlane/metadata/android/uk/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/uk/full_description.txt
index 2eb74b73..2eb74b73 100644
--- a/src/normal/fastlane/metadata/android/uk/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/uk/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/uk/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/uk/short_description.txt
index 0487f177..0487f177 100644
--- a/src/normal/fastlane/metadata/android/uk/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/uk/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/uk/store-meta-uk.json b/src/normalProductionFat/fastlane/metadata/android/uk/store-meta-uk.json
index 04d82edd..04d82edd 100644
--- a/src/normal/fastlane/metadata/android/uk/store-meta-uk.json
+++ b/src/normalProductionFat/fastlane/metadata/android/uk/store-meta-uk.json
diff --git a/src/normal/fastlane/metadata/android/zh-TW/title.txt b/src/normalProductionFat/fastlane/metadata/android/uk/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/android/zh-TW/title.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/uk/title.txt
diff --git a/src/normal/fastlane/metadata/android/zh-TW/full_description.txt b/src/normalProductionFat/fastlane/metadata/android/zh-TW/full_description.txt
index b8c707ee..b8c707ee 100644
--- a/src/normal/fastlane/metadata/android/zh-TW/full_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/zh-TW/full_description.txt
diff --git a/src/normal/fastlane/metadata/android/zh-TW/short_description.txt b/src/normalProductionFat/fastlane/metadata/android/zh-TW/short_description.txt
index cc2717d6..cc2717d6 100644
--- a/src/normal/fastlane/metadata/android/zh-TW/short_description.txt
+++ b/src/normalProductionFat/fastlane/metadata/android/zh-TW/short_description.txt
diff --git a/src/normal/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json b/src/normalProductionFat/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json
index 5aba12cd..5aba12cd 100644
--- a/src/normal/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json
+++ b/src/normalProductionFat/fastlane/metadata/android/zh-TW/store-meta-zh-TW.json
diff --git a/src/normalProductionFat/fastlane/metadata/android/zh-TW/title.txt b/src/normalProductionFat/fastlane/metadata/android/zh-TW/title.txt
new file mode 100644
index 00000000..a953d6a6
--- /dev/null
+++ b/src/normalProductionFat/fastlane/metadata/android/zh-TW/title.txt
@@ -0,0 +1 @@
+Bitmask \ No newline at end of file