diff --git a/ChangeLog.md b/ChangeLog.md index 27024bd92..5e0e2e18b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -942,3 +942,43 @@ **InviZible Pro beta 1.9.3** * Fixed Tor not starting after enabling Allow Tor Tethering. * Fixes and optimizations. + +**InviZible Pro beta 1.9.4** +* Updated Tor to version 4.8.3. +* Updated Tor geoip file. +* Updated Tor lyrebird obfuscating proxy. +* Updated Tor Conjure bridge. +* Updated Tor Snowflake bridge. +* Updated DNSCrypt. +* Fixed app can't start modules when ports are busy. +* Fixes and optimizations. + +**InviZible Pro beta 1.9.5** +* Updated DNSCrypt to version 2.1.5. +* Added support for the Tor WebTunnel bridge. + +**InviZible Pro beta 1.9.6** +* Improved Tor WebTunnel bridge censorship resistance. +* Improved Tor Snowflake bridge connection stability. +* Fixed adding meek_lite bridges with utls option. +* Fixed display of ping and country for some WebTunnel bridges. +* Optimized memory usage. + +**InviZible Pro beta 1.9.7** +* Updated Tor to version 4.8.4. +* Added a suggestion to reset the module settings in case of a startup failure. +* Fixes and optimizations. + +**InviZible Pro beta 1.9.8** +* Updated Tor to version 4.8.5. +* Implemented customizable SNI for Tor connections. +* Using Chromium's TLS fingerprint instead of Firefox's obsolete TLS fingerprint for Tor connections. +* Updated Tor WebTunnel bridge. +* Fixed ANR on Android 4.4.2. +* Fixed requesting new bridges button not responding in rare cases. +* Added Ukrainian translation. + +**InviZible Pro beta 1.9.9** +* Added TrackHostExits option to Tor settings. +* Fixed the Tor WebTunnel bridge failure to connect on Android versions lower than 8. +* Fixes and optimizations. diff --git a/build.gradle b/build.gradle index 5be85071f..2daa9850f 100644 --- a/build.gradle +++ b/build.gradle @@ -2,8 +2,8 @@ buildscript { ext { - kotlin_version = '1.8.20' - dagger_version = '2.45' + kotlin_version = '1.9.0' + dagger_version = '2.47' multidex_version = "2.0.1" } @@ -30,6 +30,6 @@ allprojects { } } -task clean(type: Delete) { +tasks.register('clean', Delete) { delete rootProject.buildDir } diff --git a/fastlane/metadata/android/en-US/changelogs/100194.txt b/fastlane/metadata/android/en-US/changelogs/100194.txt new file mode 100644 index 000000000..733d2d425 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/100194.txt @@ -0,0 +1,9 @@ +**InviZible Pro beta 1.9.4** +* Updated Tor to version 4.8.3. +* Updated Tor geoip file. +* Updated Tor lyrebird obfuscating proxy. +* Updated Tor Conjure bridge. +* Updated Tor Snowflake bridge. +* Updated DNSCrypt. +* Fixed app can't start modules when ports are busy. +* Fixes and optimizations. diff --git a/fastlane/metadata/android/en-US/changelogs/100195.txt b/fastlane/metadata/android/en-US/changelogs/100195.txt new file mode 100644 index 000000000..6710b4b20 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/100195.txt @@ -0,0 +1,3 @@ +**InviZible Pro beta 1.9.5** +* Updated DNSCrypt to version 2.1.5. +* Added support for the Tor WebTunnel bridge. diff --git a/fastlane/metadata/android/en-US/changelogs/100196.txt b/fastlane/metadata/android/en-US/changelogs/100196.txt new file mode 100644 index 000000000..5e75b4bae --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/100196.txt @@ -0,0 +1,6 @@ +**InviZible Pro beta 1.9.6** +* Improved Tor WebTunnel bridge censorship resistance. +* Improved Tor Snowflake bridge connection stability. +* Fixed adding meek_lite bridges with utls option. +* Fixed display of ping and country for some WebTunnel bridges. +* Optimized memory usage. diff --git a/fastlane/metadata/android/en-US/changelogs/100197.txt b/fastlane/metadata/android/en-US/changelogs/100197.txt new file mode 100644 index 000000000..8fda115aa --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/100197.txt @@ -0,0 +1,4 @@ +**InviZible Pro beta 1.9.7** +* Updated Tor to version 4.8.4. +* Added a suggestion to reset the module settings in case of a startup failure. +* Fixes and optimizations. diff --git a/fastlane/metadata/android/en-US/changelogs/100198.txt b/fastlane/metadata/android/en-US/changelogs/100198.txt new file mode 100644 index 000000000..783279704 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/100198.txt @@ -0,0 +1,8 @@ +**InviZible Pro beta 1.9.8** +* Updated Tor to version 4.8.5. +* Implemented customizable SNI for Tor connections. +* Using Chromium's TLS fingerprint instead of Firefox's obsolete TLS fingerprint for Tor connections. +* Updated Tor WebTunnel bridge. +* Fixed ANR on Android 4.4.2. +* Fixed requesting new bridges button not responding in rare cases. +* Added Ukrainian translation. diff --git a/fastlane/metadata/android/en-US/changelogs/100199.txt b/fastlane/metadata/android/en-US/changelogs/100199.txt new file mode 100644 index 000000000..ae4e045ab --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/100199.txt @@ -0,0 +1,4 @@ +**InviZible Pro beta 1.9.9** +* Added TrackHostExits option to Tor settings. +* Fixed the Tor WebTunnel bridge failure to connect on Android versions lower than 8. +* Fixes and optimizations. diff --git a/gradle.properties b/gradle.properties index fc5c1627f..adddd56f8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,4 @@ kotlin.caching.enabled=true android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false android.nonFinalResIds=false -#org.gradle.unsafe.configuration-cache=true +org.gradle.configuration-cache=true diff --git a/tordnscrypt/build.gradle b/tordnscrypt/build.gradle index fd7e5ffc6..7d724c224 100644 --- a/tordnscrypt/build.gradle +++ b/tordnscrypt/build.gradle @@ -5,17 +5,17 @@ plugins { } android { - compileSdkVersion 33 + compileSdk 33 namespace 'pan.alexander.tordnscrypt' - flavorDimensions "version", "processor" + flavorDimensions = ["version", "processor"] productFlavors { fdroid{ applicationId "pan.alexander.tordnscrypt.stable" - versionName "6.2.0" + versionName "6.3.0" dimension = 'version' resValue 'string', 'package_name', applicationId } @@ -55,9 +55,9 @@ android { defaultConfig { minSdkVersion 19 targetSdkVersion 33 - versionCode 193 + versionCode 199 - resConfigs "en", "ru", "pl", "de", "fa", "fi", "in", "fr", "ja", "zh", "es", "pt", "pt-rBR", "el", "tr", "it" + resConfigs "en", "ru", "pl", "de", "fa", "fi", "in", "fr", "ja", "zh", "es", "pt", "pt-rBR", "el", "tr", "it", "uk" externalNativeBuild { cmake { @@ -85,7 +85,7 @@ android { sourceCompatibility = 17 targetCompatibility = 17 } - buildToolsVersion = '30.0.3' + buildToolsVersion = '33.0.1' bundle { language { @@ -113,9 +113,10 @@ android { doNotStrip '*/*/libobfs4proxy.so' doNotStrip '*/*/libsnowflake.so' doNotStrip '*/*/libconjure.so' + doNotStrip '*/*/libwebtunnel.so' } - applicationVariants.all { variant -> + applicationVariants.configureEach { variant -> def abiVersion = variant.mergedFlavor.versionCode @@ -143,11 +144,11 @@ repositories { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'androidx.preference:preference-ktx:1.2.0' + implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'com.google.android.material:material:1.9.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.recyclerview:recyclerview:1.3.0' + implementation 'androidx.recyclerview:recyclerview:1.3.1' implementation 'androidx.lifecycle:lifecycle-process:2.6.1' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1' diff --git a/tordnscrypt/libs/arm64-v8a/libconjure.so b/tordnscrypt/libs/arm64-v8a/libconjure.so index 1b0766215..737fa457a 100755 Binary files a/tordnscrypt/libs/arm64-v8a/libconjure.so and b/tordnscrypt/libs/arm64-v8a/libconjure.so differ diff --git a/tordnscrypt/libs/arm64-v8a/libdnscrypt-proxy.so b/tordnscrypt/libs/arm64-v8a/libdnscrypt-proxy.so index 1a8461aad..242ab44c7 100755 Binary files a/tordnscrypt/libs/arm64-v8a/libdnscrypt-proxy.so and b/tordnscrypt/libs/arm64-v8a/libdnscrypt-proxy.so differ diff --git a/tordnscrypt/libs/arm64-v8a/libobfs4proxy.so b/tordnscrypt/libs/arm64-v8a/libobfs4proxy.so index 0e1518fa2..6cfaddadb 100755 Binary files a/tordnscrypt/libs/arm64-v8a/libobfs4proxy.so and b/tordnscrypt/libs/arm64-v8a/libobfs4proxy.so differ diff --git a/tordnscrypt/libs/arm64-v8a/libsnowflake.so b/tordnscrypt/libs/arm64-v8a/libsnowflake.so index 3a6de8f91..bb78889b4 100755 Binary files a/tordnscrypt/libs/arm64-v8a/libsnowflake.so and b/tordnscrypt/libs/arm64-v8a/libsnowflake.so differ diff --git a/tordnscrypt/libs/arm64-v8a/libtor.so b/tordnscrypt/libs/arm64-v8a/libtor.so index 14cbf9fe3..5e1f8763a 100644 Binary files a/tordnscrypt/libs/arm64-v8a/libtor.so and b/tordnscrypt/libs/arm64-v8a/libtor.so differ diff --git a/tordnscrypt/libs/arm64-v8a/libwebtunnel.so b/tordnscrypt/libs/arm64-v8a/libwebtunnel.so new file mode 100755 index 000000000..db8af3454 Binary files /dev/null and b/tordnscrypt/libs/arm64-v8a/libwebtunnel.so differ diff --git a/tordnscrypt/libs/armeabi-v7a/libconjure.so b/tordnscrypt/libs/armeabi-v7a/libconjure.so index a5ba26ebe..6da78e30d 100755 Binary files a/tordnscrypt/libs/armeabi-v7a/libconjure.so and b/tordnscrypt/libs/armeabi-v7a/libconjure.so differ diff --git a/tordnscrypt/libs/armeabi-v7a/libdnscrypt-proxy.so b/tordnscrypt/libs/armeabi-v7a/libdnscrypt-proxy.so index 135686818..53dcc1d16 100755 Binary files a/tordnscrypt/libs/armeabi-v7a/libdnscrypt-proxy.so and b/tordnscrypt/libs/armeabi-v7a/libdnscrypt-proxy.so differ diff --git a/tordnscrypt/libs/armeabi-v7a/libobfs4proxy.so b/tordnscrypt/libs/armeabi-v7a/libobfs4proxy.so index 3e08f86ec..e17fb9a99 100755 Binary files a/tordnscrypt/libs/armeabi-v7a/libobfs4proxy.so and b/tordnscrypt/libs/armeabi-v7a/libobfs4proxy.so differ diff --git a/tordnscrypt/libs/armeabi-v7a/libsnowflake.so b/tordnscrypt/libs/armeabi-v7a/libsnowflake.so index 6093477fa..126dc2554 100755 Binary files a/tordnscrypt/libs/armeabi-v7a/libsnowflake.so and b/tordnscrypt/libs/armeabi-v7a/libsnowflake.so differ diff --git a/tordnscrypt/libs/armeabi-v7a/libtor.so b/tordnscrypt/libs/armeabi-v7a/libtor.so index b17d540f9..acb262893 100644 Binary files a/tordnscrypt/libs/armeabi-v7a/libtor.so and b/tordnscrypt/libs/armeabi-v7a/libtor.so differ diff --git a/tordnscrypt/libs/armeabi-v7a/libwebtunnel.so b/tordnscrypt/libs/armeabi-v7a/libwebtunnel.so new file mode 100755 index 000000000..9f0073d0f Binary files /dev/null and b/tordnscrypt/libs/armeabi-v7a/libwebtunnel.so differ diff --git a/tordnscrypt/libs/build b/tordnscrypt/libs/build index ab3c32df5..0aaa86368 100755 --- a/tordnscrypt/libs/build +++ b/tordnscrypt/libs/build @@ -110,6 +110,15 @@ go build -ldflags="-s -w" -o libconjure.so mv libconjure.so ${LIBS_ROOT}/${ABI}/libconjure.so || exit 1 popd +################ +# libwebtunnel # +################ + +pushd webtunnel/main/client +go build -ldflags="-s -w" -o libwebtunnel.so +mv libwebtunnel.so ${LIBS_ROOT}/${ABI}/libwebtunnel.so || exit 1 +popd + ################ # libnflog # ################ diff --git a/tordnscrypt/libs/prebuild b/tordnscrypt/libs/prebuild index 47e2631bd..ee4e1c11e 100755 --- a/tordnscrypt/libs/prebuild +++ b/tordnscrypt/libs/prebuild @@ -7,11 +7,12 @@ dnscryptproxy_version=master snowflake_version=v2.6.0 libzmq_version=5bf04ee2ff207f0eaf34298658fe354ea61e1839 conjure_version=prod -tor_openssl_version=OpenSSL_1_1_1s +webtunnel_version=prod +tor_openssl_version=openssl-3.1.2 libevent_version=release-2.1.12-stable zstd_version=v1.4.9 xz_version=v5.2.4 -tor_version=release-0.4.7 +tor_version=prod i2pd_openssl_version=OpenSSL_1_1_1u miniupnpc_version=c2818392e12f42901ab5abf145f43d69825a38c9 i2pd_version=2.48.0 @@ -32,6 +33,8 @@ popd git clone --single-branch --branch $conjure_version https://gitlab.torproject.org/Gedsh/conjure +git clone --single-branch --branch $webtunnel_version https://gitlab.torproject.org/Gedsh/webtunnel + git clone https://github.com/Gedsh/Nflog-android pushd ../../TorBuildScript/external/ @@ -39,7 +42,7 @@ git clone --single-branch --branch $tor_openssl_version https://github.com/opens git clone --single-branch --branch $libevent_version https://github.com/libevent/libevent.git git clone --single-branch --branch $zstd_version https://github.com/facebook/zstd.git git clone --single-branch --branch $xz_version https://git.tukaani.org/xz.git -git clone --single-branch --branch $tor_version https://git.torproject.org/tor.git +git clone --single-branch --branch $tor_version https://gitlab.torproject.org/Gedsh/tor.git popd pushd ../../PurpleI2PBuildScript/external/ diff --git a/tordnscrypt/owner.gradle b/tordnscrypt/owner.gradle index 206d732fe..d9b96c76f 100644 --- a/tordnscrypt/owner.gradle +++ b/tordnscrypt/owner.gradle @@ -9,11 +9,11 @@ def keystoreProperties = new Properties() keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) android { - compileSdkVersion 33 + compileSdk 33 namespace 'pan.alexander.tordnscrypt' - flavorDimensions "version", "processor" + flavorDimensions = ["version", "processor"] signingConfigs { stablesign { @@ -34,7 +34,7 @@ android { productFlavors { lite { applicationId "pan.alexander.tordnscrypt.stable" - versionName "6.2.0" + versionName "6.3.0" dimension = 'version' signingConfig signingConfigs.stablesign resValue 'string', 'package_name', applicationId @@ -42,7 +42,7 @@ android { pro { applicationId "pan.alexander.tordnscrypt.stable" - versionName "6.2.0" + versionName "6.3.0" dimension = 'version' signingConfig signingConfigs.stablesign resValue 'string', 'package_name', applicationId @@ -50,7 +50,7 @@ android { beta { applicationId "pan.alexander.tordnscrypt" - versionName "1.9.3" + versionName "1.9.9" dimension = 'version' signingConfig signingConfigs.betasign resValue 'string', 'package_name', applicationId @@ -59,7 +59,7 @@ android { google_play { minSdkVersion 22 applicationId "pan.alexander.tordnscrypt.gp" - versionName "6.2.0" + versionName "6.3.0" dimension = 'version' signingConfig signingConfigs.stablesign resValue 'string', 'package_name', applicationId @@ -91,9 +91,9 @@ android { defaultConfig { minSdkVersion 19 targetSdkVersion 33 - versionCode 193 + versionCode 199 - resConfigs "en", "ru", "pl", "de", "fa", "fi", "in", "fr", "ja", "zh", "es", "pt", "pt-rBR", "el", "tr", "it" + resConfigs "en", "ru", "pl", "de", "fa", "fi", "in", "fr", "ja", "zh", "es", "pt", "pt-rBR", "el", "tr", "it", "uk" externalNativeBuild { cmake { @@ -127,7 +127,7 @@ android { sourceCompatibility = 17 targetCompatibility = 17 } - buildToolsVersion = '30.0.3' + buildToolsVersion = '33.0.1' bundle { language { @@ -155,9 +155,10 @@ android { doNotStrip '*/*/libobfs4proxy.so' doNotStrip '*/*/libsnowflake.so' doNotStrip '*/*/libconjure.so' + doNotStrip '*/*/libwebtunnel.so' } - applicationVariants.all { variant -> + applicationVariants.configureEach { variant -> def abiVersion = variant.mergedFlavor.versionCode @@ -187,11 +188,11 @@ repositories { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'androidx.preference:preference-ktx:1.2.0' + implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'com.google.android.material:material:1.9.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.recyclerview:recyclerview:1.3.0' + implementation 'androidx.recyclerview:recyclerview:1.3.1' implementation 'androidx.lifecycle:lifecycle-process:2.6.1' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1' diff --git a/tordnscrypt/src/main/assets/tor.mp3 b/tordnscrypt/src/main/assets/tor.mp3 index a08e01ddc..6acbe0a8b 100644 Binary files a/tordnscrypt/src/main/assets/tor.mp3 and b/tordnscrypt/src/main/assets/tor.mp3 differ diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/App.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/App.kt index 60f79c988..59b4706f4 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/App.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/App.kt @@ -148,12 +148,17 @@ class App : Application() { } private fun setExceptionHandler() { + val exceptionHandler = Thread.getDefaultUncaughtExceptionHandler() + if (exceptionHandler is TopExceptionHandler) { + return + } Thread.setDefaultUncaughtExceptionHandler( TopExceptionHandler( getSharedPreferences( SharedPreferencesModule.APP_PREFERENCES_NAME, Context.MODE_PRIVATE - ) + ), + exceptionHandler ) ) } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/MainActivity.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/MainActivity.java index a23747594..a4d7c32fb 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/MainActivity.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/MainActivity.java @@ -101,7 +101,6 @@ import pan.alexander.tordnscrypt.utils.enums.OperationMode; import pan.alexander.tordnscrypt.vpn.service.ServiceVPNHelper; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; import static pan.alexander.tordnscrypt.assistance.AccelerateDevelop.accelerated; import static pan.alexander.tordnscrypt.utils.Utils.isInterfaceLocked; import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; @@ -235,7 +234,7 @@ public void onResume() { registerBroadcastReceiver(); - if (appVersion.equals("gp")) { + if (pathVars.get().getAppVersion().equals("gp")) { accelerateDevelop = new AccelerateDevelop(this); accelerateDevelop.initBilling(); } @@ -274,7 +273,7 @@ public void onAttachFragment(@NonNull Fragment fragment) { private void setDayNightTheme() { try { - ThemeUtils.setDayNightTheme(this); + ThemeUtils.setDayNightTheme(this, pathVars.get()); } catch (Exception e) { loge("MainActivity setDayNightTheme", e); } @@ -282,7 +281,8 @@ private void setDayNightTheme() { private void checkUpdates() { - if (appVersion.equals("gp") || appVersion.equals("fd")) { + if (pathVars.get().getAppVersion().equals("gp") + || pathVars.get().getAppVersion().equals("fd")) { return; } @@ -841,7 +841,7 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) { Intent intent = new Intent(this, HelpActivity.class); startActivity(intent); } else if (id == R.id.nav_Donate) { - if (appVersion.startsWith("g")) { + if (pathVars.get().getAppVersion().startsWith("g")) { if (accelerateDevelop != null && !accelerated) { accelerateDevelop.launchBilling(AccelerateDevelop.mSkuId); } @@ -940,7 +940,9 @@ public void changeDrawerWithVersionAndDestination(NavigationView navigationView) } MenuItem item = navigationView.getMenu().findItem(R.id.nav_Donate); - if ((appVersion.startsWith("g") && accelerated) || appVersion.startsWith("p") || appVersion.startsWith("f")) { + if ((pathVars.get().getAppVersion().startsWith("g") && accelerated) + || pathVars.get().getAppVersion().startsWith("p") + || pathVars.get().getAppVersion().startsWith("f")) { if (item != null) { item.setVisible(false); } @@ -948,14 +950,14 @@ public void changeDrawerWithVersionAndDestination(NavigationView navigationView) if (item != null) { item.setVisible(true); - if (appVersion.startsWith("g")) { + if (pathVars.get().getAppVersion().startsWith("g")) { item.setTitle(R.string.premium); } } } item = navigationView.getMenu().findItem(R.id.nav_Code); - if (appVersion.startsWith("l")) { + if (pathVars.get().getAppVersion().startsWith("l")) { if (item != null) { item.setVisible(true); } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/TopFragment.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/TopFragment.java index 4a7f22dce..56f61a4c9 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/TopFragment.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/TopFragment.java @@ -37,6 +37,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; +import androidx.annotation.UiThread; +import androidx.annotation.WorkerThread; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; @@ -55,12 +57,11 @@ import dagger.Lazy; import pan.alexander.tordnscrypt.dialogs.AgreementDialog; import pan.alexander.tordnscrypt.dialogs.AskAccelerateDevelop; -import pan.alexander.tordnscrypt.dialogs.AskForceClose; +import pan.alexander.tordnscrypt.dialogs.AskRestoreDefaultsDialog; import pan.alexander.tordnscrypt.dialogs.NewUpdateDialogFragment; import pan.alexander.tordnscrypt.dialogs.NotificationDialogFragment; import pan.alexander.tordnscrypt.dialogs.NotificationHelper; import pan.alexander.tordnscrypt.dialogs.SendCrashReport; -import pan.alexander.tordnscrypt.dialogs.UpdateModulesDialogFragment; import pan.alexander.tordnscrypt.dialogs.progressDialogs.CheckUpdatesDialog; import pan.alexander.tordnscrypt.domain.connection_checker.ConnectionCheckerInteractor; import pan.alexander.tordnscrypt.domain.preferences.PreferenceRepository; @@ -73,6 +74,7 @@ import pan.alexander.tordnscrypt.settings.PathVars; import pan.alexander.tordnscrypt.update.UpdateCheck; import pan.alexander.tordnscrypt.update.UpdateService; +import pan.alexander.tordnscrypt.utils.enums.ModuleName; import pan.alexander.tordnscrypt.utils.executors.CachedExecutor; import pan.alexander.tordnscrypt.dialogs.Registration; import pan.alexander.tordnscrypt.utils.Utils; @@ -83,8 +85,10 @@ import pan.alexander.tordnscrypt.utils.notification.NotificationPermissionManager; import static pan.alexander.tordnscrypt.assistance.AccelerateDevelop.accelerated; +import static pan.alexander.tordnscrypt.dialogs.AskRestoreDefaultsDialog.MODULE_NAME_ARG; import static pan.alexander.tordnscrypt.utils.Utils.shortenTooLongConjureLog; import static pan.alexander.tordnscrypt.utils.Utils.shortenTooLongSnowflakeLog; +import static pan.alexander.tordnscrypt.utils.Utils.shortenTooLongWebTunnelLog; import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; import static pan.alexander.tordnscrypt.utils.logger.Logger.logi; import static pan.alexander.tordnscrypt.utils.logger.Logger.logw; @@ -108,28 +112,20 @@ public class TopFragment extends Fragment { - public static String DNSCryptVersion = "2.0.36"; - public static String TorVersion = "4.2.5"; - public static String ITPDVersion = "2.29.0"; - - public static String appProcVersion = "armv7a"; - public static String appVersion = "lite"; + public volatile static String DNSCryptVersion = ""; + public volatile static String TorVersion = ""; + public volatile static String ITPDVersion = ""; static String verSU = ""; static String verBB = ""; public static boolean debug = false; - public static String TOP_BROADCAST = "pan.alexander.tordnscrypt.action.TOP_BROADCAST"; - public static String wrongSign; - public static String appSign; + public static final String TOP_BROADCAST = "pan.alexander.tordnscrypt.action.TOP_BROADCAST"; private final ModulesStatus modulesStatus = ModulesStatus.getInstance(); private boolean rootIsAvailable = false; private boolean rootIsAvailableSaved = false; - private static String suVersion = ""; - private static List suResult = null; - private static List bbResult = null; @Inject public Lazy preferenceRepository; @@ -145,6 +141,10 @@ public class TopFragment extends Fragment { public Lazy notificationPermissionManager; @Inject public ViewModelProvider.Factory viewModelFactory; + @Inject + public Lazy verifierLazy; + @Inject + public Lazy askRestoreDefaultsDialog; private TopFragmentViewModel viewModel; @@ -152,13 +152,13 @@ public class TopFragment extends Fragment { private boolean runModulesWithRoot = false; public CheckUpdatesDialog checkUpdatesDialog; - Future updateCheckTask; + volatile Future updateCheckTask; private ScheduledFuture scheduledFuture; private BroadcastReceiver br; private OnActivityChangeListener onActivityChangeListener; - private Handler handler; + private volatile Handler handler; private static volatile ScheduledExecutorService timer; @@ -192,9 +192,6 @@ public void onCreate(Bundle savedInstanceState) { viewModel = new ViewModelProvider(this, viewModelFactory).get(TopFragmentViewModel.class); - appVersion = getString(R.string.appVersion); - appProcVersion = getString(R.string.appProcVersion); - Context context = getActivity(); if (context != null) { @@ -215,7 +212,8 @@ public void onCreate(Bundle savedInstanceState) { ModulesAux.switchModes(rootIsAvailable, runModulesWithRoot, mode); } - if (PathVars.isModulesInstalled(preferences) && appVersion.endsWith("p")) { + if (PathVars.isModulesInstalled(preferences) + && pathVars.get().getAppVersion().endsWith("p")) { checkAgreement(context); } @@ -238,10 +236,6 @@ public void onStart() { handler = new Handler(looper); } - if (!viewModel.getRootCheckResultSuccess()) { - viewModel.checkRootAvailable(); - } - if (Build.VERSION.SDK_INT >= 33 && activity != null && !preferenceRepository.get().getBoolPreference(NOTIFICATIONS_ARE_BLOCKED)) { @@ -274,15 +268,32 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - if (savedInstanceState == null - || !PathVars.isModulesInstalled(preferenceRepository.get()) - || modulesStatus.getDnsCryptState() == ModuleState.UNDEFINED - || modulesStatus.getTorState() == ModuleState.UNDEFINED - || modulesStatus.getItpdState() == ModuleState.UNDEFINED) { + if (savedInstanceState == null || isInitTasksRequired() || isRootCheckRequired()) { + checkRootAvailable(); observeRootState(); } } + private boolean isInitTasksRequired() { + return !PathVars.isModulesInstalled(preferenceRepository.get()) + || DNSCryptVersion.isEmpty() + || TorVersion.isEmpty() + || ITPDVersion.isEmpty() + || modulesStatus.getDnsCryptState() == ModuleState.UNDEFINED + || modulesStatus.getTorState() == ModuleState.UNDEFINED + || modulesStatus.getItpdState() == ModuleState.UNDEFINED + || rootIsAvailable != rootIsAvailableSaved + || mode == UNDEFINED; + } + + private boolean isRootCheckRequired() { + return !viewModel.getRootCheckResultSuccess(); + } + + private void checkRootAvailable() { + viewModel.checkRootAvailable(); + } + @Override public void onStop() { super.onStop(); @@ -335,16 +346,20 @@ private void observeRootState() { viewModel.getRootStateLiveData().observe(getViewLifecycleOwner(), rootState -> { if (rootState instanceof RootState.RootAvailable) { - suVersion = ((RootState.RootAvailable) rootState).getSuVersion(); - suResult = ((RootState.RootAvailable) rootState).getSuResult(); - bbResult = ((RootState.RootAvailable) rootState).getBbResult(); + String suVersion = ((RootState.RootAvailable) rootState).getSuVersion(); + List suResult = ((RootState.RootAvailable) rootState).getSuResult(); + List bbResult = ((RootState.RootAvailable) rootState).getBbResult(); + + setSUInfo(suResult, suVersion); + setBBinfo(bbResult); } - performBackgroundWorkAfterRootChecking(); + performInitTasksBackgroundWork(); }); } - private void performBackgroundWorkAfterRootChecking() { + @WorkerThread + private void performInitTasksBackgroundWork() { cachedExecutor.submit(() -> { Activity activity = getActivity(); @@ -361,13 +376,14 @@ private void performBackgroundWorkAfterRootChecking() { shortenTooLongSnowflakeLog(context, preferences, pathVars.get()); shortenTooLongConjureLog(context, preferences, pathVars.get()); + shortenTooLongWebTunnelLog(context, preferences, pathVars.get()); checkModulesStoppedBySystem(activity); checkIntegrity(activity); if (handler != null) { - handler.post(this::performMainThreadWorkAfterRootChecking); + handler.post(this::performInitTasksMainThreadWork); } }); @@ -395,11 +411,11 @@ && haveModulesSavedStateRunning() private void checkIntegrity(Activity activity) { try { - Verifier verifier = new Verifier(activity); - appSign = verifier.getApkSignatureZip(); + Verifier verifier = verifierLazy.get(); + String appSign = verifier.getAppSignature(); String appSignAlt = verifier.getApkSignature(); verifier.encryptStr(TOP_BROADCAST, appSign, appSignAlt); - wrongSign = getString(R.string.encoded).trim(); + String wrongSign = verifier.getWrongSign(); if (!verifier.decryptStr(wrongSign, appSign, appSignAlt).equals(TOP_BROADCAST)) { if (isAdded() && !isStateSaved()) { NotificationHelper notificationHelper = NotificationHelper.setHelperMessage( @@ -422,7 +438,8 @@ private void checkIntegrity(Activity activity) { } } - private void performMainThreadWorkAfterRootChecking() { + @UiThread + private void performInitTasksMainThreadWork() { MainActivity activity = (MainActivity) getActivity(); @@ -432,9 +449,6 @@ private void performMainThreadWorkAfterRootChecking() { try { - setSUInfo(suResult, suVersion); - setBBinfo(bbResult); - if (rootIsAvailable != rootIsAvailableSaved || mode == UNDEFINED) { ModulesAux.switchModes(rootIsAvailable, runModulesWithRoot, mode); @@ -445,11 +459,6 @@ private void performMainThreadWorkAfterRootChecking() { actionModulesNotInstalled(activity); } else { - //Currently not used - //if (topFragment.coreUpdateReady(activity)) { - // return; - //} - refreshModulesVersions(activity); stopInstallationTimer(); @@ -543,7 +552,7 @@ private void showDonDialog(Activity activity) { return; } - if (appVersion.endsWith("e")) { + if (pathVars.get().getAppVersion().endsWith("e")) { if (handler != null) { handler.postDelayed(() -> { if (isAdded() && !isStateSaved()) { @@ -552,7 +561,7 @@ private void showDonDialog(Activity activity) { } }, 5000); } - } else if (appVersion.endsWith("p") && isAdded()) { + } else if (pathVars.get().getAppVersion().endsWith("p") && isAdded()) { if (!preferenceRepository.get().getBoolPreference("Agreement")) { return; @@ -584,37 +593,6 @@ private void refreshModulesVersions(Context context) { } } - private boolean coreUpdateReady(Context context) { - - if (context == null) { - return false; - } - - final PreferenceRepository preferences = preferenceRepository.get(); - - String currentDNSCryptVersionStr = preferences.getStringPreference("DNSCryptVersion"); - String currentTorVersionStr = preferences.getStringPreference("TorVersion"); - String currentITPDVersionStr = preferences.getStringPreference("ITPDVersion"); - if (!(currentDNSCryptVersionStr.isEmpty() && currentTorVersionStr.isEmpty() && currentITPDVersionStr.isEmpty())) { - int currentDNSCryptVersion = Integer.parseInt(currentDNSCryptVersionStr.replaceAll("\\D+", "")); - int currentTorVersion = Integer.parseInt(currentTorVersionStr.replaceAll("\\D+", "")); - int currentITPDVersion = Integer.parseInt(currentITPDVersionStr.replaceAll("\\D+", "")); - - if (((currentDNSCryptVersion < Integer.parseInt(DNSCryptVersion.replaceAll("\\D+", "")) - || currentTorVersion < Integer.parseInt(TorVersion.replaceAll("\\D+", "")) - || currentITPDVersion < Integer.parseInt(ITPDVersion.replaceAll("\\D+", ""))) - && !preferences.getBoolPreference("UpdateNotAllowed"))) { - if (isAdded() && !isStateSaved()) { - DialogFragment updateCore = UpdateModulesDialogFragment.getInstance(); - updateCore.show(getParentFragmentManager(), "UpdateModulesDialogFragment"); - } - return true; - } - } - - return false; - } - private void actionModulesNotInstalled(Context context) { PreferenceManager.setDefaultValues(context, R.xml.preferences_common, true); @@ -639,50 +617,57 @@ private void actionModulesNotInstalled(Context context) { } private void setSUInfo(List fSuResult, String fSuVersion) { + try { + final PreferenceRepository preferences = preferenceRepository.get(); - final PreferenceRepository preferences = preferenceRepository.get(); - - if (fSuResult != null && fSuResult.size() != 0 - && fSuResult.toString().toLowerCase().contains("uid=0") - && fSuResult.toString().toLowerCase().contains("gid=0")) { + if (fSuResult != null && fSuResult.size() != 0 + && fSuResult.toString().toLowerCase().contains("uid=0") + && fSuResult.toString().toLowerCase().contains("gid=0")) { - rootIsAvailable = true; + rootIsAvailable = true; - preferences.setBoolPreference(ROOT_IS_AVAILABLE, true); + preferences.setBoolPreference(ROOT_IS_AVAILABLE, true); - if (fSuVersion != null && fSuVersion.length() != 0) { - verSU = "Root is available." + (char) 10 + - "Super User Version: " + fSuVersion + (char) 10 + - fSuResult.get(0); + if (fSuVersion != null && fSuVersion.length() != 0) { + verSU = "Root is available." + (char) 10 + + "Super User Version: " + fSuVersion + (char) 10 + + fSuResult.get(0); + } else { + verSU = "Root is available." + (char) 10 + + "Super User Version: Unknown" + + fSuResult.get(0); + } + logi(verSU); } else { - verSU = "Root is available." + (char) 10 + - "Super User Version: Unknown" + - fSuResult.get(0); + rootIsAvailable = false; + preferences.setBoolPreference(ROOT_IS_AVAILABLE, false); } - logi(verSU); - } else { - rootIsAvailable = false; - preferences.setBoolPreference(ROOT_IS_AVAILABLE, false); + } catch (Exception e) { + loge("TopFragment setSUInfo", e); } } private void setBBinfo(List fBbResult) { - final PreferenceRepository preferences = preferenceRepository.get(); + try { + final PreferenceRepository preferences = preferenceRepository.get(); - if (fBbResult != null && fBbResult.size() != 0) { - verBB = fBbResult.get(0); - } else { - preferences.setBoolPreference("bbOK", false); - return; - } + if (fBbResult != null && fBbResult.size() != 0) { + verBB = fBbResult.get(0); + } else { + preferences.setBoolPreference("bbOK", false); + return; + } - if (verBB.toLowerCase().contains("not found")) { - preferences.setBoolPreference("bbOK", false); - } else { - preferences.setBoolPreference("bbOK", true); + if (verBB.toLowerCase().contains("not found")) { + preferences.setBoolPreference("bbOK", false); + } else { + preferences.setBoolPreference("bbOK", true); - logi("BusyBox is available " + verBB); + logi("BusyBox is available " + verBB); + } + } catch (Exception e) { + loge("TopFragment setBBinfo", e); } } @@ -731,7 +716,7 @@ private boolean checkCrashReport(Activity activity) { return true; } - if (appVersion.endsWith("p")) { + if (pathVars.get().getAppVersion().endsWith("p")) { return false; } @@ -760,7 +745,9 @@ public void checkUpdates(Context context) { } boolean autoUpdate = spref.getBoolean("pref_fast_auto_update", true) - && !appVersion.startsWith("l") && !appVersion.endsWith("p") && !appVersion.startsWith("f"); + && !pathVars.get().getAppVersion().startsWith("l") + && !pathVars.get().getAppVersion().endsWith("p") + && !pathVars.get().getAppVersion().startsWith("f"); if (autoUpdate) { boolean throughTorUpdate = spref.getBoolean("pref_fast through_tor_update", false); @@ -787,7 +774,8 @@ public void checkUpdates(Context context) { public void checkNewVer(Context context, boolean showProgressDialog) { - if (appVersion.endsWith("p") || appVersion.startsWith("f")) { + if (pathVars.get().getAppVersion().endsWith("p") + || pathVars.get().getAppVersion().startsWith("f")) { return; } @@ -801,7 +789,7 @@ public void checkNewVer(Context context, boolean showProgressDialog) { try { UpdateCheck updateCheck = new UpdateCheck(this); - updateCheckTask = updateCheck.requestUpdateData("https://invizible.net", appSign); + updateCheckTask = updateCheck.requestUpdateData("https://invizible.net"); if (showProgressDialog && !isStateSaved()) { checkUpdatesDialog = new CheckUpdatesDialog(); checkUpdatesDialog.setCheckUpdatesTask(updateCheckTask); @@ -820,6 +808,11 @@ public void checkNewVer(Context context, boolean showProgressDialog) { } public void downloadUpdate(String fileName, String updateStr, String message, String hash) { + + if (handler == null) { + return; + } + handler.post(() -> { Context context = getActivity(); if (context == null) @@ -855,7 +848,8 @@ private void cancelCheckUpdatesTask() { public void showUpdateResultMessage(Activity activity) { - if (appVersion.equals("gp") || appVersion.equals("fd")) { + if (pathVars.get().getAppVersion().equals("gp") + || pathVars.get().getAppVersion().equals("fd")) { return; } @@ -916,9 +910,13 @@ private void receiverOnReceive(Intent intent) { if (intent.getAction().equals(UpdateService.UPDATE_RESULT)) { showUpdateResultMessage(activity); refreshModulesVersions(activity); - } else if (intent.getAction().equals(ModulesStarterHelper.ASK_FORCE_CLOSE)) { - DialogFragment dialogFragment = AskForceClose.getInstance(intent.getStringExtra(ModulesStarterHelper.MODULE_NAME)); - dialogFragment.show(getParentFragmentManager(), "AskForceClose"); + } else if (intent.getAction().equals(ModulesStarterHelper.ASK_RESTORE_DEFAULTS)) { + DialogFragment dialog = askRestoreDefaultsDialog.get(); + Bundle args = new Bundle(); + ModuleName name = (ModuleName) intent.getSerializableExtra(ModulesStarterHelper.MODULE_NAME); + args.putSerializable(MODULE_NAME_ARG, name); + dialog.setArguments(args); + dialog.show(getChildFragmentManager(), "AskRestoreDefaults"); } } @@ -933,7 +931,7 @@ private boolean isBroadcastMatch(Intent intent) { return false; } - if (!action.equals(UpdateService.UPDATE_RESULT) && !action.equals(ModulesStarterHelper.ASK_FORCE_CLOSE)) { + if (!action.equals(UpdateService.UPDATE_RESULT) && !action.equals(ModulesStarterHelper.ASK_RESTORE_DEFAULTS)) { return false; } @@ -954,7 +952,7 @@ public void onReceive(Context context, Intent intent) { }; IntentFilter intentFilterUpdate = new IntentFilter(UpdateService.UPDATE_RESULT); - IntentFilter intentFilterForceClose = new IntentFilter(ModulesStarterHelper.ASK_FORCE_CLOSE); + IntentFilter intentFilterForceClose = new IntentFilter(ModulesStarterHelper.ASK_RESTORE_DEFAULTS); LocalBroadcastManager.getInstance(context).registerReceiver(br, intentFilterUpdate); LocalBroadcastManager.getInstance(context).registerReceiver(br, intentFilterForceClose); } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/TopFragmentViewModel.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/TopFragmentViewModel.kt index aee7b4907..fa1eb53f8 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/TopFragmentViewModel.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/TopFragmentViewModel.kt @@ -29,7 +29,9 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeout +import pan.alexander.tordnscrypt.backup.ResetModuleHelper import pan.alexander.tordnscrypt.di.CoroutinesModule +import pan.alexander.tordnscrypt.utils.enums.ModuleName import pan.alexander.tordnscrypt.utils.logger.Logger.loge import javax.inject.Inject import javax.inject.Named @@ -38,12 +40,14 @@ private const val CHECK_ROOT_TIMEOUT_SEC = 5 class TopFragmentViewModel @Inject constructor( @Named(CoroutinesModule.DISPATCHER_IO) - private val dispatcherIo: CoroutineDispatcher + private val dispatcherIo: CoroutineDispatcher, + private val resetModuleHelper: dagger.Lazy ): ViewModel() { private val rootStateMutableLiveData = MutableLiveData() - val rootStateLiveData: LiveData get() = rootStateMutableLiveData.distinctUntilChanged() + val rootStateLiveData: LiveData get() = rootStateMutableLiveData + @Volatile var rootCheckResultSuccess = false private var checkRootJob: Job? = null @@ -100,4 +104,14 @@ class TopFragmentViewModel @Inject constructor( rootStateMutableLiveData.postValue(RootState.RootNotAvailable) } } + + fun resetModuleSettings(moduleName: ModuleName) { + viewModelScope.launch(dispatcherIo) { + try { + resetModuleHelper.get().resetModuleSettings(moduleName) + } catch (e: Exception) { + loge("TopFragmentViewModel resetModuleSettings", e) + } + } + } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/arp/ArpScannerLoop.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/arp/ArpScannerLoop.kt index e689783e3..d3fd6ff74 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/arp/ArpScannerLoop.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/arp/ArpScannerLoop.kt @@ -109,7 +109,7 @@ class ArpScannerLoop @Inject constructor( if (!ArpScanner.dhcpGatewayAttackDetected) { arpWarningNotification.send( - R.string.ask_force_close_title, + R.string.reset_settings_title, R.string.notification_rogue_dhcp, DHCP_NOTIFICATION_ID ) @@ -154,7 +154,7 @@ class ArpScannerLoop @Inject constructor( if (!ArpScanner.arpAttackDetected) { arpWarningNotification.send( - R.string.ask_force_close_title, + R.string.reset_settings_title, R.string.notification_arp_spoofing, ARP_NOTIFICATION_ID ) diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/backup/ResetModuleHelper.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/backup/ResetModuleHelper.kt new file mode 100644 index 000000000..18549d6c3 --- /dev/null +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/backup/ResetModuleHelper.kt @@ -0,0 +1,146 @@ +/* + This file is part of InviZible Pro. + + InviZible Pro is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InviZible Pro is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with InviZible Pro. If not, see . + + Copyright 2019-2023 by Garmatin Oleksandr invizible.soft@gmail.com + */ + +package pan.alexander.tordnscrypt.backup + +import android.annotation.SuppressLint +import android.content.Context +import androidx.annotation.WorkerThread +import pan.alexander.tordnscrypt.R +import pan.alexander.tordnscrypt.installer.ChmodCommand +import pan.alexander.tordnscrypt.installer.DNSCryptExtractCommand +import pan.alexander.tordnscrypt.installer.ITPDExtractCommand +import pan.alexander.tordnscrypt.installer.InstallerHelper +import pan.alexander.tordnscrypt.installer.TorExtractCommand +import pan.alexander.tordnscrypt.settings.PathVars +import pan.alexander.tordnscrypt.utils.enums.ModuleName +import pan.alexander.tordnscrypt.utils.filemanager.FileManager +import pan.alexander.tordnscrypt.utils.logger.Logger.loge +import pan.alexander.tordnscrypt.utils.logger.Logger.logw +import javax.inject.Inject + +class ResetModuleHelper @Inject constructor( + private val context: Context, + pathVars: PathVars, + private val installerHelper: InstallerHelper +) { + + private val dataDir = pathVars.appDataDir + + @WorkerThread + fun resetModuleSettings(moduleName: ModuleName) = try { + logw("Resetting ${moduleName.moduleName} settings") + + cleanModuleFolder(moduleName) + extractModuleData(moduleName) + correctAppDir(moduleName) + + logw("Reset ${moduleName.moduleName} settings success") + } catch (e: Exception) { + loge("Reset ${moduleName.moduleName} settings error", e) + } + + private fun cleanModuleFolder(moduleName: ModuleName) { + when (moduleName) { + ModuleName.DNSCRYPT_MODULE -> { + FileManager.deleteDirSynchronous( + context, + "$dataDir/app_data/dnscrypt-proxy" + ) + } + + ModuleName.TOR_MODULE -> { + FileManager.deleteDirSynchronous( + context, + "$dataDir/tor_data" + ) + FileManager.deleteDirSynchronous( + context, + "$dataDir/app_data/tor" + ) + } + + ModuleName.ITPD_MODULE -> { + FileManager.deleteDirSynchronous( + context, + "$dataDir/i2pd_data" + ) + FileManager.deleteDirSynchronous( + context, + "$dataDir/app_data/i2pd" + ) + } + } + } + + private fun extractModuleData(moduleName: ModuleName) { + when (moduleName) { + ModuleName.DNSCRYPT_MODULE -> { + DNSCryptExtractCommand(context, dataDir).execute() + ChmodCommand.dirChmod("$dataDir/app_data/dnscrypt-proxy", false) + } + + ModuleName.TOR_MODULE -> { + TorExtractCommand(context, dataDir).execute() + ChmodCommand.dirChmod("$dataDir/app_data/tor", false) + } + + ModuleName.ITPD_MODULE -> { + ITPDExtractCommand(context, dataDir).execute() + ChmodCommand.dirChmod("$dataDir/app_data/i2pd", false) + } + } + + + } + + private fun correctAppDir(moduleName: ModuleName) { + val path = when (moduleName) { + ModuleName.DNSCRYPT_MODULE -> "$dataDir/app_data/dnscrypt-proxy/dnscrypt-proxy.toml" + ModuleName.TOR_MODULE -> "$dataDir/app_data/tor/tor.conf" + ModuleName.ITPD_MODULE -> "$dataDir/app_data/i2pd/i2pd.conf" + + } + updateAppDir(path) + } + + @SuppressLint("SdCardPath") + private fun updateAppDir(path: String) { + var lines = FileManager.readTextFileSynchronous(context, path) + var line: String + for (i in lines.indices) { + line = lines[i] + if (line.contains("/data/user/0/pan.alexander.tordnscrypt")) { + line = line.replace( + "/data/user/0/pan.alexander.tordnscrypt.*?/".toRegex(), + "$dataDir/" + ) + lines[i] = line + } + } + + if (context.isGpVersion() && path.contains("dnscrypt-proxy.toml")) { + lines = installerHelper.prepareDNSCryptForGP(lines) + } + + FileManager.writeTextFileSynchronous(context, path, lines) + } + + private fun Context.isGpVersion() = getString(R.string.package_name).contains(".gp") +} diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/backup/RestoreHelper.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/backup/RestoreHelper.java index baa1fcf2e..73ed702c6 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/backup/RestoreHelper.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/backup/RestoreHelper.java @@ -153,7 +153,7 @@ void restoreAll(InputStream inputStream, boolean logsDirAccessible) { refreshModulesStatus(activity); - Patch patch = new Patch(activity); + Patch patch = new Patch(activity, pathVars.get()); patch.checkPatches(true); } catch (Exception e) { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/crash_handling/TopExceptionHandler.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/crash_handling/TopExceptionHandler.kt index 57691a907..3374e402c 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/crash_handling/TopExceptionHandler.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/crash_handling/TopExceptionHandler.kt @@ -22,13 +22,13 @@ package pan.alexander.tordnscrypt.crash_handling import android.content.SharedPreferences import android.util.Log import pan.alexander.tordnscrypt.utils.root.RootExecService.LOG_TAG +import kotlin.system.exitProcess class TopExceptionHandler( - private val sharedPreferences: SharedPreferences + private val sharedPreferences: SharedPreferences, + private val defaultExceptionHandler: Thread.UncaughtExceptionHandler? ) : Thread.UncaughtExceptionHandler { - private val defaultUEH = Thread.getDefaultUncaughtExceptionHandler() - override fun uncaughtException(t: Thread, e: Throwable) { var arr = e.stackTrace @@ -56,7 +56,7 @@ class TopExceptionHandler( saveReport(report) - defaultUEH?.uncaughtException(t, e) + defaultExceptionHandler?.uncaughtException(t, e) ?: exitProcess(2) } private fun saveReport(report: String) { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/data/bridges/DefaultVanillaBridgeDataSourceImpl.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/data/bridges/DefaultVanillaBridgeDataSourceImpl.kt index 93b94bbf5..2c253954a 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/data/bridges/DefaultVanillaBridgeDataSourceImpl.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/data/bridges/DefaultVanillaBridgeDataSourceImpl.kt @@ -30,7 +30,6 @@ class DefaultVanillaBridgeDataSourceImpl @Inject constructor( private val httpsConnectionManager: HttpsConnectionManager ) : DefaultVanillaBridgeDataSource { - @Suppress("BlockingMethodInNonBlockingContext") override suspend fun getRelaysWithFingerprintAndAddress(): List = httpsConnectionManager.apply { readTimeoutSec = READ_TIMEOUT_SEC connectTimeoutSec = CONNECT_TIMEOUT_SEC diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/data/log_reader/OwnFileReader.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/data/log_reader/OwnFileReader.java index 8d977640d..214885f83 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/data/log_reader/OwnFileReader.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/data/log_reader/OwnFileReader.java @@ -96,6 +96,10 @@ public List readLastLines() { lines.remove(0); fileIsTooLong = true; } + + if (Thread.currentThread().isInterrupted()) { + return lines; + } } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/di/AppComponent.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/di/AppComponent.kt index 02d66676e..545e5f557 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/di/AppComponent.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/di/AppComponent.kt @@ -122,7 +122,6 @@ interface AppComponent { fun inject(receiver: HelpActivityReceiver) fun inject(receiver: IptablesReceiver) fun inject(dialogFragment: RequestIgnoreBatteryOptimizationDialog) - fun inject(dialogFragment: AskForceClose) fun inject(dialogFragment: SendCrashReport) fun inject(usageStatistic: UsageStatistic) fun inject(modulesKiller: ModulesKiller) diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/di/CoroutinesModule.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/di/CoroutinesModule.kt index afce98123..0d10328ae 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/di/CoroutinesModule.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/di/CoroutinesModule.kt @@ -51,8 +51,7 @@ class CoroutinesModule { @Provides @Named(DISPATCHER_IO) - fun provideDispatcherIo(cachedExecutor: CachedExecutor): CoroutineDispatcher = - cachedExecutor.executorService.asCoroutineDispatcher() + fun provideDispatcherIo(): CoroutineDispatcher = Dispatchers.IO @Provides @Named(DISPATCHER_COMPUTATION) diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/AskForceClose.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/AskForceClose.java deleted file mode 100644 index 94832ed0f..000000000 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/AskForceClose.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - This file is part of InviZible Pro. - - InviZible Pro is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - InviZible Pro is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with InviZible Pro. If not, see . - - Copyright 2019-2023 by Garmatin Oleksandr invizible.soft@gmail.com - */ - -package pan.alexander.tordnscrypt.dialogs; - -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; - -import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; -import androidx.fragment.app.DialogFragment; - -import dagger.Lazy; -import pan.alexander.tordnscrypt.App; -import pan.alexander.tordnscrypt.R; -import pan.alexander.tordnscrypt.modules.ModulesAux; -import pan.alexander.tordnscrypt.modules.ModulesKiller; -import pan.alexander.tordnscrypt.modules.ModulesStatus; -import pan.alexander.tordnscrypt.settings.PathVars; -import pan.alexander.tordnscrypt.utils.executors.CachedExecutor; -import pan.alexander.tordnscrypt.utils.filemanager.FileManager; - -import static pan.alexander.tordnscrypt.utils.root.RootExecService.LOG_TAG; -import static pan.alexander.tordnscrypt.utils.enums.ModuleState.STOPPED; - -import javax.inject.Inject; - -public class AskForceClose extends ExtendedDialogFragment { - - @Inject - public Lazy pathVars; - @Inject - public CachedExecutor cachedExecutor; - - private static String module; - private final ModulesStatus modulesStatus = ModulesStatus.getInstance(); - - public static DialogFragment getInstance(String module) { - AskForceClose.module = module; - return new AskForceClose(); - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - App.getInstance().getDaggerComponent().inject(this); - super.onCreate(savedInstanceState); - } - - @Override - public AlertDialog.Builder assignBuilder() { - if (getActivity() == null) { - return null; - } - - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.CustomAlertDialogTheme); - builder.setMessage(String.format(getString(R.string.ask_force_close_text), module, module)) - .setTitle(getString(R.string.ask_force_close_title)) - .setPositiveButton(R.string.ask_force_close_btn, (dialog, which) -> { - if (getActivity() != null) { - final Context context = getActivity(); - Handler handler = new Handler(Looper.getMainLooper()); - handler.postDelayed(() -> { - if (context != null) { - ModulesAux.stopModulesService(context); - } - }, 1000); - - if (modulesStatus.isRootAvailable()) { - forceStopModulesWithRootMethod(getActivity(), handler); - } else { - forceStopModulesWithService(getActivity(), handler); - } - } - - }) - .setNegativeButton(R.string.cancel, (dialog, id) -> dismiss()); - - return builder; - } - - private void forceStopModulesWithService(Context context, Handler handler) { - - if (modulesStatus.isUseModulesWithRoot()) { - return; - } - - saveModulesAreStopped(); - - Log.e(LOG_TAG, "FORCE CLOSE ALL NO ROOT METHOD"); - - modulesStatus.setUseModulesWithRoot(true); - modulesStatus.setDnsCryptState(STOPPED); - modulesStatus.setTorState(STOPPED); - modulesStatus.setItpdState(STOPPED); - - cleanModulesFolders(context); - - handler.postDelayed(() -> android.os.Process.killProcess(android.os.Process.myPid()), 3000); - } - - private void forceStopModulesWithRootMethod(Context context, Handler handler) { - - saveModulesAreStopped(); - - Log.e(LOG_TAG, "FORCE CLOSE ALL ROOT METHOD"); - - boolean useModulesWithRoot = modulesStatus.isUseModulesWithRoot(); - - ModulesKiller.forceCloseApp(pathVars.get()); - - cleanModulesFolders(context); - - if (!useModulesWithRoot) { - handler.postDelayed(() -> android.os.Process.killProcess(android.os.Process.myPid()), 3000); - } - } - - private void cleanModulesFolders(Context context) { - - String appDataDir = pathVars.get().getAppDataDir(); - - cachedExecutor.submit(() -> { - FileManager.deleteFileSynchronous(context, appDataDir - + "/app_data/dnscrypt-proxy", "public-resolvers.md"); - FileManager.deleteFileSynchronous(context, appDataDir - + "/app_data/dnscrypt-proxy", "public-resolvers.md.minisig"); - FileManager.deleteFileSynchronous(context, appDataDir - + "/app_data/dnscrypt-proxy", "relays.md"); - FileManager.deleteFileSynchronous(context, appDataDir - + "/app_data/dnscrypt-proxy", "relays.md.minisig"); - FileManager.deleteDirSynchronous(context, appDataDir + "/tor_data"); - FileManager.deleteDirSynchronous(context, appDataDir + "/i2pd_data"); - }); - } - - private void saveModulesAreStopped() { - ModulesAux.saveDNSCryptStateRunning(false); - ModulesAux.saveTorStateRunning(false); - ModulesAux.saveITPDStateRunning(false); - } -} diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/AskRestoreDefaultsDialog.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/AskRestoreDefaultsDialog.java new file mode 100644 index 000000000..954fb241d --- /dev/null +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/AskRestoreDefaultsDialog.java @@ -0,0 +1,88 @@ +/* + This file is part of InviZible Pro. + + InviZible Pro is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InviZible Pro is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with InviZible Pro. If not, see . + + Copyright 2019-2023 by Garmatin Oleksandr invizible.soft@gmail.com + */ + +package pan.alexander.tordnscrypt.dialogs; + +import android.os.Bundle; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.lifecycle.ViewModelProvider; + +import javax.inject.Inject; + +import pan.alexander.tordnscrypt.R; +import pan.alexander.tordnscrypt.TopFragmentViewModel; +import pan.alexander.tordnscrypt.utils.enums.ModuleName; + +public class AskRestoreDefaultsDialog extends ExtendedDialogFragment { + + public static String MODULE_NAME_ARG = "pan.alexander.tordnscrypt.MODULE_NAME_ARG"; + + private ModuleName module; + + ViewModelProvider.Factory viewModelFactory; + TopFragmentViewModel topFragmentViewModel; + + @Inject + public AskRestoreDefaultsDialog(ViewModelProvider.Factory viewModelFactory) { + this.viewModelFactory = viewModelFactory; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + topFragmentViewModel = new ViewModelProvider( + requireParentFragment(), + viewModelFactory + ).get(TopFragmentViewModel.class); + } + + @Override + public AlertDialog.Builder assignBuilder() { + if (getActivity() == null) { + return null; + } + + Bundle arguments = getArguments(); + if (arguments != null) { + module = (ModuleName) arguments.getSerializable(MODULE_NAME_ARG); + } + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.CustomAlertDialogTheme); + builder.setMessage( + String.format( + getString(R.string.ask_reset_settings_text), + module.getModuleName(), + module.getModuleName() + ) + ) + .setTitle(getString(R.string.reset_settings_title)) + .setPositiveButton(R.string.ask_reset_settings_btn, (dialog, which) -> { + if (topFragmentViewModel != null && module != null) { + topFragmentViewModel.resetModuleSettings(module); + } + + }) + .setNegativeButton(R.string.cancel, (dialog, id) -> dismiss()); + + return builder; + } +} diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/FakeSniInputDialogFragment.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/FakeSniInputDialogFragment.kt new file mode 100644 index 000000000..40cb190b6 --- /dev/null +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/FakeSniInputDialogFragment.kt @@ -0,0 +1,68 @@ +/* + This file is part of InviZible Pro. + + InviZible Pro is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InviZible Pro is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with InviZible Pro. If not, see . + + Copyright 2019-2023 by Garmatin Oleksandr invizible.soft@gmail.com + */ + +package pan.alexander.tordnscrypt.dialogs + +import android.widget.EditText +import androidx.appcompat.app.AlertDialog +import pan.alexander.tordnscrypt.R +import pan.alexander.tordnscrypt.utils.Utils.dp2pixels +import javax.inject.Inject + +const val FAKE_SNI_ARG = "pan.alexander.tordnscrypt.dialogs.FAKE_SNI_ARG" + +class FakeSniInputDialogFragment @Inject constructor() : ExtendedDialogFragment() { + + override fun assignBuilder(): AlertDialog.Builder = + AlertDialog.Builder(requireActivity(), R.style.CustomAlertDialogTheme).apply { + + setTitle(R.string.pref_fast_fake_sni) + + val etSniInput = EditText(context).apply { + setPadding( + dp2pixels(8).toInt(), + paddingTop, + dp2pixels(8).toInt(), + paddingBottom + ) + } + + setView(etSniInput) + + arguments?.getStringArrayList(FAKE_SNI_ARG)?.let { + etSniInput.setText(it.joinToString(", ")) + } + + setPositiveButton(R.string.ok) { _, _ -> + + val sniText = etSniInput.text.toString() + + val parent = parentFragment + if (parent is SniInputListener) { + parent.setSni(sniText) + } + } + + setNegativeButton(R.string.cancel) { dialog, _ -> dialog.cancel() } + } +} + +interface SniInputListener { + fun setSni(text: String?) +} diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/SelectBridgesTransportDialogFragment.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/SelectBridgesTransportDialogFragment.kt index 4bff28e5e..93bf26847 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/SelectBridgesTransportDialogFragment.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/SelectBridgesTransportDialogFragment.kt @@ -92,6 +92,11 @@ class SelectBridgesTransportDialogFragment @Inject constructor( "obfs4", ipv6Bridges ) + R.id.rbWebTunnel -> + preferencesTorBridgesViewModel.requestTorBridgesCaptchaChallenge( + "webtunnel", + ipv6Bridges + ) } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/SendCrashReport.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/SendCrashReport.kt index 310901442..657b1bb21 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/SendCrashReport.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dialogs/SendCrashReport.kt @@ -31,6 +31,7 @@ import pan.alexander.tordnscrypt.domain.preferences.PreferenceRepository import pan.alexander.tordnscrypt.help.Utils import pan.alexander.tordnscrypt.settings.PathVars import pan.alexander.tordnscrypt.utils.executors.CachedExecutor +import pan.alexander.tordnscrypt.utils.integrity.Verifier import pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.ALWAYS_SHOW_HELP_MESSAGES import pan.alexander.tordnscrypt.utils.root.RootExecService.LOG_TAG import java.io.BufferedReader @@ -47,6 +48,8 @@ class SendCrashReport : ExtendedDialogFragment() { lateinit var pathVars: dagger.Lazy @Inject lateinit var cachedExecutor: CachedExecutor + @Inject + lateinit var verifier: dagger.Lazy override fun onCreate(savedInstanceState: Bundle?) { App.instance.daggerComponent.inject(this) @@ -72,7 +75,11 @@ class SendCrashReport : ExtendedDialogFragment() { val logsDirPath = createLogsDir(ctx) - val info = Utils.collectInfo() + val info = Utils.collectInfo( + verifier.get().appSignature, + pathVars.get().appVersion, + pathVars.get().appProcVersion + ) if (saveLogCat(logsDirPath)) { sendCrashEmail(ctx, info, File("$logsDirPath/logcat.log")) @@ -105,7 +112,7 @@ class SendCrashReport : ExtendedDialogFragment() { val cacheDir: String try { cacheDir = context.cacheDir?.canonicalPath - ?: pathVars.get().appDataDir + "/cache" + ?: (pathVars.get().appDataDir + "/cache") } catch (e: Exception) { Log.w(LOG_TAG, "SendCrashReport cannot get cache dir ${e.message} ${e.cause}") return null diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dnscrypt_fragment/DNSCryptFragmentReceiver.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dnscrypt_fragment/DNSCryptFragmentReceiver.java index 9ad43cc53..cfa79ad64 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dnscrypt_fragment/DNSCryptFragmentReceiver.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/dnscrypt_fragment/DNSCryptFragmentReceiver.java @@ -46,8 +46,6 @@ import static pan.alexander.tordnscrypt.TopFragment.DNSCryptVersion; import static pan.alexander.tordnscrypt.TopFragment.TOP_BROADCAST; -import static pan.alexander.tordnscrypt.TopFragment.appSign; -import static pan.alexander.tordnscrypt.TopFragment.wrongSign; import static pan.alexander.tordnscrypt.modules.ModulesService.DNSCRYPT_KEYWORD; import static pan.alexander.tordnscrypt.utils.root.RootCommandsMark.DNSCRYPT_RUN_FRAGMENT_MARK; import static pan.alexander.tordnscrypt.utils.root.RootExecService.LOG_TAG; @@ -65,6 +63,8 @@ public class DNSCryptFragmentReceiver extends BroadcastReceiver { public Lazy pathVars; @Inject public CachedExecutor cachedExecutor; + @Inject + public Lazy verifierLazy; private final DNSCryptFragmentView view; private final DNSCryptFragmentPresenterInterface presenter; @@ -178,9 +178,10 @@ public void onReceive(Context context, Intent intent) { return; } - Verifier verifier = new Verifier(context); + Verifier verifier = verifierLazy.get(); + String appSign = verifier.getAppSignature(); String appSignAlt = verifier.getApkSignature(); - if (!verifier.decryptStr(wrongSign, appSign, appSignAlt).equals(TOP_BROADCAST)) { + if (!verifier.decryptStr(verifier.getWrongSign(), appSign, appSignAlt).equals(TOP_BROADCAST)) { if (fragmentManager != null) { NotificationHelper notificationHelper = NotificationHelper.setHelperMessage( diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/domain/bridges/DefaultVanillaBridgeInteractor.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/domain/bridges/DefaultVanillaBridgeInteractor.kt index 15aeb4ba6..09a83873b 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/domain/bridges/DefaultVanillaBridgeInteractor.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/domain/bridges/DefaultVanillaBridgeInteractor.kt @@ -22,6 +22,8 @@ package pan.alexander.tordnscrypt.domain.bridges import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.sync.Semaphore +import kotlinx.coroutines.sync.withPermit import pan.alexander.tordnscrypt.data.bridges.RelayAddressFingerprint import pan.alexander.tordnscrypt.di.CoroutinesModule import pan.alexander.tordnscrypt.utils.logger.Logger.loge @@ -45,14 +47,18 @@ class DefaultVanillaBridgeInteractor @Inject constructor( fun observeTimeouts() = timeouts.asSharedFlow() suspend fun measureTimeouts(bridges: List) = - withContext(dispatcherIo.limitedParallelism(SIMULTANEOUS_CHECKS)) { + withContext(dispatcherIo) { + val semaphore = Semaphore(SIMULTANEOUS_CHECKS) val defers = mutableListOf>() bridges.forEach { try { + ensureActive() defers += async { - timeouts.emit( - BridgePingData(it.hashCode(), repository.getTimeout(it)) - ) + semaphore.withPermit { + timeouts.emit( + BridgePingData(it.hashCode(), repository.getTimeout(it)) + ) + } } } catch (ignored: CancellationException) { } catch (e: Exception) { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/domain/connection_records/ConnectionRecordsParser.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/domain/connection_records/ConnectionRecordsParser.kt index ea48504f8..0504a97c1 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/domain/connection_records/ConnectionRecordsParser.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/domain/connection_records/ConnectionRecordsParser.kt @@ -21,10 +21,10 @@ package pan.alexander.tordnscrypt.domain.connection_records import android.content.Context import android.content.SharedPreferences -import pan.alexander.tordnscrypt.TopFragment import pan.alexander.tordnscrypt.di.SharedPreferencesModule import pan.alexander.tordnscrypt.iptables.Tethering import pan.alexander.tordnscrypt.modules.ModulesStatus +import pan.alexander.tordnscrypt.settings.PathVars import pan.alexander.tordnscrypt.utils.Constants import pan.alexander.tordnscrypt.utils.Constants.LOOPBACK_ADDRESS import pan.alexander.tordnscrypt.utils.Constants.META_ADDRESS @@ -40,7 +40,8 @@ class ConnectionRecordsParser @Inject constructor( private val applicationContext: Context, private val installedAppNamesStorage: dagger.Lazy, @Named(SharedPreferencesModule.DEFAULT_PREFERENCES_NAME) - defaultPreferences: SharedPreferences + defaultPreferences: SharedPreferences, + private val pathVars: dagger.Lazy ) { private val modulesStatus = ModulesStatus.getInstance() @@ -85,7 +86,7 @@ class ConnectionRecordsParser @Inject constructor( val record = connectionRecords[i] - if (TopFragment.appVersion.startsWith("g") && record.blocked && record.blockedByIpv6 + if (pathVars.get().appVersion.startsWith("g") && record.blocked && record.blockedByIpv6 /*remove artifacts*/ || (record.aName.trim() == "=" || record.qName.trim() == "=") && record.uid == -1000 diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/help/HelpActivity.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/help/HelpActivity.java index b69ab2c50..70fb7d149 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/help/HelpActivity.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/help/HelpActivity.java @@ -63,6 +63,7 @@ import pan.alexander.tordnscrypt.utils.filemanager.ExternalStoragePermissions; import pan.alexander.tordnscrypt.utils.filemanager.FileManager; import pan.alexander.tordnscrypt.utils.filemanager.OnBinaryFileOperationsCompleteListener; +import pan.alexander.tordnscrypt.utils.integrity.Verifier; import pan.alexander.tordnscrypt.utils.root.RootCommands; import pan.alexander.tordnscrypt.utils.root.RootExecService; import pan.alexander.tordnscrypt.modules.ModulesStatus; @@ -84,6 +85,8 @@ public class HelpActivity extends LangAppCompatActivity implements View.OnClickL public Lazy preferenceRepository; @Inject public CachedExecutor cachedExecutor; + @Inject + public Lazy verifier; private TextView tvLogsPath; private EditText etLogsPath; @@ -183,7 +186,14 @@ public void onClick(View view) { return; } - info = Utils.INSTANCE.collectInfo(); + try { + info = Utils.INSTANCE.collectInfo( + verifier.get().getAppSignature(), + pathVarsLazy.get().getAppVersion(), + pathVarsLazy.get().getAppProcVersion() + ); + } catch (Exception ignored) { + } br.setInfo(info); dialogFragment = PleaseWaitProgressDialog.getInstance(); @@ -295,6 +305,7 @@ public void onCheckedChanged(CompoundButton compoundButton, boolean newValue) { FileManager.deleteFile(getApplicationContext(), appDataDir + "/logs", "RootExec.log", "RootExec.log"); FileManager.deleteFile(getApplicationContext(), appDataDir + "/logs", "Snowflake.log", "Snowflake.log"); FileManager.deleteFile(getApplicationContext(), appDataDir + "/logs", "Conjure.log", "Conjure.log"); + FileManager.deleteFile(getApplicationContext(), appDataDir + "/logs", "WebTunnel.log", "WebTunnel.log"); } } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/help/Utils.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/help/Utils.kt index 96d64d036..c1c410399 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/help/Utils.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/help/Utils.kt @@ -79,7 +79,7 @@ object Utils { return false } - fun collectInfo(): String { + fun collectInfo(appSign: String, appVersion: String, appProcVersion: String): String { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return "BRAND " + Build.BRAND + 10.toChar() + "MODEL " + Build.MODEL + 10.toChar() + @@ -92,15 +92,16 @@ object Utils { "SUPPORTED_32_BIT_ABIS " + Arrays.toString(Build.SUPPORTED_32_BIT_ABIS) + 10.toChar() + "SUPPORTED_64_BIT_ABIS " + Arrays.toString(Build.SUPPORTED_64_BIT_ABIS) + 10.toChar() + "SDK_INT " + Build.VERSION.SDK_INT + 10.toChar() + + "THREADS " + Thread.getAllStackTraces().size + 10.toChar() + "APP_VERSION_CODE " + BuildConfig.VERSION_CODE + 10.toChar() + "APP_VERSION_NAME " + BuildConfig.VERSION_NAME + 10.toChar() + - "APP_PROC_VERSION " + TopFragment.appProcVersion + 10.toChar() + + "APP_PROC_VERSION " + appProcVersion + 10.toChar() + "CAN_FILTER " + VpnUtils.canFilter() + 10.toChar() + - "APP_VERSION " + TopFragment.appVersion + 10.toChar() + + "APP_VERSION " + appVersion + 10.toChar() + "DNSCRYPT_INTERNAL_VERSION " + TopFragment.DNSCryptVersion + 10.toChar() + "TOR_INTERNAL_VERSION " + TopFragment.TorVersion + 10.toChar() + "I2PD_INTERNAL_VERSION " + TopFragment.ITPDVersion + 10.toChar() + - "SIGN_VERSION " + TopFragment.appSign + "SIGN_VERSION " + appSign } else { return "BRAND " + Build.BRAND + 10.toChar() + "MODEL " + Build.MODEL + 10.toChar() + @@ -110,15 +111,16 @@ object Utils { "BOARD " + Build.BOARD + 10.toChar() + "HARDWARE " + Build.HARDWARE + 10.toChar() + "SDK_INT " + Build.VERSION.SDK_INT + 10.toChar() + + "THREADS " + Thread.getAllStackTraces().size + 10.toChar() + "APP_VERSION_CODE " + BuildConfig.VERSION_CODE + 10.toChar() + "APP_VERSION_NAME " + BuildConfig.VERSION_NAME + 10.toChar() + - "APP_PROC_VERSION " + TopFragment.appProcVersion + 10.toChar() + + "APP_PROC_VERSION " + appProcVersion + 10.toChar() + "CAN_FILTER " + VpnUtils.canFilter() + 10.toChar() + - "APP_VERSION " + TopFragment.appVersion + 10.toChar() + + "APP_VERSION " + appVersion + 10.toChar() + "DNSCRYPT_INTERNAL_VERSION " + TopFragment.DNSCryptVersion + 10.toChar() + "TOR_INTERNAL_VERSION " + TopFragment.TorVersion + 10.toChar() + "I2PD_INTERNAL_VERSION " + TopFragment.ITPDVersion + 10.toChar() + - "SIGN_VERSION " + TopFragment.appSign + "SIGN_VERSION " + appSign } } } \ No newline at end of file diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/ChmodCommand.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/ChmodCommand.java index f62973121..535b7387b 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/ChmodCommand.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/ChmodCommand.java @@ -22,10 +22,10 @@ import android.annotation.SuppressLint; import java.io.File; -class ChmodCommand { +public class ChmodCommand { @SuppressLint("SetWorldReadable") - static void dirChmod(String path, boolean executableDir) { + public static void dirChmod(String path, boolean executableDir) { File dir = new File(path); if (!dir.isDirectory()) { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/DNSCryptExtractCommand.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/DNSCryptExtractCommand.java index e7cf935e1..e6460dc4e 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/DNSCryptExtractCommand.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/DNSCryptExtractCommand.java @@ -26,7 +26,7 @@ public class DNSCryptExtractCommand extends AssetsExtractCommand { private final String appDataDir; - DNSCryptExtractCommand(Context context, String appDataDir) { + public DNSCryptExtractCommand(Context context, String appDataDir) { super(context); this.appDataDir = appDataDir; } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/ITPDExtractCommand.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/ITPDExtractCommand.java index 39c3ab8e9..0d3bba9e6 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/ITPDExtractCommand.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/ITPDExtractCommand.java @@ -26,7 +26,7 @@ public class ITPDExtractCommand extends AssetsExtractCommand { private final String appDataDir; - ITPDExtractCommand(Context context, String appDataDir) { + public ITPDExtractCommand(Context context, String appDataDir) { super(context); this.appDataDir = appDataDir; } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/Installer.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/Installer.java index 0e5e818c7..8a2fe5ce4 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/Installer.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/Installer.java @@ -53,6 +53,7 @@ import static pan.alexander.tordnscrypt.TopFragment.TOP_BROADCAST; import static pan.alexander.tordnscrypt.di.SharedPreferencesModule.DEFAULT_PREFERENCES_NAME; +import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.MAIN_ACTIVITY_RECREATE; import static pan.alexander.tordnscrypt.utils.root.RootCommandsMark.INSTALLER_MARK; import static pan.alexander.tordnscrypt.utils.root.RootExecService.COMMAND_RESULT; @@ -73,6 +74,8 @@ public class Installer implements TopFragment.OnActivityChangeListener { public CachedExecutor cachedExecutor; @Inject public Lazy modulesVersions; + @Inject + public Lazy installerHelper; private Activity activity; private MainActivity mainActivity; @@ -291,11 +294,15 @@ protected boolean waitUntilAllModulesStopped() { boolean result = true; try { - //noinspection ResultOfMethodCallIgnored - countDownLatch.await(10, TimeUnit.SECONDS); + if (countDownLatch != null) { + //noinspection ResultOfMethodCallIgnored + countDownLatch.await(10, TimeUnit.SECONDS); + } } catch (InterruptedException e) { Log.e(LOG_TAG, "Installer CountDownLatch interrupted"); result = false; + } catch (Exception e) { + loge("Installer waitUntilAllModulesStopped", e, true); } return result; @@ -371,7 +378,7 @@ private void fixAppDirLinesList(String path, List lines) { && activity.getText(R.string.package_name).toString().contains(".gp") && path.contains("dnscrypt-proxy.toml") && !PathVars.isModulesInstalled(preferenceRepository.get())) { - lines = prepareDNSCryptForGP(lines); + lines = installerHelper.get().prepareDNSCryptForGP(lines); } FileManager.writeTextFileSynchronous(activity, path, lines); @@ -380,48 +387,6 @@ private void fixAppDirLinesList(String path, List lines) { } } - @SuppressLint("SdCardPath") - private List prepareDNSCryptForGP(List lines) { - - defaultPreferences.get().edit().putBoolean("require_nofilter", true).apply(); - - ArrayList prepared = new ArrayList<>(); - - for (String line : lines) { - - if (line.contains("blacklist_file")) { - line = ""; - } else if (line.contains("whitelist_file")) { - line = ""; - } else if (line.contains("blocked_names_file")) { - line = ""; - } else if (line.contains("blocked_ips_file")) { - line = ""; - } else if (line.matches("(^| )\\{ ?server_name([ =]).+")) { - line = ""; - } else if (line.matches("(^| )server_names([ =]).+")) { - line = "server_names = ['uncensoreddns-dk-ipv4', " + - "'njalla-doh', " + - "'faelix-ch-ipv4', " + - "'dns.digitale-gesellschaft.ch', " + - "'dnscrypt.ca-1', " + - "'sth-doh-se', " + - "'libredns', " + - "'dnswarden-uncensor-dc-swiss', " + - "'publicarray-au-doh', " + - "'scaleway-fr']"; - } else if (line.contains("require_nofilter")) { - line = "require_nofilter = true"; - } - - if (!line.isEmpty()) { - prepared.add(line); - } - } - - return prepared; - } - protected void stopAllRunningModulesWithRootCommand() { Log.i(LOG_TAG, "Installer: stopAllRunningModulesWithRootCommand"); diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/InstallerHelper.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/InstallerHelper.java new file mode 100644 index 000000000..eb8f6c27a --- /dev/null +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/InstallerHelper.java @@ -0,0 +1,81 @@ +/* + This file is part of InviZible Pro. + + InviZible Pro is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InviZible Pro is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with InviZible Pro. If not, see . + + Copyright 2019-2023 by Garmatin Oleksandr invizible.soft@gmail.com + */ + +package pan.alexander.tordnscrypt.installer; + +import static pan.alexander.tordnscrypt.di.SharedPreferencesModule.DEFAULT_PREFERENCES_NAME; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.SharedPreferences; +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Named; + +import pan.alexander.tordnscrypt.R; + +public class InstallerHelper { + + private final Context context; + private final SharedPreferences defaultPreferences; + + @Inject + public InstallerHelper(Context context, @Named(DEFAULT_PREFERENCES_NAME) SharedPreferences defaultPreferences) { + this.context = context; + this.defaultPreferences = defaultPreferences; + } + + @SuppressLint("SdCardPath") + public List prepareDNSCryptForGP(List lines) { + + defaultPreferences.edit().putBoolean("require_nofilter", true).apply(); + + ArrayList prepared = new ArrayList<>(); + + for (String line : lines) { + + if (line.contains("blacklist_file")) { + line = ""; + } else if (line.contains("whitelist_file")) { + line = ""; + } else if (line.contains("blocked_names_file")) { + line = ""; + } else if (line.contains("blocked_ips_file")) { + line = ""; + } else if (line.matches("(^| )\\{ ?server_name([ =]).+")) { + line = ""; + } else if (line.matches("(^| )server_names([ =]).+")) { + String[] servers = context.getResources().getStringArray(R.array.default_dnscrypt_servers_gp); + line = "server_names = ['" + TextUtils.join("', '", servers) + "']"; + } else if (line.contains("require_nofilter")) { + line = "require_nofilter = true"; + } + + if (!line.isEmpty()) { + prepared.add(line); + } + } + + return prepared; + } +} diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/TorExtractCommand.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/TorExtractCommand.java index 1e5f29612..ce98577f2 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/TorExtractCommand.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/installer/TorExtractCommand.java @@ -26,7 +26,7 @@ public class TorExtractCommand extends AssetsExtractCommand { private final String appDataDir; - TorExtractCommand(Context context, String appDataDir) { + public TorExtractCommand(Context context, String appDataDir) { super(context); this.appDataDir = appDataDir; } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/language/LanguageList.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/language/LanguageList.java index efdfd3527..b82a6eabb 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/language/LanguageList.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/language/LanguageList.java @@ -31,20 +31,21 @@ public class LanguageList { null, "Q2hpbmVzZSAo5Lit5paHKQ==", "RW5nbGlzaCAoRW5nbGlzaCk=", - "RmlubmlzaCAoU3VvbWFsYWluZW4p", - "RnJlbmNoIChGcmFuw6dhaXNlKQ==", - "R2VybWFuIChEZXV0c2NoZSk=", - "R3JlZWsgKM6VzrvOu863zr3Ouc66zq4p", + "RmlubmlzaCAoU3VvbWkp", + "RnJlbmNoIChGcmFuw6dhaXMp", + "R2VybWFuIChEZXV0c2NoKQ==", + "R3JlZWsgKM6VzrvOu863zr3Ouc66zqwp", "SW5kb25lc2lhbiAoYmFoYXNhIEluZG9uZXNpYSk=", - "SXRhbGlhbiAoSXRhbGlhbmEp", + "SXRhbGlhbiAoSXRhbGlhbm8p", "SmFwYW5lc2UgKOaXpeacrOiqnik=", "UGVyc2lhbiAo2YHYp9ix2LPbjCk=", "UG9saXNoIChQb2xza2kp", "UG9ydHVndWVzZSAoUG9ydHVndcOqcyk=", "UG9ydHVndWVzZS1CUiAoUG9ydHVndcOqcy1CUik=", "UnVzc2lhbiAo0KDRg9GB0YHQutC40Lkp", - "U3BhbmlzaCAoRXNwYcOxb2xhKQ==", - "VHVya2lzaCAoVMO8cmsp" + "U3BhbmlzaCAoRXNwYcOxb2wp", + "VHVya2lzaCAoVMO8cmvDp2Up", + "VWtyYWluaWFuICjQo9C60YDQsNGX0L3RgdGM0LrQsCk=" }; private static final String[] MACHINE = { "", @@ -63,7 +64,8 @@ public class LanguageList { "pt-rBR", "ru", "es", - "tr" + "tr", + "uk" }; private static String[] mHuman; diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesActionSender.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesActionSender.kt index f9faa5f42..01d911ddb 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesActionSender.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesActionSender.kt @@ -27,7 +27,7 @@ import pan.alexander.tordnscrypt.utils.app import pan.alexander.tordnscrypt.utils.logger.Logger.loge object ModulesActionSender { - fun sendIntent(context: Context, action: String) { + fun sendIntent(context: Context, action: String) = try { val intent = Intent(context, ModulesService::class.java) intent.action = action @@ -49,5 +49,7 @@ object ModulesActionSender { intent.putExtra("showNotification", isShowNotification(context)) context.startService(intent) } + } catch (e: Exception) { + loge("ModulesActionSender sendIntent", e, true) } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesService.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesService.java index 3684f46e7..4a09cb500 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesService.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesService.java @@ -34,8 +34,6 @@ import java.io.File; import java.io.IOException; import java.io.PrintWriter; -import java.net.DatagramSocket; -import java.net.ServerSocket; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -57,6 +55,7 @@ import pan.alexander.tordnscrypt.utils.apps.InstalledAppNamesStorage; import pan.alexander.tordnscrypt.utils.executors.CachedExecutor; import pan.alexander.tordnscrypt.utils.Utils; +import pan.alexander.tordnscrypt.utils.portchecker.PortChecker; import pan.alexander.tordnscrypt.utils.root.RootExecService; import pan.alexander.tordnscrypt.utils.wakelock.WakeLocksManager; import pan.alexander.tordnscrypt.utils.enums.OperationMode; @@ -138,6 +137,8 @@ public class ModulesService extends Service { public CachedExecutor cachedExecutor; @Inject public Lazy installedAppNamesStorage; + @Inject + public Lazy portChecker; private final ModulesStatus modulesStatus = ModulesStatus.getInstance(); @@ -247,63 +248,28 @@ public int onStartCommand(Intent intent, int flags, int startId) { manageWakelocks(); switch (action) { - case ACTION_START_DNSCRYPT: - startDNSCrypt(); - break; - case ACTION_START_TOR: - startTor(); - break; - case ACTION_START_ITPD: - startITPD(); - break; - case ACTION_STOP_DNSCRYPT: - stopDNSCrypt(); - break; - case ACTION_STOP_TOR: - stopTor(); - break; - case ACTION_STOP_ITPD: - stopITPD(); - break; - case ACTION_RESTART_DNSCRYPT: - restartDNSCrypt(); - break; - case ACTION_RESTART_TOR: - restartTor(); - break; - case ACTION_RESTART_TOR_FULL: - restartTorFull(); - break; - case ACTION_RESTART_ITPD: - restartITPD(); - break; - case ACTION_DISMISS_NOTIFICATION: - dismissNotification(startId); - break; - case ACTION_RECOVER_SERVICE: - recoverAppState(); - break; - case SPEEDUP_LOOP: - speedupTimer(); - break; - case SLOWDOWN_LOOP: - slowdownTimer(); - break; - case EXTRA_LOOP: - makeExtraLoop(); - break; - case ACTION_STOP_SERVICE: + case ACTION_START_DNSCRYPT -> startDNSCrypt(); + case ACTION_START_TOR -> startTor(); + case ACTION_START_ITPD -> startITPD(); + case ACTION_STOP_DNSCRYPT -> stopDNSCrypt(); + case ACTION_STOP_TOR -> stopTor(); + case ACTION_STOP_ITPD -> stopITPD(); + case ACTION_RESTART_DNSCRYPT -> restartDNSCrypt(); + case ACTION_RESTART_TOR -> restartTor(); + case ACTION_RESTART_TOR_FULL -> restartTorFull(); + case ACTION_RESTART_ITPD -> restartITPD(); + case ACTION_DISMISS_NOTIFICATION -> dismissNotification(startId); + case ACTION_RECOVER_SERVICE -> recoverAppState(); + case SPEEDUP_LOOP -> speedupTimer(); + case SLOWDOWN_LOOP -> slowdownTimer(); + case EXTRA_LOOP -> makeExtraLoop(); + case ACTION_STOP_SERVICE -> { stopModulesService(); return START_NOT_STICKY; - case START_ARP_SCANNER: - startArpScanner(); - break; - case STOP_ARP_SCANNER: - stopArpScanner(); - break; - case CLEAR_IPTABLES_COMMANDS_HASH: - clearIptablesCommandsSavedHash(); - break; + } + case START_ARP_SCANNER -> startArpScanner(); + case STOP_ARP_SCANNER -> stopArpScanner(); + case CLEAR_IPTABLES_COMMANDS_HASH -> clearIptablesCommandsSavedHash(); } setBroadcastReceiver(); @@ -413,7 +379,8 @@ private void changeDNSCryptStatus(final Thread dnsCryptThread) { } private boolean stopDNSCryptIfPortIsBusy() { - if (isNotAvailable(pathVars.get().getDNSCryptPort())) { + PortChecker checker = portChecker.get(); + if (checker.isPortBusy(pathVars.get().getDNSCryptPort())) { try { modulesStatus.setDnsCryptState(RESTARTING); @@ -540,10 +507,11 @@ private void changeTorStatus(final Thread torThread) { } private boolean stopTorIfPortsIsBusy() { - boolean stopRequired = isNotAvailable(pathVars.get().getTorDNSPort()) - || isNotAvailable(pathVars.get().getTorSOCKSPort()) - || isNotAvailable(pathVars.get().getTorTransPort()) - || isNotAvailable(pathVars.get().getTorHTTPTunnelPort()); + PortChecker checker = portChecker.get(); + boolean stopRequired = checker.isPortBusy(pathVars.get().getTorDNSPort()) + || checker.isPortBusy(pathVars.get().getTorSOCKSPort()) + || checker.isPortBusy(pathVars.get().getTorTransPort()) + || checker.isPortBusy(pathVars.get().getTorHTTPTunnelPort()); if (stopRequired) { try { @@ -685,17 +653,18 @@ private boolean stopITPDIfPortsIsBusy() { preferenceRepository.get() .setStringSetPreference("ITPDTunnelsPorts", itpdTunnelsPorts); + PortChecker checker = portChecker.get(); boolean stopRequired = false; for (String port : itpdTunnelsPorts) { - if (isNotAvailable(port)) { + if (checker.isPortBusy(port)) { stopRequired = true; } } stopRequired = stopRequired || - isNotAvailable(pathVars.get().getITPDSOCKSPort()) - || isNotAvailable(pathVars.get().getITPDHttpProxyPort()); + checker.isPortBusy(pathVars.get().getITPDSOCKSPort()) + || checker.isPortBusy(pathVars.get().getITPDHttpProxyPort()); if (stopRequired) { try { @@ -924,7 +893,10 @@ private void stopModulesThreadsTimer() { private void stopVPNServiceIfRunning() { OperationMode operationMode = modulesStatus.getMode(); - SharedPreferences prefs = android.preference.PreferenceManager.getDefaultSharedPreferences(this); + if (defaultSharedPreferences == null) { + return; + } + SharedPreferences prefs = defaultSharedPreferences.get(); if (((operationMode == VPN_MODE) || modulesStatus.isFixTTL()) && prefs.getBoolean(VPN_SERVICE_ENABLED, false)) { ServiceVPNHelper.stop("ModulesService is destroyed", this); } @@ -1165,35 +1137,6 @@ private ThreadGroup getRootThreadGroup(Thread thread) { return rootGroup; } - private boolean isNotAvailable(String portStr) { - - int port = Integer.parseInt(portStr); - - ServerSocket ss = null; - DatagramSocket ds = null; - try { - ss = new ServerSocket(port); - ss.setReuseAddress(true); - ds = new DatagramSocket(port); - ds.setReuseAddress(true); - return false; - } catch (IOException ignored) { - } finally { - if (ds != null) { - ds.close(); - } - - if (ss != null) { - try { - ss.close(); - } catch (IOException ignored) { - } - } - } - - return true; - } - private void cleanLogFileNoRootMethod(String logFilePath, String text) { try { File f = new File(pathVars.get().getAppDataDir() + "/logs"); @@ -1233,7 +1176,7 @@ private void clearIptablesCommandsSavedHash() { } private void checkModulesConfigPatches() { - Patch patch = new Patch(this); + Patch patch = new Patch(this, pathVars.get()); patch.checkPatches(false); } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesServiceNotificationManager.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesServiceNotificationManager.java index 3860e2115..5fb0a990f 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesServiceNotificationManager.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesServiceNotificationManager.java @@ -127,10 +127,14 @@ public synchronized void sendNotification(String title, String text) { Notification notification = builder.build(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - service.startForeground(DEFAULT_NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST); - } else { - service.startForeground(DEFAULT_NOTIFICATION_ID, notification); + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + service.startForeground(DEFAULT_NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST); + } else { + service.startForeground(DEFAULT_NOTIFICATION_ID, notification); + } + } catch (Exception e) { + loge("ModulesServiceNotificationManager sendNotification", e); } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesStarterHelper.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesStarterHelper.java index 7a0f366c6..c85a020fb 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesStarterHelper.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/modules/ModulesStarterHelper.java @@ -21,7 +21,9 @@ import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Handler; +import android.text.TextUtils; import android.widget.Toast; import androidx.localbroadcastmanager.content.LocalBroadcastManager; @@ -31,24 +33,38 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import dagger.Lazy; import pan.alexander.tordnscrypt.App; +import pan.alexander.tordnscrypt.R; import pan.alexander.tordnscrypt.domain.preferences.PreferenceRepository; import pan.alexander.tordnscrypt.patches.Patch; import pan.alexander.tordnscrypt.settings.PathVars; +import pan.alexander.tordnscrypt.utils.enums.ModuleName; +import pan.alexander.tordnscrypt.utils.portchecker.PortChecker; import pan.alexander.tordnscrypt.utils.root.RootCommands; import pan.alexander.tordnscrypt.utils.filemanager.FileManager; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; +import static pan.alexander.tordnscrypt.di.SharedPreferencesModule.DEFAULT_PREFERENCES_NAME; import static pan.alexander.tordnscrypt.modules.ModulesService.DNSCRYPT_KEYWORD; import static pan.alexander.tordnscrypt.modules.ModulesService.ITPD_KEYWORD; import static pan.alexander.tordnscrypt.modules.ModulesService.TOR_KEYWORD; import static pan.alexander.tordnscrypt.utils.AppExtension.getApp; +import static pan.alexander.tordnscrypt.utils.Constants.NUMBER_REGEX; +import static pan.alexander.tordnscrypt.utils.Utils.verifyHostsSet; import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; import static pan.alexander.tordnscrypt.utils.logger.Logger.logi; import static pan.alexander.tordnscrypt.utils.logger.Logger.logw; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.DNSCRYPT_LISTEN_PORT; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.FAKE_SNI; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.FAKE_SNI_HOSTS; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_DNS_PORT; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_HTTP_TUNNEL_PORT; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_SOCKS_PORT; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_TRANS_PORT; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.USE_DEFAULT_BRIDGES; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.USE_OWN_BRIDGES; import static pan.alexander.tordnscrypt.utils.root.RootCommandsMark.DNSCRYPT_RUN_FRAGMENT_MARK; @@ -62,22 +78,29 @@ import static pan.alexander.tordnscrypt.utils.enums.ModuleState.STOPPING; import javax.inject.Inject; +import javax.inject.Named; public class ModulesStarterHelper { - public final static String ASK_FORCE_CLOSE = "pan.alexander.tordnscrypt.AskForceClose"; + public final static String ASK_RESTORE_DEFAULTS = "pan.alexander.tordnscrypt.AskRestoreDefaults"; public final static String MODULE_NAME = "pan.alexander.tordnscrypt.ModuleName"; + @Inject + @Named(DEFAULT_PREFERENCES_NAME) + public Lazy defaultPreferences; @Inject public Lazy preferenceRepository; @Inject public PathVars pathVars; + @Inject + public Lazy portChecker; private final Context context; private final Handler handler; private final String appDataDir; private final String busyboxPath; private final String dnscryptPath; + private final String dnscryptConfPath; private final String torPath; private final String torConfPath; private final String obfsPath; @@ -92,6 +115,7 @@ public class ModulesStarterHelper { appDataDir = pathVars.getAppDataDir(); busyboxPath = pathVars.getBusyboxPath(); dnscryptPath = pathVars.getDNSCryptPath(); + dnscryptConfPath = pathVars.getDnscryptConfPath(); torPath = pathVars.getTorPath(); torConfPath = pathVars.getTorConfPath(); obfsPath = pathVars.getObfsPath(); @@ -108,6 +132,12 @@ Runnable getDNSCryptStarterRunnable() { final CommandResult shellResult; if (modulesStatus.isUseModulesWithRoot()) { + List lines = readDnsCryptConfiguration(); + + checkDnsCryptPortsForBusyness(lines); + + saveDnsCryptConfiguration(lines); + dnsCmdString = busyboxPath + "nohup " + dnscryptPath + " -config " + appDataDir + "/app_data/dnscrypt-proxy/dnscrypt-proxy.toml -pidfile " + appDataDir @@ -126,6 +156,13 @@ Runnable getDNSCryptStarterRunnable() { } } else { + + List lines = readDnsCryptConfiguration(); + + checkDnsCryptPortsForBusyness(lines); + + saveDnsCryptConfiguration(lines); + dnsCmdString = dnscryptPath + " -config " + appDataDir + "/app_data/dnscrypt-proxy/dnscrypt-proxy.toml -pidfile " + appDataDir + "/dnscrypt-proxy.pid"; preferenceRepository.get().setBoolPreference("DNSCryptStartedWithRoot", false); @@ -142,7 +179,7 @@ Runnable getDNSCryptStarterRunnable() { if (modulesStatus.getDnsCryptState() != STOPPING && modulesStatus.getDnsCryptState() != STOPPED) { - if (appVersion.startsWith("b") && handler != null) { + if (pathVars.getAppVersion().startsWith("b") && handler != null) { handler.post(() -> Toast.makeText(context, "DNSCrypt Module Fault: " + shellResult.exitCode + "\n\n ERR = " + shellResult.getStderr() + "\n\n OUT = " + shellResult.getStdout(), Toast.LENGTH_LONG).show()); @@ -150,7 +187,7 @@ Runnable getDNSCryptStarterRunnable() { checkModulesConfigPatches(); - sendAskForceCloseBroadcast(context, "DNSCrypt"); + sendAskRestoreDefaults(context, ModuleName.DNSCRYPT_MODULE); } loge("Error DNSCrypt: " @@ -185,12 +222,23 @@ Runnable getTorStarterRunnable() { final CommandResult shellResult; if (modulesStatus.isUseModulesWithRoot()) { - List lines = correctTorConfRunAsDaemon(context, true); + List lines = readTorConfiguration(); + + correctTorConfRunAsDaemon(lines, true); correctObfsModulePath(lines); - torCmdString = torPath + " -f " - + appDataDir + "/app_data/tor/tor.conf -pidfile " + appDataDir + "/tor.pid"; + checkTorPortsForBusyness(lines); + + saveTorConfiguration(lines); + + torCmdString = torPath + + " -f " + appDataDir + "/app_data/tor/tor.conf" + + " -pidfile " + appDataDir + "/tor.pid"; + String fakeHosts = getFakeSniHosts(); + if (defaultPreferences.get().getBoolean(FAKE_SNI, false) && !fakeHosts.isEmpty()) { + torCmdString += " -fake-hosts " + fakeHosts; + } String waitString = busyboxPath + "sleep 3"; String checkIfModuleRunning = busyboxPath + "pgrep -l /libtor.so"; @@ -206,14 +254,25 @@ Runnable getTorStarterRunnable() { } else { - List lines = correctTorConfRunAsDaemon(context, false); + List lines = readTorConfiguration(); + + correctTorConfRunAsDaemon(lines, false); useTorSchedulerVanilla(lines); correctObfsModulePath(lines); - torCmdString = torPath + " -f " - + appDataDir + "/app_data/tor/tor.conf -pidfile " + appDataDir + "/tor.pid"; + checkTorPortsForBusyness(lines); + + saveTorConfiguration(lines); + + torCmdString = torPath + + " -f " + appDataDir + "/app_data/tor/tor.conf" + + " -pidfile " + appDataDir + "/tor.pid"; + String fakeHosts = getFakeSniHosts(); + if (defaultPreferences.get().getBoolean(FAKE_SNI, false) && !fakeHosts.isEmpty()) { + torCmdString += " -fake-hosts " + fakeHosts; + } preferenceRepository.get().setBoolPreference("TorStartedWithRoot", false); shellResult = new ProcessStarter(context.getApplicationInfo().nativeLibraryDir) @@ -227,7 +286,7 @@ Runnable getTorStarterRunnable() { } if (modulesStatus.getTorState() != STOPPING && modulesStatus.getTorState() != STOPPED) { - if (appVersion.startsWith("b") && handler != null) { + if (pathVars.getAppVersion().startsWith("b") && handler != null) { handler.post(() -> Toast.makeText(context, "Tor Module Fault: " + shellResult.exitCode + "\n\n ERR = " + shellResult.getStderr() + "\n\n OUT = " + shellResult.getStdout(), Toast.LENGTH_LONG).show()); @@ -235,7 +294,7 @@ Runnable getTorStarterRunnable() { checkModulesConfigPatches(); - sendAskForceCloseBroadcast(context, "Tor"); + sendAskRestoreDefaults(context, ModuleName.TOR_MODULE); //Try to update Selinux context and UID once again if (shellResult.exitCode == 1 && modulesStatus.isRootAvailable()) { @@ -319,7 +378,7 @@ Runnable getITPDStarterRunnable() { } if (modulesStatus.getItpdState() != STOPPING && modulesStatus.getItpdState() != STOPPED) { - if (appVersion.startsWith("b") && handler != null) { + if (pathVars.getAppVersion().startsWith("b") && handler != null) { handler.post(() -> Toast.makeText(context, "Purple I2P Module Fault: " + shellResult.exitCode + "\n\n ERR = " + shellResult.getStderr() + "\n\n OUT = " + shellResult.getStdout(), Toast.LENGTH_LONG).show()); @@ -327,7 +386,7 @@ Runnable getITPDStarterRunnable() { checkModulesConfigPatches(); - sendAskForceCloseBroadcast(context, "I2P"); + sendAskRestoreDefaults(context, ModuleName.ITPD_MODULE); } loge("Error ITPD: " + shellResult.exitCode + " ERR=" @@ -351,24 +410,54 @@ Runnable getITPDStarterRunnable() { }; } - private List correctTorConfRunAsDaemon(Context context, boolean runAsDaemon) { + private List readDnsCryptConfiguration() { + return FileManager.readTextFileSynchronous(context, dnscryptConfPath); + } + + private void checkDnsCryptPortsForBusyness(List lines) { + String port = pathVars.getDNSCryptPort(); + PortChecker checker = portChecker.get(); - List lines = FileManager.readTextFileSynchronous(context, torConfPath); + if (port.matches(NUMBER_REGEX) && checker.isPortBusy(port)) { + + String freePort = checker.getFreePort(port); + + if (freePort.equals(port)) { + return; + } + + for (int i = 0; i < lines.size(); i++) { + String line = lines.get(i); + if (line.contains("listen_addresses") && line.contains(port)) { + line = line.replace(port, freePort); + lines.set(i, line); + } + } + defaultPreferences.get().edit().putString(DNSCRYPT_LISTEN_PORT, freePort).apply(); + } + } + + private void saveDnsCryptConfiguration(List lines) { + FileManager.writeTextFileSynchronous(context, dnscryptConfPath, lines); + } + + private List readTorConfiguration() { + return FileManager.readTextFileSynchronous(context, torConfPath); + } + + private void correctTorConfRunAsDaemon(List lines, boolean runAsDaemon) { for (int i = 0; i < lines.size(); i++) { if (lines.get(i).contains("RunAsDaemon")) { if (runAsDaemon && lines.get(i).contains("0")) { lines.set(i, "RunAsDaemon 1"); - FileManager.writeTextFileSynchronous(context, torConfPath, lines); } else if (!runAsDaemon && lines.get(i).contains("1")) { lines.set(i, "RunAsDaemon 0"); - FileManager.writeTextFileSynchronous(context, torConfPath, lines); } - return lines; + return; } } - return lines; } //Disable Tor Kernel-Informed Socket Transport because ioctl() with request SIOCOUTQNSD is denied by android SELINUX policy @@ -407,24 +496,70 @@ private void correctObfsModulePath(List lines) { for (int i = 0; i < lines.size(); i++) { line = lines.get(i); if (line.contains("ClientTransportPlugin ") && line.contains("/libobfs4proxy.so")) { - line = line.replaceAll("/.+?/libobfs4proxy.so", context.getApplicationInfo().nativeLibraryDir + "/libobfs4proxy.so"); + line = line.replaceAll("/.+?/libobfs4proxy.so", pathVars.getObfsPath()); lines.set(i, line); } else if (line.contains("ClientTransportPlugin ") && line.contains("/libsnowflake.so")) { - line = line.replaceAll("/.+?/libsnowflake.so", context.getApplicationInfo().nativeLibraryDir + "/libsnowflake.so"); + line = line.replaceAll("/.+?/libsnowflake.so", pathVars.getSnowflakePath()); lines.set(i, line); } else if (line.contains("ClientTransportPlugin ") && line.contains("/libconjure.so")) { - line = line.replaceAll("/.+?/libconjure.so", context.getApplicationInfo().nativeLibraryDir + "/libconjure.so"); + line = line.replaceAll("/.+?/libconjure.so", pathVars.getConjurePath()); + lines.set(i, line); + } else if (line.contains("ClientTransportPlugin ") && line.contains("/libwebtunnel.so")) { + line = line.replaceAll("/.+?/libwebtunnel.so", pathVars.getWebTunnelPath()); lines.set(i, line); } } - FileManager.writeTextFileSynchronous(context, torConfPath, lines); - logi("ModulesService Tor Obfs module path is corrected"); } } } + private void checkTorPortsForBusyness(List lines) { + String dnsPort = pathVars.getTorDNSPort(); + String socksPort = pathVars.getTorSOCKSPort(); + String httpTunnelPort = pathVars.getTorHTTPTunnelPort(); + String transPort = pathVars.getTorTransPort(); + + PortChecker checker = portChecker.get(); + + if (dnsPort.matches(NUMBER_REGEX) && checker.isPortBusy(dnsPort)) { + fixTorProxyPort(lines, TOR_DNS_PORT, dnsPort); + } + if (socksPort.matches(NUMBER_REGEX) && checker.isPortBusy(socksPort)) { + fixTorProxyPort(lines, TOR_SOCKS_PORT, socksPort); + } + if (httpTunnelPort.matches(NUMBER_REGEX) && checker.isPortBusy(httpTunnelPort)) { + fixTorProxyPort(lines, TOR_HTTP_TUNNEL_PORT, httpTunnelPort); + } + if (transPort.matches(NUMBER_REGEX) && checker.isPortBusy(transPort)) { + fixTorProxyPort(lines, TOR_TRANS_PORT, transPort); + } + + } + + private void fixTorProxyPort(List lines, String proxyType, String proxyPort) { + PortChecker checker = portChecker.get(); + String port = checker.getFreePort(proxyPort); + + if (port.equals(proxyPort)) { + return; + } + + for (int i = 0; i < lines.size(); i++) { + String line = lines.get(i); + if (line.contains(proxyType) && line.contains(proxyPort)) { + line = line.replace(proxyPort, port); + lines.set(i, line); + } + } + defaultPreferences.get().edit().putString(proxyType, port).apply(); + } + + private void saveTorConfiguration(List lines) { + FileManager.writeTextFileSynchronous(context, torConfPath, lines); + } + private void correctITPDConfRunAsDaemon(Context context, String appDataDir, boolean runAsDaemon) { String path = appDataDir + "/app_data/i2pd/i2pd.conf"; List lines = FileManager.readTextFileSynchronous(context, path); @@ -451,15 +586,28 @@ private void sendResultIntent(int moduleMark, String moduleKeyWord, String binar LocalBroadcastManager.getInstance(context).sendBroadcast(intent); } - private void sendAskForceCloseBroadcast(Context context, String module) { - Intent intent = new Intent(ASK_FORCE_CLOSE); + private void sendAskRestoreDefaults(Context context, ModuleName module) { + Intent intent = new Intent(ASK_RESTORE_DEFAULTS); intent.putExtra("Mark", TOP_FRAGMENT_MARK); intent.putExtra(MODULE_NAME, module); LocalBroadcastManager.getInstance(context).sendBroadcast(intent); } private void checkModulesConfigPatches() { - Patch patch = new Patch(context); + Patch patch = new Patch(context, pathVars); patch.checkPatches(true); } + + private String getFakeSniHosts() { + Set hosts = verifyHostsSet( + preferenceRepository.get().getStringSetPreference(FAKE_SNI_HOSTS) + ); + if (hosts.isEmpty()) { + hosts = new HashSet<>( + Arrays.asList(context.getResources().getStringArray(R.array.default_fake_sni)) + ); + } + return TextUtils.join(",", hosts); + } + } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/patches/Patch.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/patches/Patch.kt index 759232df9..f94bf3790 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/patches/Patch.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/patches/Patch.kt @@ -25,7 +25,7 @@ import androidx.annotation.WorkerThread import androidx.preference.PreferenceManager import pan.alexander.tordnscrypt.App import pan.alexander.tordnscrypt.BuildConfig -import pan.alexander.tordnscrypt.TopFragment.appVersion +import pan.alexander.tordnscrypt.settings.PathVars import pan.alexander.tordnscrypt.utils.Constants.QUAD_DNS_41 import pan.alexander.tordnscrypt.utils.logger.Logger.loge import pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.DNSCRYPT_BOOTSTRAP_RESOLVERS @@ -33,7 +33,7 @@ import java.util.concurrent.atomic.AtomicBoolean private const val SAVED_VERSION_CODE = "SAVED_VERSION_CODE" -class Patch(private val context: Context) { +class Patch(private val context: Context, private val pathVars: PathVars) { private companion object { val patchingIsInProgress = AtomicBoolean(false) @@ -245,7 +245,7 @@ class Patch(private val context: Context) { } private fun enableDNSCryptRequireNoFilterByDefault(savedVersion: Int) { - if (appVersion.endsWith("p") && (savedVersion <= 2143 || savedVersion <= 3143)) { + if (pathVars.appVersion.endsWith("p") && (savedVersion <= 2143 || savedVersion <= 3143)) { PreferenceManager.getDefaultSharedPreferences(context) .edit() diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/proxy/ProxyHelper.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/proxy/ProxyHelper.kt index 583da5008..d5655ad42 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/proxy/ProxyHelper.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/proxy/ProxyHelper.kt @@ -151,6 +151,7 @@ class ProxyHelper @Inject constructor( Socket(proxy).use { it.connect(sockaddr, CHECK_CONNECTION_TIMEOUT_MSEC) + it.soTimeout = 1 if (!it.isConnected) { throw IllegalStateException("unable to connect to $dnsCryptFallbackRes") diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PathVars.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PathVars.java index 937e0dfef..0dbba6d39 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PathVars.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PathVars.java @@ -31,13 +31,19 @@ import java.io.File; import pan.alexander.tordnscrypt.App; +import pan.alexander.tordnscrypt.R; import pan.alexander.tordnscrypt.domain.preferences.PreferenceRepository; +import pan.alexander.tordnscrypt.update.UpdateCheck; import static pan.alexander.tordnscrypt.utils.Constants.IPv4_REGEX; import static pan.alexander.tordnscrypt.utils.Constants.IPv6_REGEX; import static pan.alexander.tordnscrypt.utils.Constants.QUAD_DNS_41; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.DNSCRYPT_BOOTSTRAP_RESOLVERS; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.DNSCRYPT_LISTEN_PORT; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_DNS_PORT; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_HTTP_TUNNEL_PORT; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_SOCKS_PORT; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_TRANS_PORT; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.USE_IPTABLES; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.WAIT_IPTABLES; import static pan.alexander.tordnscrypt.utils.root.RootExecService.LOG_TAG; @@ -48,15 +54,16 @@ @Singleton public class PathVars { private final SharedPreferences preferences; - - private String appDataDir; + private final String appDataDir; + private volatile String appVersion; + private final String appProcVersion; private final String dnscryptPath; private final String torPath; private final String itpdPath; private final String obfsPath; private final String snowflakePath; - private final String conjurePath; + private final String webTunnelPath; private final String nflogPath; private final boolean bbOK; private volatile int appUid = -1; @@ -68,14 +75,14 @@ public class PathVars { preferences = PreferenceManager.getDefaultSharedPreferences(context); - appDataDir = context.getApplicationInfo().dataDir; - - if (appDataDir == null) { - appDataDir = "/data/data/" + context.getPackageName(); - } + String dataDir = context.getApplicationInfo().dataDir; + appDataDir = dataDir != null ? dataDir : "/data/data/" + context.getPackageName(); String nativeLibPath = context.getApplicationInfo().nativeLibraryDir; + appVersion = context.getString(R.string.appVersion); + appProcVersion = context.getString(R.string.appProcVersion); + bbOK = App.getInstance().getDaggerComponent().getPreferenceRepository().get().getBoolPreference("bbOK"); dnscryptPath = nativeLibPath + "/libdnscrypt-proxy.so"; @@ -84,6 +91,7 @@ public class PathVars { obfsPath = nativeLibPath + "/libobfs4proxy.so"; snowflakePath = nativeLibPath + "/libsnowflake.so"; conjurePath = nativeLibPath + "/libconjure.so"; + webTunnelPath = nativeLibPath + "/libwebtunnel.so"; nflogPath = nativeLibPath + "/libnflog.so"; } @@ -212,6 +220,10 @@ public String getConjurePath() { return conjurePath; } + public String getWebTunnelPath() { + return webTunnelPath; + } + public String getNflogPath() { return nflogPath; } @@ -233,7 +245,7 @@ public String getITPDHttpProxyPort() { } public String getTorTransPort() { - String torTransPort = preferences.getString("TransPort", "9040"); + String torTransPort = preferences.getString(TOR_TRANS_PORT, "9040"); if (torTransPort == null) { torTransPort = "9040"; } @@ -245,7 +257,7 @@ public String getDNSCryptFallbackRes() { String dnsCryptFallbackResolvers = preferences.getString(DNSCRYPT_BOOTSTRAP_RESOLVERS, QUAD_DNS_41); StringBuilder fallbackResolvers = new StringBuilder(); - for (String resolver: dnsCryptFallbackResolvers.split(", ?")) { + for (String resolver : dnsCryptFallbackResolvers.split(", ?")) { resolver = resolver .replace("[", "").replace("]", "") .replace("'", "").replace("\"", ""); @@ -268,21 +280,21 @@ public String getDNSCryptFallbackRes() { } public String getTorDNSPort() { - String torDnsPort = preferences.getString("DNSPort", "5400"); + String torDnsPort = preferences.getString(TOR_DNS_PORT, "5400"); return torDnsPort.split(" ")[0] .replaceAll(".+:", "") .replaceAll("\\D+", ""); } public String getTorSOCKSPort() { - String torSocksPort = preferences.getString("SOCKSPort", "9050"); + String torSocksPort = preferences.getString(TOR_SOCKS_PORT, "9050"); return torSocksPort.split(" ")[0] .replaceAll(".+:", "") .replaceAll("\\D+", ""); } public String getTorHTTPTunnelPort() { - String torHttpTunnelPort = preferences.getString("HTTPTunnelPort", "8118"); + String torHttpTunnelPort = preferences.getString(TOR_HTTP_TUNNEL_PORT, "8118"); return torHttpTunnelPort.split(" ")[0] .replaceAll(".+:", "") .replaceAll("\\D+", ""); @@ -428,4 +440,16 @@ public synchronized String getAppUidStr() { } return appUidStr; } + + public String getAppVersion() { + return appVersion; + } + + public void setAppVersion(T ignoredCaller, String version) { + appVersion = version; + } + + public String getAppProcVersion() { + return appProcVersion; + } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesCommonFragment.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesCommonFragment.java index 93ae8d155..f1d953147 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesCommonFragment.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesCommonFragment.java @@ -68,8 +68,6 @@ import pan.alexander.tordnscrypt.vpn.service.ServiceVPNHelper; import static pan.alexander.tordnscrypt.TopFragment.TOP_BROADCAST; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; -import static pan.alexander.tordnscrypt.TopFragment.wrongSign; import static pan.alexander.tordnscrypt.di.SharedPreferencesModule.DEFAULT_PREFERENCES_NAME; import static pan.alexander.tordnscrypt.proxy.ProxyFragmentKt.CLEARNET_APPS_FOR_PROXY; import static pan.alexander.tordnscrypt.settings.tor_preferences.PreferencesTorFragment.ISOLATE_DEST_ADDRESS; @@ -120,6 +118,8 @@ public class PreferencesCommonFragment extends PreferenceFragmentCompat public Lazy defaultPreferences; @Inject public Lazy proxyHelper; + @Inject + public Lazy verifierLazy; private static final int ARP_SCANNER_CHANGE_STATE_DELAY_SEC = 5; @@ -252,7 +252,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Preference shellControl = findPreference("pref_common_shell_control"); - if (appVersion.startsWith("g")) { + if (pathVars.get().getAppVersion().startsWith("g")) { PreferenceCategory hotspotSettingsCategory = findPreference("HOTSPOT"); Preference blockHTTP = findPreference("pref_common_block_http"); if (hotspotSettingsCategory != null && blockHTTP != null) { @@ -307,10 +307,10 @@ public void onResume() { cachedExecutor.submit(() -> { try { - Verifier verifier = new Verifier(context); - String appSign = verifier.getApkSignatureZip(); + Verifier verifier = verifierLazy.get(); + String appSign = verifier.getAppSignature(); String appSignAlt = verifier.getApkSignature(); - if (!verifier.decryptStr(wrongSign, appSign, appSignAlt).equals(TOP_BROADCAST)) { + if (!verifier.decryptStr(verifier.getWrongSign(), appSign, appSignAlt).equals(TOP_BROADCAST)) { NotificationHelper notificationHelper = NotificationHelper.setHelperMessage( context, getString(R.string.verifier_error), "5889"); if (notificationHelper != null && isAdded()) { @@ -397,7 +397,7 @@ public boolean onPreferenceChange(@NonNull Preference preference, Object newValu break; case MULTI_USER_SUPPORT: if (Boolean.parseBoolean(newValue.toString())) { - Utils.allowInteractAcrossUsersPermissionIfRequired(context); + Utils.allowInteractAcrossUsersPermissionIfRequired(context, pathVars.get()); } modulesStatus.setIptablesRulesUpdateRequested(context, true); break; diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesFastFragment.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesFastFragment.java index b40229a8b..8c1378513 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesFastFragment.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesFastFragment.java @@ -26,11 +26,13 @@ import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; +import androidx.appcompat.widget.SwitchCompat; import androidx.fragment.app.DialogFragment; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; @@ -40,24 +42,33 @@ import androidx.preference.SwitchPreference; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import dagger.Lazy; import pan.alexander.tordnscrypt.App; import pan.alexander.tordnscrypt.MainActivity; import pan.alexander.tordnscrypt.R; +import pan.alexander.tordnscrypt.dialogs.FakeSniInputDialogFragment; import pan.alexander.tordnscrypt.dialogs.NotificationDialogFragment; +import pan.alexander.tordnscrypt.dialogs.SniInputListener; import pan.alexander.tordnscrypt.domain.connection_records.ConnectionRecordsInteractorInterface; import pan.alexander.tordnscrypt.domain.preferences.PreferenceRepository; import pan.alexander.tordnscrypt.language.Language; import pan.alexander.tordnscrypt.modules.ModulesAux; +import pan.alexander.tordnscrypt.modules.ModulesRestarter; import pan.alexander.tordnscrypt.modules.ModulesStatus; import pan.alexander.tordnscrypt.nflog.NflogManager; import pan.alexander.tordnscrypt.utils.ThemeUtils; +import pan.alexander.tordnscrypt.views.SwitchPlusClickPreference; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; import static pan.alexander.tordnscrypt.assistance.AccelerateDevelop.accelerated; +import static pan.alexander.tordnscrypt.di.SharedPreferencesModule.DEFAULT_PREFERENCES_NAME; +import static pan.alexander.tordnscrypt.dialogs.FakeSniInputDialogFragmentKt.FAKE_SNI_ARG; +import static pan.alexander.tordnscrypt.utils.Utils.verifyHostsSet; import static pan.alexander.tordnscrypt.utils.jobscheduler.JobSchedulerManager.startRefreshTorUnlockIPs; import static pan.alexander.tordnscrypt.utils.jobscheduler.JobSchedulerManager.stopRefreshTorUnlockIPs; import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; @@ -66,6 +77,8 @@ import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.BLOCK_HTTP; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.BYPASS_LAN; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.CONNECTION_LOGS; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.FAKE_SNI; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.FAKE_SNI_HOSTS; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.MAIN_ACTIVITY_RECREATE; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.SITES_IPS_REFRESH_INTERVAL; import static pan.alexander.tordnscrypt.utils.enums.ModuleState.RUNNING; @@ -73,18 +86,29 @@ import static pan.alexander.tordnscrypt.utils.enums.OperationMode.VPN_MODE; import javax.inject.Inject; +import javax.inject.Named; -public class PreferencesFastFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener { +public class PreferencesFastFragment extends PreferenceFragmentCompat + implements Preference.OnPreferenceChangeListener, + SwitchPlusClickPreference.SwitchPlusClickListener, + SniInputListener { @Inject public Lazy preferenceRepository; @Inject + @Named(DEFAULT_PREFERENCES_NAME) + public Lazy defaultPreferences; + @Inject public Lazy handler; @Inject public Lazy nflogManager; @Inject public Lazy connectionRecordsInteractor; + @Inject + public Lazy pathVars; + @Inject + public Lazy fakeSniInputDialogFragment; private final ModulesStatus modulesStatus = ModulesStatus.getInstance(); @@ -142,6 +166,20 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, pref_fast_language.setOnPreferenceChangeListener(this); } + SwitchPlusClickPreference fakeSni = findPreference(FAKE_SNI); + if (fakeSni != null) { + Set hosts = verifyHostsSet( + preferenceRepository.get().getStringSetPreference(FAKE_SNI_HOSTS) + ); + if (hosts.isEmpty()) { + hosts = new LinkedHashSet<>( + Arrays.asList(context.getResources().getStringArray(R.array.default_fake_sni)) + ); + } + fakeSni.setSummary(TextUtils.join(", ", hosts)); + fakeSni.setSwitchClickListener(this); + } + if (modulesStatus.getMode() == ROOT_MODE || modulesStatus.getMode() == VPN_MODE) { changePreferencesWithRootOrVPNMode(context); @@ -149,11 +187,11 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, changePreferencesWithProxyMode(); } - if (appVersion.startsWith("g")) { + if (pathVars.get().getAppVersion().startsWith("g")) { changePreferencesForGPVersion(); - } else if (appVersion.endsWith("d")) { + } else if (pathVars.get().getAppVersion().endsWith("d")) { changePreferencesForFDVersion(); - } else if (appVersion.startsWith("l")) { + } else if (pathVars.get().getAppVersion().startsWith("l")) { changePreferencesForLiteVersion(); } @@ -164,7 +202,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public void onCreatePreferences(Bundle bundle, String s) { Context context = getActivity(); - if (appVersion.startsWith("g") && !accelerated && context != null) { + if (pathVars.get().getAppVersion().startsWith("g") && !accelerated && context != null) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); if (preferences != null) { preferences.edit().putString("pref_fast_theme", "1").apply(); @@ -223,7 +261,7 @@ private void setUpdateTimeLast(Context context) { + dateString + " " + timeString + System.lineSeparator() + lastUpdateResult); } else if (lastUpdateResult.equals(getString(R.string.update_fault)) && preferenceRepository.get().getStringPreference("updateTimeLast").isEmpty() - && appVersion.startsWith("p")) { + && pathVars.get().getAppVersion().startsWith("p")) { Preference pref_fast_auto_update = findPreference("pref_fast_auto_update"); if (pref_fast_auto_update != null) { pref_fast_auto_update.setEnabled(false); @@ -271,7 +309,7 @@ private void changeTheme() { handler.get().post(() -> { try { - ThemeUtils.setDayNightTheme(context); + ThemeUtils.setDayNightTheme(context, pathVars.get()); activityCurrentRecreate(); } catch (Exception e) { loge("PreferencesFastFragment changeTheme", e); @@ -386,7 +424,7 @@ public boolean onPreferenceChange(@NonNull Preference preference, Object newValu } return true; case "pref_fast_theme": - if (appVersion.startsWith("g") && !accelerated) { + if (pathVars.get().getAppVersion().startsWith("g") && !accelerated) { if (isAdded()) { DialogFragment notificationDialogFragment = NotificationDialogFragment.newInstance(R.string.only_premium_feature); notificationDialogFragment.show(getParentFragmentManager(), "NotificationDialogFragment"); @@ -408,6 +446,28 @@ public boolean onPreferenceChange(@NonNull Preference preference, Object newValu return false; } + + @Override + public void onCheckedChanged(SwitchCompat buttonView, boolean isChecked) { + boolean torRunning = ModulesAux.isTorSavedStateRunning(); + if (torRunning) { + ModulesRestarter.restartTor(getContext()); + modulesStatus.setIptablesRulesUpdateRequested(getContext(), true); + } + } + + @Override + public void onClick(View view) { + FakeSniInputDialogFragment fragment = fakeSniInputDialogFragment.get(); + Bundle bundle = new Bundle(); + Set hosts = verifyHostsSet( + preferenceRepository.get().getStringSetPreference(FAKE_SNI_HOSTS) + ); + bundle.putStringArrayList(FAKE_SNI_ARG, new ArrayList<>(hosts)); + fragment.setArguments(bundle); + fragment.show(getChildFragmentManager(), "FakeSniInputDialogFragment"); + } + private void changePreferencesWithRootOrVPNMode(Context context) { Preference pref_fast_all_through_tor = findPreference(ALL_THROUGH_TOR); if (pref_fast_all_through_tor != null) { @@ -534,4 +594,43 @@ private void changePreferencesForLiteVersion() { prefCheckUpdate.setEnabled(false); } } + + @Override + public void setSni(String text) { + + if (text == null) { + return; + } + + Set sni = verifyHostsSet( + new LinkedHashSet<>(Arrays.asList(text.split(", ?| +|\\n"))) + ); + + Set savedSni = verifyHostsSet( + preferenceRepository.get().getStringSetPreference(FAKE_SNI_HOSTS) + ); + + if (savedSni.size() == sni.size() && savedSni.containsAll(sni)) { + return; + } + + preferenceRepository.get().setStringSetPreference(FAKE_SNI_HOSTS, sni); + + if (sni.isEmpty()) { + sni = new LinkedHashSet<>( + Arrays.asList(getResources().getStringArray(R.array.default_fake_sni)) + ); + } + + SwitchPlusClickPreference fakeSni = findPreference(FAKE_SNI); + if (fakeSni != null) { + fakeSni.setSummary(TextUtils.join(", ", sni)); + } + + boolean torRunning = ModulesAux.isTorSavedStateRunning(); + if (torRunning && defaultPreferences.get().getBoolean(FAKE_SNI, false)) { + ModulesRestarter.restartTor(getContext()); + modulesStatus.setIptablesRulesUpdateRequested(getContext(), true); + } + } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesITPDFragment.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesITPDFragment.java index d61be6ef0..f6aeab05c 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesITPDFragment.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/PreferencesITPDFragment.java @@ -46,7 +46,6 @@ import pan.alexander.tordnscrypt.utils.filemanager.FileManager; import pan.alexander.tordnscrypt.modules.ModulesRestarter; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; import static pan.alexander.tordnscrypt.utils.enums.ModuleState.STOPPED; import static pan.alexander.tordnscrypt.utils.enums.OperationMode.ROOT_MODE; @@ -77,7 +76,7 @@ public void onCreate(Bundle savedInstanceState) { addPreferencesFromResource(R.xml.preferences_i2pd); - if (appVersion.endsWith("p")) { + if (pathVars.get().getAppVersion().endsWith("p")) { changePreferencesForGPVersion(); } @@ -118,7 +117,7 @@ public void onCreate(Bundle savedInstanceState) { for (Preference preference : preferences) { if (preference != null) { preference.setOnPreferenceChangeListener(this); - } else if (!appVersion.startsWith("g")){ + } else if (!pathVars.get().getAppVersion().startsWith("g")){ loge("PreferencesITPDFragment preference is null exception"); } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/SettingsParser.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/SettingsParser.java index 4ed160a09..a37700e5f 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/SettingsParser.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/SettingsParser.java @@ -315,6 +315,12 @@ private void readTorConf(List lines) { case "#Socks5Proxy": editor.putBoolean(TOR_OUTBOUND_PROXY, false); break; + case "TrackHostExits": + editor.putBoolean("Enable TrackHostExits", true); + break; + case "#TrackHostExits": + editor.putBoolean("Enable TrackHostExits", false); + break; } } editor.apply(); diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/dnscrypt_servers/PreferencesDNSCryptServers.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/dnscrypt_servers/PreferencesDNSCryptServers.java index adad2f94f..338866aa9 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/dnscrypt_servers/PreferencesDNSCryptServers.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/dnscrypt_servers/PreferencesDNSCryptServers.java @@ -68,7 +68,6 @@ import pan.alexander.tordnscrypt.utils.filemanager.OnTextFileOperationsCompleteListener; import static pan.alexander.tordnscrypt.TopFragment.TOP_BROADCAST; -import static pan.alexander.tordnscrypt.TopFragment.wrongSign; import static pan.alexander.tordnscrypt.utils.root.RootExecService.LOG_TAG; import javax.inject.Inject; @@ -83,6 +82,8 @@ public class PreferencesDNSCryptServers extends Fragment implements View.OnClick public Lazy pathVars; @Inject public CachedExecutor cachedExecutor; + @Inject + public Lazy verifierLazy; private RecyclerView.Adapter dNSServersAdapter; private ArrayList dnsServerNames; @@ -124,10 +125,10 @@ public void onCreate(@Nullable Bundle savedInstanceState) { cachedExecutor.submit(() -> { try { - Verifier verifier = new Verifier(activity); - String appSign = verifier.getApkSignatureZip(); + Verifier verifier = verifierLazy.get(); + String appSign = verifier.getAppSignature(); String appSignAlt = verifier.getApkSignature(); - if (!verifier.decryptStr(wrongSign, appSign, appSignAlt).equals(TOP_BROADCAST)) { + if (!verifier.decryptStr(verifier.getWrongSign(), appSign, appSignAlt).equals(TOP_BROADCAST)) { NotificationHelper notificationHelper = NotificationHelper.setHelperMessage( activity, getText(R.string.verifier_error).toString(), "6787"); if (notificationHelper != null && isAdded()) { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/dnscrypt_settings/PreferencesDNSFragment.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/dnscrypt_settings/PreferencesDNSFragment.java index 5b16b49f9..c5fab86c3 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/dnscrypt_settings/PreferencesDNSFragment.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/dnscrypt_settings/PreferencesDNSFragment.java @@ -65,7 +65,6 @@ import pan.alexander.tordnscrypt.vpn.service.VpnBuilder; import static android.provider.DocumentsContract.EXTRA_INITIAL_URI; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; import static pan.alexander.tordnscrypt.assistance.AccelerateDevelop.accelerated; import static pan.alexander.tordnscrypt.di.SharedPreferencesModule.DEFAULT_PREFERENCES_NAME; import static pan.alexander.tordnscrypt.utils.Constants.DNSCRYPT_RELAYS_SOURCE_IPV6; @@ -130,7 +129,7 @@ public void onCreate(Bundle savedInstanceState) { checkRootDirAccessible(); - if (appVersion.endsWith("p")) { + if (pathVars.get().getAppVersion().endsWith("p")) { removePreferencesWithGPVersion(); } @@ -166,7 +165,7 @@ public void onCreate(Bundle savedInstanceState) { for (Preference preference : preferences) { if (preference != null) { preference.setOnPreferenceChangeListener(this); - } else if (!appVersion.startsWith("g")) { + } else if (!pathVars.get().getAppVersion().startsWith("g")) { loge("PreferencesDNSFragment preference is null exception"); } } @@ -174,7 +173,7 @@ public void onCreate(Bundle savedInstanceState) { Preference editDNSTomlDirectly = findPreference("editDNSTomlDirectly"); if (editDNSTomlDirectly != null) { editDNSTomlDirectly.setOnPreferenceClickListener(this); - } else if (!appVersion.startsWith("g")) { + } else if (!pathVars.get().getAppVersion().startsWith("g")) { loge("PreferencesDNSFragment preference is null exception"); } @@ -207,7 +206,7 @@ private void registerImportErasePrefs() { for (Preference preference : preferences) { if (preference != null) { preference.setOnPreferenceClickListener(this); - } else if (!appVersion.startsWith("g")) { + } else if (!pathVars.get().getAppVersion().startsWith("g")) { loge("PreferencesDNSFragment preference is null exception"); } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_apps/UnlockTorAppsFragment.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_apps/UnlockTorAppsFragment.java index 19e2e8b1f..595b9f6df 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_apps/UnlockTorAppsFragment.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_apps/UnlockTorAppsFragment.java @@ -35,7 +35,6 @@ import androidx.annotation.Nullable; import androidx.appcompat.widget.SearchView; import androidx.fragment.app.Fragment; -import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -47,7 +46,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; @@ -67,8 +65,6 @@ import pan.alexander.tordnscrypt.utils.integrity.Verifier; import static pan.alexander.tordnscrypt.TopFragment.TOP_BROADCAST; -import static pan.alexander.tordnscrypt.TopFragment.appSign; -import static pan.alexander.tordnscrypt.TopFragment.wrongSign; import static pan.alexander.tordnscrypt.proxy.ProxyFragmentKt.CLEARNET_APPS_FOR_PROXY; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.ALL_THROUGH_TOR; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.FIREWALL_SHOWS_ALL_APPS; @@ -112,6 +108,8 @@ public class UnlockTorAppsFragment extends Fragment implements InstalledApplicat public CachedExecutor cachedExecutor; @Inject public Lazy handler; + @Inject + public Lazy verifierLazy; public UnlockTorAppsFragment() { @@ -203,9 +201,10 @@ public void onResume() { cachedExecutor.submit(() -> { try { - Verifier verifier = new Verifier(context); + Verifier verifier = verifierLazy.get(); + String appSign = verifier.getAppSignature(); String appSignAlt = verifier.getApkSignature(); - if (!verifier.decryptStr(wrongSign, appSign, appSignAlt).equals(TOP_BROADCAST)) { + if (!verifier.decryptStr(verifier.getWrongSign(), appSign, appSignAlt).equals(TOP_BROADCAST)) { NotificationHelper notificationHelper = NotificationHelper.setHelperMessage( context, getString(R.string.verifier_error), "11"); if (notificationHelper != null && isAdded()) { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/BridgeAdapter.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/BridgeAdapter.java index 5f077c262..efa7de989 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/BridgeAdapter.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/BridgeAdapter.java @@ -25,6 +25,7 @@ import static pan.alexander.tordnscrypt.utils.enums.BridgeType.obfs4; import static pan.alexander.tordnscrypt.utils.enums.BridgeType.scramblesuit; import static pan.alexander.tordnscrypt.utils.enums.BridgeType.snowflake; +import static pan.alexander.tordnscrypt.utils.enums.BridgeType.webtunnel; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.USE_DEFAULT_BRIDGES; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.USE_NO_BRIDGES; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.USE_OWN_BRIDGES; @@ -165,7 +166,8 @@ private void bind(int position) { || obfsType.contains(scramblesuit.toString()) || obfsType.contains(meek_lite.toString()) || obfsType.contains(snowflake.toString()) - || obfsType.contains(conjure.toString())) + || obfsType.contains(conjure.toString()) + || obfsType.contains(webtunnel.toString())) && bridgeComponents.length > 1) { tvBridgeText = bridgeComponents[0] + " " + bridgeComponents[1]; } else { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/PreferencesTorBridges.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/PreferencesTorBridges.java index 80191bf09..100db9bfa 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/PreferencesTorBridges.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/PreferencesTorBridges.java @@ -87,10 +87,10 @@ import pan.alexander.tordnscrypt.utils.filemanager.FileManager; import pan.alexander.tordnscrypt.utils.filemanager.OnTextFileOperationsCompleteListener; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; import static pan.alexander.tordnscrypt.di.SharedPreferencesModule.DEFAULT_PREFERENCES_NAME; import static pan.alexander.tordnscrypt.utils.Constants.IPv6_REGEX_NO_BOUNDS; import static pan.alexander.tordnscrypt.utils.enums.BridgeType.conjure; +import static pan.alexander.tordnscrypt.utils.enums.BridgeType.webtunnel; import static pan.alexander.tordnscrypt.utils.enums.ModuleState.STOPPED; import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.DEFAULT_BRIDGES_OBFS; @@ -120,8 +120,10 @@ public class PreferencesTorBridges extends Fragment implements View.OnClickListe OnTextFileOperationsCompleteListener, PreferencesBridges, SwipeRefreshLayout.OnRefreshListener { public final static String SNOWFLAKE_BRIDGES_DEFAULT = "3"; public final static String CONJURE_BRIDGES_DEFAULT = "4"; + public final static String WEB_TUNNEL_BRIDGES_DEFAULT = "5"; public final static String SNOWFLAKE_BRIDGES_OWN = "4"; public final static String CONJURE_BRIDGES_OWN = "5"; + public final static String WEB_TUNNEL_BRIDGES_OWN = "6"; private final static int DEFAULT_VANILLA_BRIDGES_DISPLAY_COUNT = 5; @@ -150,6 +152,7 @@ public class PreferencesTorBridges extends Fragment implements View.OnClickListe private String obfsPath; private String conjurePath; + private String webTunnelPath; private String currentBridgesFilePath; private String bridgesDefaultFilePath; private String bridgesCustomFilePath; @@ -200,6 +203,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { appDataDir = pathVars.get().getAppDataDir(); obfsPath = pathVars.get().getObfsPath(); conjurePath = pathVars.get().getConjurePath(); + webTunnelPath = pathVars.get().getWebTunnelPath(); currentBridgesFilePath = appDataDir + "/app_data/tor/bridges_default.lst"; bridgesDefaultFilePath = appDataDir + "/app_data/tor/bridges_default.lst"; @@ -332,18 +336,10 @@ public void onStop() { if (!bridgesInUse.isEmpty()) { switch (savedBridgesSelector) { - case NO_BRIDGES: - saveUseBridgesPreferences(true, false, false); - break; - case DEFAULT_BRIDGES: - saveUseBridgesPreferences(false, true, false); - break; - case OWN_BRIDGES: - saveUseBridgesPreferences(false, false, true); - break; - default: - saveUseBridgesPreferences(false, false, false); - break; + case NO_BRIDGES -> saveUseBridgesPreferences(true, false, false); + case DEFAULT_BRIDGES -> saveUseBridgesPreferences(false, true, false); + case OWN_BRIDGES -> saveUseBridgesPreferences(false, false, true); + default -> saveUseBridgesPreferences(false, false, false); } } @@ -378,11 +374,18 @@ public void onStop() { clientTransportPlugin = snowflakeConfigurator.get().getConfiguration(); } else if (currentBridgesType.equals(conjure)) { String saveLogsString = ""; - if (appVersion.equals("beta")) { + if (pathVars.get().getAppVersion().equals("beta")) { saveLogsString = " -log " + appDataDir + "/logs/Conjure.log"; } clientTransportPlugin = "ClientTransportPlugin " + currentBridgesTypeToSave + " exec " + conjurePath + saveLogsString; + } else if (currentBridgesType.equals(webtunnel)) { + String saveLogsString = ""; + if (pathVars.get().getAppVersion().equals("beta")) { + saveLogsString = " -log " + appDataDir + "/logs/WebTunnel.log"; + } + clientTransportPlugin = "ClientTransportPlugin " + currentBridgesTypeToSave + " exec " + + webTunnelPath + saveLogsString; } else { clientTransportPlugin = "ClientTransportPlugin " + currentBridgesTypeToSave + " exec " + obfsPath; @@ -684,13 +687,16 @@ private void addBridges(final List persistList) { pattern = Pattern.compile("^scramblesuit +" + bridgeBase + "( +password=\\w+)?"); } else if (inputLinesStr.contains(meek_lite.toString())) { inputBridgesType = meek_lite.toString(); - pattern = Pattern.compile("^meek_lite +" + bridgeBase + " +url=https://[\\w./-]+ +front=[\\w./-]+"); + pattern = Pattern.compile("^meek_lite +" + bridgeBase + " +url=https://[\\w./-]+ +front=[\\w./-]+( +utls=\\w+)?"); } else if (inputLinesStr.contains(snowflake.toString())) { inputBridgesType = snowflake.toString(); pattern = Pattern.compile("^snowflake +" + bridgeBase); } else if (inputLinesStr.contains(conjure.toString())) { inputBridgesType = conjure.toString(); pattern = Pattern.compile("^conjure +" + bridgeBase + ".*"); + } else if (inputLinesStr.contains(webtunnel.toString())) { + inputBridgesType = webtunnel.toString(); + pattern = Pattern.compile("^webtunnel +" + bridgeBase + " +url=http(s)?://[\\w./-]+"); } else { pattern = Pattern.compile(bridgeBase); } @@ -813,9 +819,15 @@ private void addRequestedBridges(String bridgesToAdd, List savedCustomBr } else { ownBridgesOperation(bridgesListNew); } + } else if (bridgesToAdd.contains(webtunnel.toString())) { + if (!spOwnBridges.getSelectedItem().toString().equals(webtunnel.toString())) { + spOwnBridges.setSelection(6); + } else { + ownBridgesOperation(bridgesListNew); + } } else { if (!spOwnBridges.getSelectedItem().toString().equals(vanilla.toString())) { - spOwnBridges.setSelection(6); + spOwnBridges.setSelection(7); } else { ownBridgesOperation(bridgesListNew); } @@ -969,20 +981,17 @@ public void OnFileOperationComplete( if (fileOperationResult && currentFileOperation == readTextFile) { switch (tag) { - case TOR_CONF_FLAG: + case TOR_CONF_FLAG -> { if (lines == null || lines.isEmpty()) { return; } - tor_conf.clear(); bridgesInUse.clear(); - for (String line : lines) { if (!line.trim().isEmpty()) { tor_conf.add(line); } } - for (int i = 0; i < tor_conf.size(); i++) { String line = tor_conf.get(i); if (!line.contains("#") && line.contains("Bridge ")) { @@ -996,7 +1005,6 @@ public void OnFileOperationComplete( bridgesInUse.add(line.trim()); } } - if (!bridgesInUse.isEmpty()) { String testBridge = bridgesInUse.toString(); if (testBridge.contains(obfs4.toString())) { @@ -1011,21 +1019,22 @@ public void OnFileOperationComplete( currentBridgesType = snowflake; } else if (testBridge.contains(conjure.toString())) { currentBridgesType = conjure; + } else if (testBridge.contains(webtunnel.toString())) { + currentBridgesType = webtunnel; } else { currentBridgesType = vanilla; } } else { currentBridgesType = undefined; } - break; - case ADD_BRIDGES_TAG: { + } + case ADD_BRIDGES_TAG -> { final List bridges_lst = lines; if (handler != null && bridges_lst != null) { handler.post(() -> addBridges(bridges_lst)); } - break; } - case DEFAULT_BRIDGES_OPERATION_TAG: { + case DEFAULT_BRIDGES_OPERATION_TAG -> { final List savedDefaultBridges = lines; if (areDefaultVanillaBridgesSelected()) { @@ -1035,21 +1044,18 @@ public void OnFileOperationComplete( if (handler != null && savedDefaultBridges != null) { handler.post(() -> defaultBridgesOperation(savedDefaultBridges)); } - break; } - case OWN_BRIDGES_OPERATION_TAG: { + case OWN_BRIDGES_OPERATION_TAG -> { final List savedCustomBridges = lines; if (handler != null && savedCustomBridges != null) { handler.post(() -> ownBridgesOperation(savedCustomBridges)); } - break; } - case ADD_REQUESTED_BRIDGES_TAG: { + case ADD_REQUESTED_BRIDGES_TAG -> { final List savedCustomBridges = lines; if (handler != null && savedCustomBridges != null) { handler.post(() -> addRequestedBridges(requestedBridgesToAdd, savedCustomBridges)); } - break; } } } @@ -1320,6 +1326,7 @@ private boolean isBridgeVanilla(String bridgeLine) { && !bridgeLine.contains(meek_lite.toString()) && !bridgeLine.contains(snowflake.toString()) && !bridgeLine.contains(conjure.toString()) + && !bridgeLine.contains(webtunnel.toString()) && !bridgeLine.isEmpty(); } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/PreferencesTorBridgesViewModel.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/PreferencesTorBridgesViewModel.kt index 3fc7de863..8c91a37ce 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/PreferencesTorBridgesViewModel.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_bridges/PreferencesTorBridgesViewModel.kt @@ -24,18 +24,29 @@ import androidx.lifecycle.* import kotlinx.coroutines.* import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach +import pan.alexander.tordnscrypt.di.CoroutinesModule import pan.alexander.tordnscrypt.domain.bridges.* +import pan.alexander.tordnscrypt.domain.dns_resolver.DnsInteractor +import pan.alexander.tordnscrypt.utils.enums.BridgeType import pan.alexander.tordnscrypt.utils.logger.Logger.loge import pan.alexander.tordnscrypt.utils.logger.Logger.logw +import java.util.concurrent.ConcurrentHashMap +import java.util.regex.Pattern import javax.inject.Inject -import kotlin.Exception +import javax.inject.Named + +private const val DNS_RESOLVE_TIMEOUT_SEC = 3 @ExperimentalCoroutinesApi class PreferencesTorBridgesViewModel @Inject constructor( private val defaultVanillaBridgeInteractor: DefaultVanillaBridgeInteractor, private val requestBridgesInteractor: RequestBridgesInteractor, - private val bridgesCountriesInteractor: BridgesCountriesInteractor + private val bridgesCountriesInteractor: BridgesCountriesInteractor, + private val dnsInteractor: DnsInteractor, + @Named(CoroutinesModule.DISPATCHER_IO) + private val dispatcherIo: CoroutineDispatcher ) : ViewModel() { private val timeouts = mutableListOf() @@ -58,24 +69,93 @@ class PreferencesTorBridgesViewModel @Inject constructor( private var bridgeCountriesObserveJob: Job? = null private val dialogsFlowMutableLiveData = MutableLiveData() - val dialogsFlowLiveData: LiveData get() = dialogsFlowMutableLiveData.distinctUntilChanged() + val dialogsFlowLiveData: LiveData get() = dialogsFlowMutableLiveData private val errorsMutableLiveData = MutableLiveData() val errorsLiveData: LiveData get() = errorsMutableLiveData + private val webTunnelBridgePattern by lazy { + Pattern.compile("^webtunnel +(.+:\\d+)(?: +\\w+)? +url=(http(s)?://[\\w.-]+)(?:/[\\w.-]+)*/?") + } + + private val webTunnelBridgesMatcherMap by lazy { ConcurrentHashMap() } + fun measureTimeouts(bridges: List) { + if (bridges.isEmpty()) { + return + } + cancelMeasuringTimeouts() if (timeoutsObserveJob?.isCancelled != false) { initBridgeCheckerObserver() } + webTunnelBridgesMatcherMap.clear() + timeoutsMeasurementJob = viewModelScope.launch { - defaultVanillaBridgeInteractor.measureTimeouts(bridges.map { it.bridge }) + + if (bridges.firstOrNull()?.obfsType == BridgeType.webtunnel) { + val bridgesToMeasure = getRealIPFromWebTunnelBridges(ArrayList(bridges)) + launch { + defaultVanillaBridgeInteractor.measureTimeouts(ArrayList(bridgesToMeasure)) + } + searchBridgeCountries(ArrayList(bridgesToMeasure).map { + ObfsBridge( + it, + BridgeType.vanilla, + false + ) + }) + } else { + defaultVanillaBridgeInteractor.measureTimeouts(bridges.map { it.bridge }) + } } } + private suspend fun getRealIPFromWebTunnelBridges(bridges: List) = try { + withContext(dispatcherIo) { + val bridgesToMeasure = mutableListOf() + for (bridge in bridges) { + + val matcher = webTunnelBridgePattern.matcher(bridge.bridge) + if (matcher.find()) { + val ipWithPort = matcher.group(1) ?: continue + val domain = matcher.group(2) ?: continue + val port = if (domain.startsWith("https")) { + 443 + } else { + 80 + } + + val ips = try { + dnsInteractor.resolveDomain(domain, true, DNS_RESOLVE_TIMEOUT_SEC).toList() + } catch (ignored: Exception) { + emptyList() + } + ensureActive() + if (ips.isEmpty()) { + continue + } + val ipsSorted = ips.sortedBy { it.isIPv6Address() } + val address = if (ipsSorted.first().isIPv6Address()) { + "[${ipsSorted.first()}]:$port" + } else { + "${ipsSorted.first()}:$port" + } + val bridgeLine = bridge.bridge.replace(ipWithPort, address) + bridgesToMeasure.add(bridgeLine) + webTunnelBridgesMatcherMap[bridgeLine.hashCode()] = + bridge.bridge.hashCode() + } + } + bridgesToMeasure + } + } catch (ignored: Exception) { + emptyList() + } + fun cancelMeasuringTimeouts() { timeoutsMeasurementJob?.cancelChildren() timeouts.clear() @@ -89,6 +169,12 @@ class PreferencesTorBridgesViewModel @Inject constructor( is BridgePingData -> it.ping != 0 is PingCheckComplete -> true } + }.map { + if (it is BridgePingData && webTunnelBridgesMatcherMap.containsKey(it.bridgeHash)) { + BridgePingData(webTunnelBridgesMatcherMap[it.bridgeHash] ?: 0, it.ping) + } else { + it + } }.onEach { timeouts.add(it) timeoutMutableLiveData.value = timeouts @@ -145,7 +231,8 @@ class PreferencesTorBridgesViewModel @Inject constructor( torBridgesRequestJob?.cancel() torBridgesRequestJob = viewModelScope.launch { try { - val result = requestBridgesInteractor.requestCaptchaChallenge(transport, ipv6Bridges) + val result = + requestBridgesInteractor.requestCaptchaChallenge(transport, ipv6Bridges) dismissRequestBridgesDialogs() showCaptchaDialog(transport, ipv6Bridges, result.first, result.second) } catch (e: CancellationException) { @@ -159,7 +246,12 @@ class PreferencesTorBridgesViewModel @Inject constructor( } } - private fun showCaptchaDialog(transport: String, ipv6Bridges: Boolean, captcha: Bitmap, secretCode: String) { + private fun showCaptchaDialog( + transport: String, + ipv6Bridges: Boolean, + captcha: Bitmap, + secretCode: String + ) { dialogsFlowMutableLiveData.value = DialogsFlowState.CaptchaDialog(transport, ipv6Bridges, captcha, secretCode) } @@ -188,6 +280,7 @@ class PreferencesTorBridgesViewModel @Inject constructor( when (result) { is ParseBridgesResult.BridgesReady -> showBridgesReadyDialog(result.bridges) + is ParseBridgesResult.RecaptchaChallenge -> showCaptchaDialog(transport, ipv6Bridges, result.captcha, result.secretCode) } @@ -208,6 +301,10 @@ class PreferencesTorBridgesViewModel @Inject constructor( return } + if (bridges.first().obfsType == BridgeType.webtunnel) { + return + } + cancelSearchingBridgeCountries() if (bridgeCountriesObserveJob?.isCancelled != false) { @@ -222,7 +319,16 @@ class PreferencesTorBridgesViewModel @Inject constructor( private fun initBridgeCountriesObserver() { bridgeCountriesObserveJob = viewModelScope.launch { bridgesCountriesInteractor.observeBridgeCountries() - .onEach { + .map { + if (webTunnelBridgesMatcherMap.containsKey(it.bridgeHash)) { + BridgeCountryData( + webTunnelBridgesMatcherMap[it.bridgeHash] ?: 0, + it.country + ) + } else { + it + } + }.onEach { bridgeCountries.add(it) bridgeCountriesMutableLiveData.value = bridgeCountries }.collect() diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_ips/UnlockTorIpsFragment.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_ips/UnlockTorIpsFragment.java index 866cbf04e..48e154d09 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_ips/UnlockTorIpsFragment.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_ips/UnlockTorIpsFragment.java @@ -52,8 +52,6 @@ import pan.alexander.tordnscrypt.modules.ModulesStatus; import static pan.alexander.tordnscrypt.TopFragment.TOP_BROADCAST; -import static pan.alexander.tordnscrypt.TopFragment.appSign; -import static pan.alexander.tordnscrypt.TopFragment.wrongSign; import static pan.alexander.tordnscrypt.di.SharedPreferencesModule.DEFAULT_PREFERENCES_NAME; import static pan.alexander.tordnscrypt.utils.enums.OperationMode.ROOT_MODE; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.ALL_THROUGH_TOR; @@ -83,6 +81,8 @@ public class UnlockTorIpsFragment extends Fragment { ViewModelProvider.Factory viewModelFactory; @Inject @Named(DEFAULT_PREFERENCES_NAME) Lazy defaultPreferences; + @Inject + Lazy verifierLazy; public UnlockTorIpsViewModel viewModel; @@ -134,9 +134,10 @@ public void onCreate(Bundle savedInstanceState) { cachedExecutor.submit(() -> { try { - Verifier verifier = new Verifier(activity); + Verifier verifier = verifierLazy.get(); + String appSign = verifier.getAppSignature(); String appSignAlt = verifier.getApkSignature(); - if (!verifier.decryptStr(wrongSign, appSign, appSignAlt).equals(TOP_BROADCAST)) { + if (!verifier.decryptStr(verifier.getWrongSign(), appSign, appSignAlt).equals(TOP_BROADCAST)) { NotificationHelper notificationHelper = NotificationHelper.setHelperMessage( activity, getString(R.string.verifier_error), "123"); if (notificationHelper != null && isAdded()) { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_preferences/PreferencesTorFragment.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_preferences/PreferencesTorFragment.java index c9dfd0d04..5415ad087 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_preferences/PreferencesTorFragment.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/settings/tor_preferences/PreferencesTorFragment.java @@ -54,7 +54,6 @@ import pan.alexander.tordnscrypt.utils.executors.CachedExecutor; import pan.alexander.tordnscrypt.utils.filemanager.FileManager; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; import static pan.alexander.tordnscrypt.utils.Constants.IPv4_REGEX_WITH_MASK; import static pan.alexander.tordnscrypt.utils.Constants.IPv4_REGEX_WITH_PORT; import static pan.alexander.tordnscrypt.utils.Constants.LOOPBACK_ADDRESS; @@ -62,9 +61,13 @@ import static pan.alexander.tordnscrypt.utils.Constants.META_ADDRESS; import static pan.alexander.tordnscrypt.utils.Constants.TOR_VIRTUAL_ADDR_NETWORK_IPV6; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.SNOWFLAKE_RENDEZVOUS; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_DNS_PORT; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_HTTP_TUNNEL_PORT; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_OUTBOUND_PROXY; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_OUTBOUND_PROXY_ADDRESS; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_SOCKS_PORT; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_TETHERING; +import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_TRANS_PORT; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.TOR_USE_IPV6; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.USE_DEFAULT_BRIDGES; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.USE_OWN_BRIDGES; @@ -114,7 +117,7 @@ public void onCreate(Bundle savedInstanceState) { return; } - if (appVersion.endsWith("p")) { + if (pathVars.get().getAppVersion().endsWith("p")) { changePreferencesForGPVersion(); } @@ -134,13 +137,13 @@ public void onCreate(Bundle savedInstanceState) { preferences.add(findPreference("MaxCircuitDirtiness")); preferences.add(findPreference("EnforceDistinctSubnets")); preferences.add(findPreference("Enable SOCKS proxy")); - preferences.add(findPreference("SOCKSPort")); + preferences.add(findPreference(TOR_SOCKS_PORT)); preferences.add(findPreference("Enable HTTPTunnel")); - preferences.add(findPreference("HTTPTunnelPort")); + preferences.add(findPreference(TOR_HTTP_TUNNEL_PORT)); preferences.add(findPreference("Enable Transparent proxy")); - preferences.add(findPreference("TransPort")); + preferences.add(findPreference(TOR_TRANS_PORT)); preferences.add(findPreference("Enable DNS")); - preferences.add(findPreference("DNSPort")); + preferences.add(findPreference(TOR_DNS_PORT)); preferences.add(findPreference("ClientUseIPv4")); preferences.add(findPreference(TOR_USE_IPV6)); preferences.add(findPreference("pref_tor_snowflake_stun")); @@ -149,11 +152,12 @@ public void onCreate(Bundle savedInstanceState) { preferences.add(findPreference("pref_tor_isolate_dest_address")); preferences.add(findPreference("pref_tor_isolate_dest_port")); preferences.add(findPreference(SNOWFLAKE_RENDEZVOUS)); + preferences.add(findPreference("Enable TrackHostExits")); for (Preference preference : preferences) { if (preference != null) { preference.setOnPreferenceChangeListener(this); - } else if (!appVersion.startsWith("g")) { + } else if (!pathVars.get().getAppVersion().startsWith("g")) { Log.e(LOG_TAG, "PreferencesTorFragment preference is null exception"); } } @@ -391,7 +395,25 @@ public boolean onPreferenceChange(@NonNull Preference preference, Object newValu } } return true; - } else if (Objects.equals(preference.getKey(), "DNSPort")) { + } else if (Objects.equals(preference.getKey(), "Enable TrackHostExits")) { + boolean enable = Boolean.parseBoolean(newValue.toString()); + if (!key_tor.contains("TrackHostExits") && !key_tor.contains("#TrackHostExits")) { + int index = key_tor.indexOf("ConnectionPadding"); + if (index > 0) { + key_tor.add(index, "TrackHostExits"); + val_tor.add(index, "."); + } + } + for (int i = 0; i < key_tor.size(); i++) { + String key = key_tor.get(i); + if (enable && key.equals("#TrackHostExits")) { + key_tor.set(i, "TrackHostExits"); + } else if (!enable && key.equals("TrackHostExits")) { + key_tor.set(i, "#TrackHostExits"); + } + } + return true; + } else if (Objects.equals(preference.getKey(), TOR_DNS_PORT)) { String dnsPort = newValue.toString(); boolean useModulesWithRoot = ModulesStatus.getInstance().getMode() == ROOT_MODE @@ -456,9 +478,9 @@ public boolean onPreferenceChange(@NonNull Preference preference, Object newValu .getConfiguration(serversStr)); } return true; - } else if (Objects.equals(preference.getKey(), "SOCKSPort") - || Objects.equals(preference.getKey(), "HTTPTunnelPort") - || Objects.equals(preference.getKey(), "TransPort")) { + } else if (Objects.equals(preference.getKey(), TOR_SOCKS_PORT) + || Objects.equals(preference.getKey(), TOR_HTTP_TUNNEL_PORT) + || Objects.equals(preference.getKey(), TOR_TRANS_PORT)) { String proxyPort = newValue.toString(); String proxyType = preference.getKey(); diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/tiles/TilesLimiter.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/tiles/TilesLimiter.kt index 092a6056d..16d381369 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/tiles/TilesLimiter.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/tiles/TilesLimiter.kt @@ -31,7 +31,6 @@ import androidx.appcompat.app.AlertDialog import androidx.appcompat.view.ContextThemeWrapper import pan.alexander.tordnscrypt.MainActivity import pan.alexander.tordnscrypt.R -import pan.alexander.tordnscrypt.TopFragment.appVersion import pan.alexander.tordnscrypt.assistance.AccelerateDevelop.accelerated import pan.alexander.tordnscrypt.di.SharedPreferencesModule.Companion.DEFAULT_PREFERENCES_NAME import pan.alexander.tordnscrypt.di.tiles.TilesScope @@ -56,7 +55,8 @@ private const val TILES_SAFE_COUNT = 3 class TilesLimiter @Inject constructor( private val appPreferences: dagger.Lazy, @Named(DEFAULT_PREFERENCES_NAME) - private val defaultPreferences: dagger.Lazy + private val defaultPreferences: dagger.Lazy, + private val pathVars: dagger.Lazy ) { private val currentTilesSet by lazy { @@ -81,7 +81,6 @@ class TilesLimiter @Inject constructor( } fun checkActiveTilesCount(service: TileService) { - appVersion = service.getString(R.string.appVersion) applyAppTheme(service) @@ -100,11 +99,11 @@ class TilesLimiter @Inject constructor( showDialog(service, getWarningDialog(service)) } } else { - if (appVersion.endsWith("e") + if (pathVars.get().appVersion.endsWith("e") && wrongRegistrationCode && service is ChangeTorIpTileService) { showDialog(service, getDonateDialogForLite(service)) - } else if (appVersion.endsWith("p") && !accelerated) { + } else if (pathVars.get().appVersion.endsWith("p") && !accelerated) { showDialog(service, getDonateDialogForGp(service)) } } @@ -113,7 +112,7 @@ class TilesLimiter @Inject constructor( private fun applyAppTheme(service: TileService) { if (!themeApplied) { try { - ThemeUtils.setDayNightTheme(service) + ThemeUtils.setDayNightTheme(service, pathVars.get()) themeApplied = true } catch (e: Exception) { loge("TilesLimiter applyAppTheme", e) diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/tor_fragment/TorFragmentPresenter.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/tor_fragment/TorFragmentPresenter.java index 18b925831..528441cbe 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/tor_fragment/TorFragmentPresenter.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/tor_fragment/TorFragmentPresenter.java @@ -52,14 +52,13 @@ import pan.alexander.tordnscrypt.modules.ModulesKiller; import pan.alexander.tordnscrypt.modules.ModulesRunner; import pan.alexander.tordnscrypt.modules.ModulesStatus; +import pan.alexander.tordnscrypt.settings.PathVars; import pan.alexander.tordnscrypt.utils.executors.CachedExecutor; import pan.alexander.tordnscrypt.utils.integrity.Verifier; import pan.alexander.tordnscrypt.utils.enums.ModuleState; import pan.alexander.tordnscrypt.vpn.service.ServiceVPNHelper; import static pan.alexander.tordnscrypt.TopFragment.TOP_BROADCAST; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; -import static pan.alexander.tordnscrypt.TopFragment.wrongSign; import static pan.alexander.tordnscrypt.utils.jobscheduler.JobSchedulerManager.stopRefreshTorUnlockIPs; import static pan.alexander.tordnscrypt.utils.preferences.PreferenceKeys.IGNORE_SYSTEM_DNS; import static pan.alexander.tordnscrypt.utils.root.RootExecService.LOG_TAG; @@ -85,6 +84,10 @@ public class TorFragmentPresenter implements TorFragmentPresenterInterface, public Lazy torInteractor; @Inject public CachedExecutor cachedExecutor; + @Inject + public Lazy verifierLazy; + @Inject + public Lazy pathVars; public TorFragmentView view; @@ -494,7 +497,9 @@ private void checkInvizibleUpdates(MainActivity activity) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); boolean throughTorUpdate = sharedPreferences.getBoolean("pref_fast through_tor_update", false); boolean autoUpdate = sharedPreferences.getBoolean("pref_fast_auto_update", true) - && !appVersion.startsWith("l") && !appVersion.endsWith("p") && !appVersion.startsWith("f"); + && !pathVars.get().getAppVersion().startsWith("l") + && !pathVars.get().getAppVersion().endsWith("p") + && !pathVars.get().getAppVersion().startsWith("f"); String lastUpdateResult = preferenceRepository.get().getStringPreference("LastUpdateResult"); @@ -584,10 +589,10 @@ public void startButtonOnClick() { } try { - Verifier verifier = new Verifier(activity); - String appSign = verifier.getApkSignatureZip(); + Verifier verifier = verifierLazy.get(); + String appSign = verifier.getAppSignature(); String appSignAlt = verifier.getApkSignature(); - if (!verifier.decryptStr(wrongSign, appSign, appSignAlt).equals(TOP_BROADCAST)) { + if (!verifier.decryptStr(verifier.getWrongSign(), appSign, appSignAlt).equals(TOP_BROADCAST)) { NotificationHelper notificationHelper = NotificationHelper.setHelperMessage( activity, context.getString(R.string.verifier_error), "15"); if (notificationHelper != null) { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/update/UpdateCheck.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/update/UpdateCheck.java index 5601b429e..7c19ac995 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/update/UpdateCheck.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/update/UpdateCheck.java @@ -51,10 +51,11 @@ import pan.alexander.tordnscrypt.R; import pan.alexander.tordnscrypt.TopFragment; import pan.alexander.tordnscrypt.domain.preferences.PreferenceRepository; +import pan.alexander.tordnscrypt.settings.PathVars; +import pan.alexander.tordnscrypt.utils.executors.CachedExecutor; +import pan.alexander.tordnscrypt.utils.integrity.Verifier; import pan.alexander.tordnscrypt.utils.web.HttpsConnectionManager; -import static pan.alexander.tordnscrypt.TopFragment.appProcVersion; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; import static pan.alexander.tordnscrypt.dialogs.Registration.wrongRegistrationCode; import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; import static pan.alexander.tordnscrypt.utils.logger.Logger.logw; @@ -65,14 +66,20 @@ public class UpdateCheck { public Lazy preferenceRepository; @Inject public Lazy httpsConnectionManager; + @Inject + public Lazy verifier; + @Inject + public Lazy cachedExecutor; + @Inject + public Lazy pathVars; private static final int CONNECT_TIMEOUT = 30; private static final int READ_TIMEOUT = 30; private final TopFragment topFragment; private final Context context; - private static PublicKey publicKey; - private static PrivateKey privateKey; + private volatile static PublicKey publicKey; + private volatile static PrivateKey privateKey; public UpdateCheck(TopFragment topFragment) { App.getInstance().getDaggerComponent().inject(this); @@ -130,8 +137,8 @@ private String RSASign(final String appSignature) { String signature = appSignature.trim() + convertKeyForPHP(publicKey.getEncoded()).trim() + - appProcVersion.trim() + - appVersion.trim() + + pathVars.get().getAppProcVersion().trim() + + pathVars.get().getAppVersion().trim() + "submit"; MessageDigest md = MessageDigest.getInstance("SHA-256"); @@ -154,13 +161,13 @@ private String bin2hex(byte[] data) { private void compareVersions(String serverAnswer) { - if (!serverAnswer.toLowerCase().contains(appProcVersion.toLowerCase())) { + if (!serverAnswer.toLowerCase().contains(pathVars.get().getAppProcVersion().toLowerCase())) { showUpdateMessageAndSaveResult(R.string.update_fault); loge("compareVersions function fault " + serverAnswer); return; } - serverAnswer = serverAnswer.toLowerCase().replace(appProcVersion.toLowerCase(), "").trim(); + serverAnswer = serverAnswer.toLowerCase().replace(pathVars.get().getAppProcVersion().toLowerCase(), "").trim(); String[] modulesArr = serverAnswer.split(";"); if (modulesArr.length < 1) { showUpdateMessageAndSaveResult(R.string.update_fault); @@ -202,11 +209,11 @@ private void compareVersions(String serverAnswer) { int currentIPROversion = Integer.parseInt(BuildConfig.VERSION_NAME.replaceAll("\\D+", "")); if (currentIPROversion < Integer.parseInt(iproArr[1].replaceAll("\\D+", "")) - || appVersion.startsWith("l")) { + || pathVars.get().getAppVersion().startsWith("l")) { String message; - if (appVersion.endsWith("e")) { + if (pathVars.get().getAppVersion().endsWith("e")) { message = activity.getString(R.string.thanks_for_donate); - appVersion = "pfrzo".replace("f", "").replace("z", ""); + pathVars.get().setAppVersion(this, "pfrzo".replace("f", "").replace("z", "")); SharedPreferences sPref = PreferenceManager.getDefaultSharedPreferences(activity); SharedPreferences.Editor editor = sPref.edit(); @@ -216,7 +223,7 @@ private void compareVersions(String serverAnswer) { message = activity.getString(R.string.update_ipro_has_apdate) + " " + activity.getString(R.string.update_new_version) + " " + iproArr[1]; } - String iproName = "InviZible_" + appVersion.toUpperCase() + "_ver." + iproArr[1] + "_" + appProcVersion + ".apk"; + String iproName = "InviZible_" + pathVars.get().getAppVersion().toUpperCase() + "_ver." + iproArr[1] + "_" + pathVars.get().getAppProcVersion() + ".apk"; String iproUpdateStr = iproArr[2]; String iproHash = iproArr[3]; @@ -234,17 +241,17 @@ private String convertKeyForPHP(byte[] key) { return Base64.encodeToString(key, Base64.DEFAULT); } - public synchronized Future requestUpdateData(final String domainName, final String appSign) { - if (appVersion.endsWith("p") || appVersion.startsWith("f")) { + public synchronized Future requestUpdateData(final String domainName) { + if (pathVars.get().getAppVersion().endsWith("p") || pathVars.get().getAppVersion().startsWith("f")) { return null; } - return App.getInstance().getDaggerComponent().getCachedExecutor().submit(() -> { + return cachedExecutor.get().submit(() -> { String serverAnswerEncoded = ""; String serverAnswer = ""; try { - String rsaSign = RSASign(appSign); + String rsaSign = RSASign(verifier.get().getAppSignature()); if (rsaSign == null) { showUpdateMessageAndSaveResult(R.string.update_fault); @@ -257,8 +264,8 @@ public synchronized Future requestUpdateData(final String domainName, final S HashMap request = new HashMap<>(); request.put("sign", rsaSign); request.put("key", convertKeyForPHP(publicKey.getEncoded())); - request.put("app_proc_version", appProcVersion); - request.put("app_version", appVersion); + request.put("app_proc_version", pathVars.get().getAppProcVersion()); + request.put("app_version", pathVars.get().getAppVersion()); request.put("registration_code", registrationCode.replaceAll("\\W", "")); request.put("submit", "submit"); diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/update/UpdateService.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/update/UpdateService.java index 626fa42f3..a1fbc2d4c 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/update/UpdateService.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/update/UpdateService.java @@ -19,6 +19,8 @@ package pan.alexander.tordnscrypt.update; +import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; + import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationChannel; @@ -262,7 +264,8 @@ void sendNotification(int serviceStartId, int notificationId, long startTime, St .setUsesChronometer(true) .setChannelId(UPDATE_CHANNEL_ID) .setPriority(Notification.PRIORITY_DEFAULT) - .setVisibility(NotificationCompat.VISIBILITY_PRIVATE); + .setVisibility(NotificationCompat.VISIBILITY_PRIVATE) + .setProgress(100, 100, true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { builder.setCategory(Notification.CATEGORY_PROGRESS); @@ -274,10 +277,14 @@ void sendNotification(int serviceStartId, int notificationId, long startTime, St Notification notification = builder.build(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - startForeground(notificationId, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST); - } else { - startForeground(notificationId, notification); + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + startForeground(notificationId, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST); + } else { + startForeground(notificationId, notification); + } + } catch (Exception e) { + loge("UpdateService sendNotification", e, true); } } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/Constants.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/Constants.java index d078a6aa6..cc0e2697e 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/Constants.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/Constants.java @@ -107,4 +107,6 @@ public interface Constants { String IPv6_REGEX_WITH_MASK = "^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$"; String NUMBER_REGEX = "\\d+"; + + String HOST_NAME_REGEX = "^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])(\\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]))*$"; } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/ThemeUtils.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/ThemeUtils.kt index bc63f2fa3..08a5e6346 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/ThemeUtils.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/ThemeUtils.kt @@ -23,17 +23,17 @@ import android.content.Context import android.util.Log import androidx.appcompat.app.AppCompatDelegate import androidx.preference.PreferenceManager -import pan.alexander.tordnscrypt.TopFragment.appVersion import pan.alexander.tordnscrypt.assistance.AccelerateDevelop.accelerated +import pan.alexander.tordnscrypt.settings.PathVars import pan.alexander.tordnscrypt.utils.root.RootExecService.LOG_TAG import java.lang.Exception object ThemeUtils { @JvmStatic @Suppress("deprecation") - fun setDayNightTheme(context: Context) { + fun setDayNightTheme(context: Context, pathVars: PathVars) { try { - val theme = if (appVersion.startsWith("g") && !accelerated) { + val theme = if (pathVars.appVersion.startsWith("g") && !accelerated) { "1" } else { val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/Utils.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/Utils.kt index d6619a4f7..1a480d479 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/Utils.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/Utils.kt @@ -26,15 +26,16 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.content.res.Configuration +import android.content.res.Resources import android.graphics.Point import android.os.Build import android.os.Environment import android.os.Process import android.util.Base64 +import android.util.TypedValue import android.view.Display import androidx.core.content.ContextCompat import androidx.preference.PreferenceManager -import pan.alexander.tordnscrypt.TopFragment.appVersion import pan.alexander.tordnscrypt.domain.preferences.PreferenceRepository import pan.alexander.tordnscrypt.modules.ModulesService import pan.alexander.tordnscrypt.modules.ModulesStatus @@ -42,6 +43,8 @@ import pan.alexander.tordnscrypt.settings.PathVars import pan.alexander.tordnscrypt.settings.tor_apps.ApplicationData.Companion.SPECIAL_UID_CONNECTIVITY_CHECK import pan.alexander.tordnscrypt.settings.tor_bridges.PreferencesTorBridges import pan.alexander.tordnscrypt.utils.Constants.DNS_DEFAULT_UID +import pan.alexander.tordnscrypt.utils.Constants.HOST_NAME_REGEX +import pan.alexander.tordnscrypt.utils.Constants.IPv4_REGEX import pan.alexander.tordnscrypt.utils.Constants.NETWORK_STACK_DEFAULT_UID import pan.alexander.tordnscrypt.utils.appexit.AppExitDetectService import pan.alexander.tordnscrypt.utils.filemanager.FileShortener @@ -88,6 +91,13 @@ object Utils { return (dips * context.resources.displayMetrics.density + 0.5f).roundToInt() } + fun dp2pixels(dp: Int) = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dp.toFloat(), + Resources.getSystem().displayMetrics + ) + + fun getDeviceIP(): String { try { val en = NetworkInterface.getNetworkInterfaces() @@ -257,7 +267,8 @@ object Utils { val shPref = PreferenceManager.getDefaultSharedPreferences(context) val showHelperMessages = shPref.getBoolean(ALWAYS_SHOW_HELP_MESSAGES, false) - if (showHelperMessages && (bridgesConjureDefault || bridgesConjureOwn)) { + val betaVersion = pathVars.appVersion.equals("beta") + if ((showHelperMessages || betaVersion) && (bridgesConjureDefault || bridgesConjureOwn)) { FileShortener.shortenTooTooLongFile(pathVars.appDataDir + "/logs/Conjure.log") } } catch (e: Exception) { @@ -265,6 +276,29 @@ object Utils { } } + @JvmStatic + fun shortenTooLongWebTunnelLog( + context: Context, + preferences: PreferenceRepository, + pathVars: PathVars + ) { + try { + val bridgesWebTunnelDefault = + preferences.getStringPreference(DEFAULT_BRIDGES_OBFS) == PreferencesTorBridges.WEB_TUNNEL_BRIDGES_DEFAULT + val bridgesWebTunnelOwn = + preferences.getStringPreference(OWN_BRIDGES_OBFS) == PreferencesTorBridges.WEB_TUNNEL_BRIDGES_OWN + val shPref = PreferenceManager.getDefaultSharedPreferences(context) + val showHelperMessages = + shPref.getBoolean(ALWAYS_SHOW_HELP_MESSAGES, false) + val betaVersion = pathVars.appVersion.equals("beta") + if ((showHelperMessages || betaVersion) && (bridgesWebTunnelDefault || bridgesWebTunnelOwn)) { + FileShortener.shortenTooTooLongFile(pathVars.appDataDir + "/logs/WebTunnel.log") + } + } catch (e: Exception) { + loge("ShortenTooLongWebTunnelLog exception", e) + } + } + fun getUidForName(name: String, defaultValue: Int): Int { var uid = defaultValue try { @@ -292,9 +326,10 @@ object Utils { @JvmStatic fun allowInteractAcrossUsersPermissionIfRequired( - context: Context + context: Context, + pathVars: PathVars ) { - if (!appVersion.endsWith("p") + if (!pathVars.appVersion.endsWith("p") && ModulesStatus.getInstance().isRootAvailable && !isInteractAcrossUsersPermissionGranted(context) ) { @@ -324,4 +359,11 @@ object Utils { fun areNotificationsNotAllowed(notificationManager: NotificationManager) = !areNotificationsAllowed(notificationManager) + @JvmStatic + fun verifyHostsSet(hosts: Set) = + hosts.filter { + it.length < 255 + && (it.matches(HOST_NAME_REGEX.toRegex()) || it.matches(IPv4_REGEX.toRegex())) + }.toSet() + } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/apps/InstalledApplicationsManager.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/apps/InstalledApplicationsManager.kt index 2ca8813a5..2c87c5d33 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/apps/InstalledApplicationsManager.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/apps/InstalledApplicationsManager.kt @@ -82,7 +82,7 @@ class InstalledApplicationsManager private constructor( try { if (multiUserSupport) { - allowInteractAcrossUsersPermissionIfRequired(context) + allowInteractAcrossUsersPermissionIfRequired(context, pathVars) } reentrantLock.lockInterruptibly() @@ -258,6 +258,8 @@ class InstalledApplicationsManager private constructor( } } } + } catch (ignored: PackageManager.NameNotFoundException) { + useInternet = true } catch (e: Exception) { useInternet = true logw("InstalledApplications isAppUseInternet", e) diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/connectionchecker/SocketInternetChecker.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/connectionchecker/SocketInternetChecker.kt index ea2ef9bdc..d3dad9da3 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/connectionchecker/SocketInternetChecker.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/connectionchecker/SocketInternetChecker.kt @@ -54,6 +54,7 @@ class SocketInternetChecker @Inject constructor() { InetSocketAddress(InetAddress.getByName(ip), port) socket.connect(sockAddress, CONNECT_TIMEOUT_SEC * 1000) + socket.soTimeout = 100 return if (isProxyUsed(proxyAddress, proxyPort)) { socket.inetAddress.isReachable(CHECK_ADDRESS_REACHABLE_TIMEOUT_SEC * 1000) @@ -95,6 +96,7 @@ class SocketInternetChecker @Inject constructor() { InetSocketAddress(InetAddress.getByName(ip), port) socket.connect(sockAddress, PING_TIMEOUT_SEC * 1000) + socket.soTimeout = 100 if (isProxyUsed(proxyAddress, proxyPort)) { if (socket.inetAddress.isReachable(CHECK_ADDRESS_REACHABLE_TIMEOUT_SEC * 1000)) { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/enums/BridgeType.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/enums/BridgeType.java index d15ec4edf..8c53aa0bf 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/enums/BridgeType.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/enums/BridgeType.java @@ -27,5 +27,6 @@ public enum BridgeType { vanilla, snowflake, conjure, + webtunnel, undefined } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/enums/ModuleName.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/enums/ModuleName.kt new file mode 100644 index 000000000..1f670daa6 --- /dev/null +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/enums/ModuleName.kt @@ -0,0 +1,26 @@ +/* + This file is part of InviZible Pro. + + InviZible Pro is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InviZible Pro is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with InviZible Pro. If not, see . + + Copyright 2019-2023 by Garmatin Oleksandr invizible.soft@gmail.com + */ + +package pan.alexander.tordnscrypt.utils.enums + +enum class ModuleName(val moduleName: String) { + DNSCRYPT_MODULE("DNSCrypt"), + TOR_MODULE("Tor"), + ITPD_MODULE("I2P") +} diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/executors/CachedExecutor.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/executors/CachedExecutor.kt index 21bd6e75e..e5806e740 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/executors/CachedExecutor.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/executors/CachedExecutor.kt @@ -19,26 +19,40 @@ package pan.alexander.tordnscrypt.utils.executors -import android.util.Log -import pan.alexander.tordnscrypt.utils.root.RootExecService.LOG_TAG -import java.lang.Exception +import pan.alexander.tordnscrypt.utils.logger.Logger.loge import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.Future +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeoutException import javax.inject.Inject import javax.inject.Singleton +import kotlin.Exception @Singleton class CachedExecutor @Inject constructor() { - val executorService: ExecutorService by lazy { Executors.newCachedThreadPool() } + private val executorService: ExecutorService by lazy { Executors.newCachedThreadPool() } @Synchronized fun submit(block: Runnable): Future<*>? = try { executorService.submit(block) } catch (e: Exception) { - Log.e(LOG_TAG, "CachedExecutor ${e.javaClass} ${e.message} ${e.cause}") + loge("CachedExecutor submit", e) null } + + //For testing purposes + @Suppress("unused") + private fun checkTimeout(future: Future<*>) { + executorService.submit { + try { + future.get(2, TimeUnit.MINUTES) + } catch (e: TimeoutException) { + loge("CachedExecutor checkTimeout", e) + } catch (ignored: Exception) { + } + } + } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/integrity/Verifier.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/integrity/Verifier.java index b45e7a4df..c1ebe52e9 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/integrity/Verifier.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/integrity/Verifier.java @@ -24,7 +24,6 @@ import android.content.pm.PackageManager; import android.content.pm.Signature; import android.util.Base64; -import android.util.Log; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; @@ -45,29 +44,30 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; +import javax.inject.Singleton; import dagger.Lazy; -import pan.alexander.tordnscrypt.App; +import pan.alexander.tordnscrypt.R; import pan.alexander.tordnscrypt.TopFragment; import pan.alexander.tordnscrypt.settings.PathVars; -import static pan.alexander.tordnscrypt.TopFragment.appVersion; -import static pan.alexander.tordnscrypt.utils.root.RootExecService.LOG_TAG; +import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; +import static pan.alexander.tordnscrypt.utils.logger.Logger.logi; +@Singleton public class Verifier { - - @Inject public Lazy pathVars; - public Context context; + private volatile String apkSignature; - public Verifier(Context context) { - App.getInstance().getDaggerComponent().inject(this); + @Inject + public Verifier(Context context, Lazy pathVars) { this.context = context; + this.pathVars = pathVars; } - public String getApkSignatureZip() throws Exception { + private String getApkSignatureZip() throws Exception { File apkFile = new File(context.getApplicationInfo().sourceDir); @@ -77,27 +77,29 @@ public String getApkSignatureZip() throws Exception { ZipEntry ze = entries.nextElement(); String name = ze.getName().toUpperCase(); if (name.startsWith("META-INF/") && (name.endsWith(".RSA") || name.endsWith(".DSA"))) { - InputStream inputStream = zipFile.getInputStream(ze); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[8192]; - int len; - while ((len = inputStream.read(buffer)) != -1) { - baos.write(buffer, 0, len); + try(InputStream inputStream = zipFile.getInputStream(ze); + ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + byte[] buffer = new byte[8192]; + int len; + while ((len = inputStream.read(buffer)) != -1) { + baos.write(buffer, 0, len); + } + byte[] byteSign = baos.toByteArray(); + byteSign = CertificateFactory.getInstance("X509").generateCertificate(new ByteArrayInputStream(byteSign)).getEncoded(); + return Base64.encodeToString(MessageDigest.getInstance("md5").digest(byteSign), Base64.DEFAULT); + } finally { + zipFile.close(); } - baos.close(); - inputStream.close(); - zipFile.close(); - byte[] byteSign = baos.toByteArray(); - byteSign = CertificateFactory.getInstance("X509").generateCertificate(new ByteArrayInputStream(byteSign)).getEncoded(); - return Base64.encodeToString(MessageDigest.getInstance("md5").digest(byteSign), Base64.DEFAULT); } } - return null; + loge("Verifier unable to get signature from zip. Use the conventional method instead."); + + return getApkSignature(); } @SuppressWarnings("unused") - public String getApkSignatureZipModern() throws Exception { + private String getApkSignatureZipModern() throws Exception { File apkFile = new File(context.getApplicationInfo().sourceDir); ZipFile zipFile = new ZipFile(apkFile); ZipEntry ze = zipFile.getEntry("META-INF/CERT.RSA"); @@ -142,7 +144,7 @@ public String decryptStr(String text, String key, String vector) throws Exceptio byte[] ivBytes = vector.substring(vector.length() - 16).getBytes(); cipher.init(Cipher.DECRYPT_MODE, aesKey, new IvParameterSpec(ivBytes)); byte[] decrypted = Base64.decode(text.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT); - if (appVersion.endsWith("d")) { + if (pathVars.get().getAppVersion().endsWith("d")) { return new String(decrypted); } return new String(cipher.doFinal(decrypted)); @@ -165,9 +167,9 @@ public void encryptStr(String text, String key, String vector) { File f = new File(pathVars.get().getAppDataDir() + "/logs"); if (f.mkdirs() && f.setReadable(true) && f.setWritable(true)) { - Log.i(LOG_TAG, "encryptStr log dir created"); + logi("encryptStr log dir created"); } else { - Log.e(LOG_TAG, "encryptStr Unable to create and chmod log dir"); + loge("encryptStr Unable to create and chmod log dir"); } PrintWriter writer = new PrintWriter( @@ -185,8 +187,23 @@ public void encryptStr(String text, String key, String vector) { } catch (Exception e) { - Log.e(LOG_TAG, "encryptStr Failed " + e.getMessage() + " " + e.getCause()); + loge("encryptStr Failed", e); + } + } + + public String getWrongSign() { + return context.getString(R.string.encoded).trim(); + } + + public String getAppSignature() throws Exception { + if (apkSignature == null) { + synchronized (Verifier.class) { + if (apkSignature == null) { + apkSignature = getApkSignatureZip(); + } + } } + return apkSignature; } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/notification/NotificationPermissionDialog.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/notification/NotificationPermissionDialog.kt index e7a989ceb..30937c1c4 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/notification/NotificationPermissionDialog.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/notification/NotificationPermissionDialog.kt @@ -48,7 +48,7 @@ class NotificationPermissionDialog: ExtendedDialogFragment() { val builder = AlertDialog.Builder(requireActivity(), R.style.CustomAlertDialogTheme) builder.setMessage(getString(R.string.notifications_permission_rationale_message)) - .setTitle(R.string.ask_force_close_title) + .setTitle(R.string.reset_settings_title) .setPositiveButton(R.string.ok) { _, _ -> if (activity?.isFinishing == false) { launcher?.let { diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/parsers/TorProjectBridgesParser.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/parsers/TorProjectBridgesParser.kt index 3bfc4d9cf..f0c374fa1 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/parsers/TorProjectBridgesParser.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/parsers/TorProjectBridgesParser.kt @@ -57,6 +57,13 @@ class TorProjectBridgesParser @Inject constructor() { Pattern.compile("obfs4 +$ipv6BridgeBase +cert=.+ +iat-mode=\\d") } + private val webTunnelBridgePatternIPv4 by lazy { + Pattern.compile("webtunnel +$ipv4BridgeBase +url=http(s)?://[\\w./-]+") + } + private val webTunnelBridgePatternIPv6 by lazy { + Pattern.compile("webtunnel +$ipv6BridgeBase +url=http(s)?://[\\w./-]+") + } + @Throws(IOException::class) fun parseCaptchaImage(inputStream: InputStream): Pair { @@ -177,6 +184,8 @@ class TorProjectBridgesParser @Inject constructor() { private fun parseBridge(line: String): String? = if (containsObfs4Bridge(line)) { parseObfs4Bridge(line) + } else if (containsWebTunnelBridge(line)) { + parseWebTunnelBridge(line) } else { parseVanillaBridge(line) } @@ -198,6 +207,22 @@ class TorProjectBridgesParser @Inject constructor() { return null } + private fun parseWebTunnelBridge(line: String): String? { + val matcherIPv4 = webTunnelBridgePatternIPv4.matcher(line) + if (matcherIPv4.find()) { + return matcherIPv4.group() + } + + val matcherIPv6 = webTunnelBridgePatternIPv6.matcher(line) + if (matcherIPv6.find()) { + return matcherIPv6.group() + } + + loge("TorProjectBridgesParser parseWebTunnelBridge failed $line") + + return null + } + private fun parseVanillaBridge(line: String): String? { val matcherIPv4 = vanillaBridgePatternIPv4.matcher(line) if (matcherIPv4.find()) { @@ -215,4 +240,6 @@ class TorProjectBridgesParser @Inject constructor() { } private fun containsObfs4Bridge(line: String): Boolean = line.contains("obfs4") + + private fun containsWebTunnelBridge(line: String): Boolean = line.contains("webtunnel") } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/portchecker/PortChecker.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/portchecker/PortChecker.java new file mode 100644 index 000000000..ed869e6ba --- /dev/null +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/portchecker/PortChecker.java @@ -0,0 +1,94 @@ +/* + This file is part of InviZible Pro. + + InviZible Pro is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InviZible Pro is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with InviZible Pro. If not, see . + + Copyright 2019-2023 by Garmatin Oleksandr invizible.soft@gmail.com + */ + +package pan.alexander.tordnscrypt.utils.portchecker; + +import static pan.alexander.tordnscrypt.utils.Constants.LOOPBACK_ADDRESS; +import static pan.alexander.tordnscrypt.utils.Constants.NUMBER_REGEX; +import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; + +import java.net.ConnectException; +import java.net.DatagramSocket; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketTimeoutException; + +import javax.inject.Inject; + +public class PortChecker { + + @Inject + public PortChecker() { + } + + public boolean isPortBusy(String port) { + int portInt; + if (port.matches(NUMBER_REGEX)) { + portInt = Integer.parseInt(port); + } else { + return true; + } + return !isPortAvailable(portInt); + } + + public boolean isPortAvailable(int port) { + if (isTCPPortAvailable(port)) { + return isUDPPortAvailable(port); + } + return false; + } + + public String getFreePort(String port) { + + if (!port.matches(NUMBER_REGEX)) { + return port; + } + + int portInt = Integer.parseInt(port); + + for (int i = 0; i < 3; i++) { + int freePort = portInt + i + 1; + if (isPortAvailable(freePort)) { + return String.valueOf(freePort); + } + } + return port; + } + + private boolean isTCPPortAvailable(int port) { + try (Socket socket = new Socket()) { + socket.connect(new InetSocketAddress(LOOPBACK_ADDRESS, port), 200); + socket.setSoTimeout(1); + return false; + } catch (ConnectException | SocketTimeoutException e) { + return true; + } catch (Exception e) { + return false; + } + } + + private boolean isUDPPortAvailable(int port) { + try (DatagramSocket socket = new DatagramSocket(port)) { + socket.setSoTimeout(1); + return true; + } catch (Exception ignored) { + } + return false; + } +} diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/preferences/PreferenceKeys.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/preferences/PreferenceKeys.java index 55782abff..f648b5b17 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/preferences/PreferenceKeys.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/preferences/PreferenceKeys.java @@ -68,6 +68,7 @@ public interface PreferenceKeys { String USE_NO_BRIDGES = "useNoBridges"; String USE_DEFAULT_BRIDGES = "useDefaultBridges"; String USE_OWN_BRIDGES = "useOwnBridges"; + String FAKE_SNI_HOSTS = "fakeSniHosts"; String NOTIFICATIONS_ARE_BLOCKED = "notificationsAreBlocked"; @@ -81,6 +82,7 @@ public interface PreferenceKeys { String ALL_THROUGH_TOR = "pref_fast_all_through_tor"; String BYPASS_LAN = "Allow LAN"; String AUTO_START_DELAY = "pref_fast_autostart_delay"; + String FAKE_SNI = "swFakeSni"; //Common Settings String ARP_SPOOFING_DETECTION = "pref_common_arp_spoofing_detection"; @@ -122,6 +124,10 @@ public interface PreferenceKeys { String DNSCRYPT_OUTBOUND_PROXY = "Enable proxy"; //Tor Settings + String TOR_DNS_PORT = "DNSPort"; + String TOR_SOCKS_PORT = "SOCKSPort"; + String TOR_HTTP_TUNNEL_PORT = "HTTPTunnelPort"; + String TOR_TRANS_PORT = "TransPort"; String TOR_OUTBOUND_PROXY = "Enable output Socks5Proxy"; String TOR_OUTBOUND_PROXY_ADDRESS = "Socks5Proxy"; String SNOWFLAKE_RENDEZVOUS = "SnowflakeRendezvous"; diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/root/RootExecService.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/root/RootExecService.java index 03739076a..72beb1c81 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/root/RootExecService.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/root/RootExecService.java @@ -101,10 +101,14 @@ public static void performAction(Context context, Intent intent) { logi("RootExecService Root = " + true + " performAction"); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - context.startForegroundService(intent); - } else { - context.startService(intent); + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(intent); + } else { + context.startService(intent); + } + } catch (Exception e) { + loge("RootExecService performAction", e, true); } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/root/RootServiceNotificationManager.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/root/RootServiceNotificationManager.java index 5b7123492..181eaf677 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/root/RootServiceNotificationManager.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/root/RootServiceNotificationManager.java @@ -19,6 +19,8 @@ package pan.alexander.tordnscrypt.utils.root; +import static pan.alexander.tordnscrypt.utils.logger.Logger.loge; + import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationChannel; @@ -81,10 +83,14 @@ void sendNotification(String title, String text) { savedProgress ); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - service.startForeground(DEFAULT_NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST); - } else { - service.startForeground(DEFAULT_NOTIFICATION_ID, notification); + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + service.startForeground(DEFAULT_NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST); + } else { + service.startForeground(DEFAULT_NOTIFICATION_ID, notification); + } + } catch (Exception e) { + loge("RootServiceNotificationManager sendNotification", e, true); } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/web/HttpsConnectionManager.kt b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/web/HttpsConnectionManager.kt index 9b19c311e..8eb1a2ed8 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/web/HttpsConnectionManager.kt +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/utils/web/HttpsConnectionManager.kt @@ -99,7 +99,9 @@ class HttpsConnectionManager @Inject constructor( mutableListOf().also { lines -> httpsURLConnection.inputStream.bufferedReader().useLines { it.forEach { line -> - yield() + if (!isActive) { + return@forEach + } lines.add(line) } } diff --git a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/vpn/service/ServiceVPNHelper.java b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/vpn/service/ServiceVPNHelper.java index 8451c985e..52f8c8e1f 100644 --- a/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/vpn/service/ServiceVPNHelper.java +++ b/tordnscrypt/src/main/java/pan/alexander/tordnscrypt/vpn/service/ServiceVPNHelper.java @@ -111,12 +111,16 @@ public static void prepareVPNServiceIfRequired(Activity activity, ModulesStatus } private static void sendIntent(Context context, Intent intent) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - intent.putExtra("showNotification", true); - context.startForegroundService(intent); - } else { - intent.putExtra("showNotification", Utils.INSTANCE.isShowNotification(context)); - context.startService(intent); + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + intent.putExtra("showNotification", true); + context.startForegroundService(intent); + } else { + intent.putExtra("showNotification", Utils.INSTANCE.isShowNotification(context)); + context.startService(intent); + } + } catch (Exception e) { + loge("ServiceVPNHelper sendIntent", e, true); } } } diff --git a/tordnscrypt/src/main/res/layout/select_tor_transport.xml b/tordnscrypt/src/main/res/layout/select_tor_transport.xml index d6ffade26..d3638cf0e 100644 --- a/tordnscrypt/src/main/res/layout/select_tor_transport.xml +++ b/tordnscrypt/src/main/res/layout/select_tor_transport.xml @@ -25,6 +25,13 @@ android:layout_weight="1" android:text="Obfs4" /> + + + + دەستپێکردنەوە لەکاتی ئیشپێکردنەوە + مەودا + Tor ڕێکخستنەکانی + Tor لەگەڵ DNSCrypt و I2P + باشترین ڕێگایە بۆ پاراستنی تایبەتمەندییەکانت + ڕێکخستنەکان + I2P وەستێنرا + I2P کارایە + I2P دەستپێدەکات + ڕەتکردنەوە + I2P دادەمەزرێت + I2P دامەزرا + I2P لەوەستاندایە + I2P دانەبەزێنراوە + دڵنیابونەوە لە دۆخی ڕۆت… + پەیوەندیکردن + تکایە چاوەڕوانبە… + پیشانم مەدرەرەوە + DNSCrypt وەستێنرا + DNSCrypt لە وەستاندایە + DNSCrypt دامەزرا + DNSCrypt دادەبەزێت + DNSCrypt دانەبەزێنراوە + DNSCrypt دەسپێدەکات + DNSCrypt کارایە + Tor وەستێنرا + Tor دامەزرا + Tor دادەبەزێت + Tor دانەبەزێنراوە + Tor دەسپێدەکات + Tor کارایە + Tor لە وەستاندایە + ئاگادارکردنەوە! + هەڵەیەک ڕوویدا! + ئایا دڵنیایت؟ ئەم کردارە ناتوانرێ بگەڕێنرێتەوە! + ئەتەوێ بەردەوام بیت لە دامەزراندن؟ + پاشگەزبونەوە + وەشانی پارەدان + فەرامۆشکردنی گۆڕانکارییەکان + ڕێگەپێدان + هەڵە هەیە! + دەرچوون + تەواو + ڕازیم + نا رازیم + پاراستنی گۆڕانکارییەکان + دەربارە + دامەزراندن + تۆمارەکان + گێڕانەوەی ڕێکخستنەکان + بەرنامە دیاریبکە + بەخشین + پاراستنی ڕێکخستنەکان + سفکردنەوەی ڕێکخستنەکان + فۆڵدەری پاشکەوتکردن دیاریبکە: + شوێنی فۆڵدەر: + پاراستنی فایلی هەڵە! + پاشەکەوت پارێزرا + لابردنی دیاریکراو + پاشەکەوت گەڕێنرایەوە + ڕێکخستنەکان + دەسپێکردنی خۆکار + دیاریکردنی هەمووی + ڕێکخستنی گشتی + DNSCrypt ڕێکخستنی + Tor ڕێکخستنی + ڕێکخستنی خێرا + پاشەکەوت و گێڕانەوە + ماڵپەڕ دیاریبکە + I2P ڕێکخستنی + \ No newline at end of file diff --git a/tordnscrypt/src/main/res/values-de/strings.xml b/tordnscrypt/src/main/res/values-de/strings.xml index 6b4f21ddc..9eddd9f8d 100644 --- a/tordnscrypt/src/main/res/values-de/strings.xml +++ b/tordnscrypt/src/main/res/values-de/strings.xml @@ -349,12 +349,9 @@ Möchtest du den Download und das Upgrade auf PRO durchführen? Die Installation "VPN Modus Fehler!" "Bitte konfiguriere die Benutzung des Proxy Servers in den Einstellungen des verbundenen Gerätes. Standard Werte sind: IP:10.1.10.1 Port:8118" "Verstecke deine IP mit TOR" - "Schütze DNS mit DNSCRYPT" - "Zugang zu I2P Seiten mit Purple I2P" - "Achtung" - "InviZible Pro kann nicht starten %1$s! Bitte überprüfe %2$s Einstellungen oder versuche die App manuell zu beenden. -Falls das nicht helfen sollte, starte dein Gerät bitte neu." - "Erzwinge Beenden" + "Achtung" + Mit DNSCRYPT verteidigen + Zugang zum I2P-Netzwerk mit Purple I2P "Eigenen Server hinzufügen" "Ungültige Server Konfiguration. Bitte überprüfe das SDNS Feld." "Bitte beachte, dass du momentan bereits einen Einkauf getätigt hast:" @@ -402,16 +399,13 @@ Falls das nicht helfen sollte, starte dein Gerät bitte neu." " "Lösche Cloaking Regeln" "Importiere Blacklist" - "Importiere eine Liste von Domains oder eine Hosts Datei. Du kannst mehrere Dateien auswählen, doppelte Einträge werden entfernt. -" + Importiere eine Liste von Domains oder eine Hosts Datei. Du kannst mehrere Dateien auswählen, doppelte Einträge werden entfernt. "Lösche Blacklist" "Importiere IP Blacklist" - "Importiere eine IP Blacklist. Du kannst mehrere Dateien auswählen, doppelte Einträge werden entfernt. -" + Importiere eine IP Blacklist Liste. Du kannst mehrere Dateien auswählen, doppelte Einträge werden entfernt. "Lösche IP Blacklist" "Importiere Whitelist" - "Importiere eine Liste von Domains. Du kannst mehrere Dateien auswählen, doppelte Einträge werden entfernt. -" + Importiere eine Domain-Liste. Du kannst mehrere Dateien auswählen, doppelte Einträge werden entfernt. "Lösche Whitelist" "Beantworte IPv6 bezogene Anfragen umgehend leer. Dies beschleunigt Abläufe, wenn keine IPv6 Konnektivität vorhanden ist, kann aber gleichzeitig zu Störungen bei manchen Stub Resolvern führen." @@ -469,9 +463,8 @@ Möchtest du diesen zum Verbessern von InviZible an den Entwickler senden?""Erfolgreiche Verbindung. Ping %s ms." "ARP Spoofing erkannt!" "Bösartiges DHCP erkannt!" - "Man-in-the-middle Angriff erkannt! Deine Daten können von einem anderen Gerät im lokalen Netzwerk abgefangen werden. -WLAN aus- und kurz darauf wieder anschalten. Die Verwendung des derzeitigen Hotspots kann ebenfalls betroffen sein. -" + Man-in-the-middle Angriff erkannt! Deine Daten können von einem anderen Gerät im lokalen Netzwerk abgefangen werden. +\nWLAN aus- und kurz darauf wieder anschalten. Die Verwendung des derzeitigen Hotspots kann ebenfalls betroffen sein. "Erkennung von ARP Spoofing auf deinem Gerät wird leider nicht unterstützt!" "Bitte deaktiviere die Einstiegsknoten in den Tor Einstellungen um Bridges nutzen zu können." "Umgehe LAN Adressen" diff --git a/tordnscrypt/src/main/res/values-el/strings.xml b/tordnscrypt/src/main/res/values-el/strings.xml index bc3478297..812278d66 100644 --- a/tordnscrypt/src/main/res/values-el/strings.xml +++ b/tordnscrypt/src/main/res/values-el/strings.xml @@ -364,9 +364,7 @@ Should it be named instead "Βασικές Ρυθμίσεις" (originating from "Απόκρυψη IP μέσω TOR" "Προστασία DNS μέσω DNSCRYPT" "Πρόσβαση σε ιστοσελίδες I2P μέσω Purple I2P" - "Προσοχή" - "Το InviZible Pro δεν μπορεί να ξεκινήσει %1$s! Ελέγξτε τις ρυθμίσεις %2$s ή προσπαθήστε να κλείσετε με εξαναγκασμό την εφαρμογή. Εάν αυτό δεν σας βοηθήσει, κάντε επανεκκίνηση της συσκευής σας." - "Τερματισμός" + "Προσοχή" "Προσθήκη προσαρμοσμένου διακομιστή" "Μη έγκυρη προσαρμοσμένη διαμόρφωση διακομιστή. Ελέγξτε το πεδίο SDNS." "Λάβετε υπόψη ότι έχετε μια αγορά σε εκκρεμότητα:" diff --git a/tordnscrypt/src/main/res/values-es/strings.xml b/tordnscrypt/src/main/res/values-es/strings.xml index 699ad0daa..84bff1553 100644 --- a/tordnscrypt/src/main/res/values-es/strings.xml +++ b/tordnscrypt/src/main/res/values-es/strings.xml @@ -237,7 +237,7 @@ Con estas peticiones se puede descubrir la presencia de malware, aplicaciones de "Nombre de hosts o IPs para excluir de Tor" "Editar nombres de hosts o IPs" "Desactivado" - "Limpiar directorio del módulo" + Limpiar la cache "Apps a usar con InviZible" "Apps a excluir de InviZible" "Seleccionar todo" @@ -338,11 +338,9 @@ Con estas peticiones se puede descubrir la presencia de malware, aplicaciones de "¡Fallo detectado en modo VPN!" "Por favor, configura el uso de un servidor de proxy en la configuración del dispositivo. Configuración por defecto: IP: 10.1.10.1 Puerto:8118" "Ocultar IP con TOR" - "Proteger DNS con DNSCRYPT" - "Acceso a sitios I2P con I2Pd" - "Atención" - "¡InviZible Pro no puede arrancar %1$s! Por favor, comprueba la configuración de %2$s o intenta un Cierre Forzado de la aplicación. Si esto no ayuda, por favor, reinicia tu dispositivo." - "Forzar Cierre" + "Atención" + Protégete con DNSCRYPT + Acceder a la red I2P con Purple I2P "Añadir servidor personalizado" "Configuración del servidor personalizado erronea. Por favor, comprueba el campo SDNS." "Te recordamos que tienes pendiente una compra incompleta:" diff --git a/tordnscrypt/src/main/res/values-fa/strings.xml b/tordnscrypt/src/main/res/values-fa/strings.xml index 7e7eedd7b..12d97a1bb 100644 --- a/tordnscrypt/src/main/res/values-fa/strings.xml +++ b/tordnscrypt/src/main/res/values-fa/strings.xml @@ -362,10 +362,7 @@ "پنهان‌سازی IP توسط TOR" "حفاظت از DNS توسط DNSCrypt" "دسترسی به سایت‌های I2P توسط Purple I2P" - "توجه" - "اپلیکیشن InviZible Pro نمی‌تواند اجرا شود%2$s! لطفاً تنظیمات %1$s را بررسی نمایید و یا سعی نمایید برنامه را به‌صورت اجباری ببندید. -اگر این موارد پاسخگو نبودند، لطفاً دستگاه خود را مجدداً راه‌اندازی نمایید." - "بستن اجباری" + "توجه" "افزودن سرور سفارشی" "تنظیمات سرور سفارشی نامعتبر است. لطفاً قسمت SDNS را بررسی نمایید." "لطفاً توجه نمایید که شما یک خرید در حالت انتظار دارید:" diff --git a/tordnscrypt/src/main/res/values-fi/strings.xml b/tordnscrypt/src/main/res/values-fi/strings.xml index 2b8dfe464..ac201992c 100644 --- a/tordnscrypt/src/main/res/values-fi/strings.xml +++ b/tordnscrypt/src/main/res/values-fi/strings.xml @@ -352,10 +352,7 @@ "Piilota IP TOR:lla" "Suojaa DNS DNSCRYPT:llä" "Pääsy I2P-sivustoihin Purple I2P:llä" - "Huomio" - "InviZible Pro ei voi käynnistää %1$s! Tarkista %2$s-asetukset tai yritä pakottaa sovellus sulkemaan. - Jos tämä ei auta, käynnistä laite uudelleen." - "Pakota sulkeminen" + "Huomio" "Lisää mukautettu palvelin" "Virheellinen mukautettu palvelinmääritys. Tarkista SDNS-kenttä." "Huomaa, että sinulla on vireillä oleva osto:" diff --git a/tordnscrypt/src/main/res/values-fr/strings.xml b/tordnscrypt/src/main/res/values-fr/strings.xml index a5562cb2f..737dd2635 100644 --- a/tordnscrypt/src/main/res/values-fr/strings.xml +++ b/tordnscrypt/src/main/res/values-fr/strings.xml @@ -351,10 +351,7 @@ "Masquer l'IP avec TOR" "Protection du DNS avec DNSCRYPT" "Accès aux sites I2P avec Purple I2P" - "Attention" - "InviZible Pro ne peut pas démarrer %1$s! Veuillez vérifier les paramètres de %2$s ou essayer de forcer la fermeture de l'application. - Si cela ne résout pas le problème, veuillez redémarrer votre appareil." - "Forcer la fermeture" + "Attention" "Ajouter un serveur personnalisé" "Configuration du serveur personnalisée non valide. Veuillez vérifier le champ SDNS." "Veuillez noter que vous avez un achat en attente:" diff --git a/tordnscrypt/src/main/res/values-in/strings.xml b/tordnscrypt/src/main/res/values-in/strings.xml index edc623647..00fa910be 100644 --- a/tordnscrypt/src/main/res/values-in/strings.xml +++ b/tordnscrypt/src/main/res/values-in/strings.xml @@ -242,7 +242,7 @@ "Host atau IP untuk jalan pintas" "Edit Host atau IP" "Dinonaktifkan" - "Bersihkan folder modul" + Bersihkan cache "Aplikasi untuk digunakan dengan InviZible" "Aplikasi untuk jalan pintas InviZible" "Pilih Semua" @@ -345,12 +345,9 @@ "Kesalahan mode VPN!" "Harap konfigurasikan penggunaan server proxy dalam pengaturan perangkat yang terhubung. Nilai default: IP: 10.1.10.1 Port: 8118" "Sembunyikan IP dengan TOR" - "Lindungi DNS dengan DNSCRYPT" - "Akses ke situs I2P dengan Purple I2P" - "Perhatian" - "InviZible Pro tidak dapat memulai %1$s! Silakan periksa pengaturan %2$s atau coba tutup paksa aplikasi. -        Jika masih belum berfungsi, silakan mulai ulang perangkat anda." - "Tutup paksa" + "Perhatian" + Lindungi dengan DNSCRYPT + Akses situs I2P dengan Purple I2P "Tambahkan server khusus" "Konfigurasi server khusus tidak valid. Silakan periksa bidang SDNS." "Harap perhatikan bahwa Anda memiliki pembelian yang tertunda:" diff --git a/tordnscrypt/src/main/res/values-it/strings.xml b/tordnscrypt/src/main/res/values-it/strings.xml index fcb475b93..a960fd7ca 100644 --- a/tordnscrypt/src/main/res/values-it/strings.xml +++ b/tordnscrypt/src/main/res/values-it/strings.xml @@ -338,9 +338,7 @@ "Nascondi IP con TOR" "Proteggi DNS con DNSCRYPT" "Accedi ai siti I2P con Purple I2P" - "Attenzione" - "InviZible Pro non può avviare %1$s! Per favore controlla le impostazioni %2$s o prova la Chiusura Forzata dell'applicazione. Se non funziona, riavvia il tuo dispositivo." - "Chiusura forzata" + "Attenzione" "Aggiungi server personalizzato" "Configurazione server personalizzato invalida. Controlla il campo SDNS." "Attenzione hai già un acquisto in sospeso:" diff --git a/tordnscrypt/src/main/res/values-ja/strings.xml b/tordnscrypt/src/main/res/values-ja/strings.xml index 7ea27c3e7..441d901b6 100644 --- a/tordnscrypt/src/main/res/values-ja/strings.xml +++ b/tordnscrypt/src/main/res/values-ja/strings.xml @@ -338,9 +338,7 @@ These queries can reveal the presence of malware, broken/obsolete applications, "TorでIPを隠す" "DNSCryptでDNSを保護する" "Purple I2Pでeepsitesにアクセスする" - "警告" - "Invizible Proは %1$s を開始できませんでした。 %2$s の設定を確認するか、このアプリを強制終了して再度お試しください。それでも解決しない場合、端末を再起動してみてください。" - "強制終了" + "警告" "カスタムサーバーを追加" "カスタムサーバー設定が無効です。SDNSの項目をご確認ください。" "Please note that you have a pending purchase:" diff --git a/tordnscrypt/src/main/res/values-pl/strings.xml b/tordnscrypt/src/main/res/values-pl/strings.xml index 40efbe29a..28241532d 100644 --- a/tordnscrypt/src/main/res/values-pl/strings.xml +++ b/tordnscrypt/src/main/res/values-pl/strings.xml @@ -62,7 +62,7 @@ "Uruchom Tor przy starcie systemu" "Uruchom I2P przy starcie systemu" "Opoznij" - "Uzyj opoznienia (w sek) tylko jesli autostart nie dziala prawidlowo" + Użyj opóźnienia (w sekundach) tylko wtedy, gdy Autostart nie działa prawidłowo "Serwery DNSCrypt" "Wybierz serwery DNSCrypt" "Ustawienia Tora" @@ -140,7 +140,7 @@ "Prosze zrestartowac DNSCrypt" "Prosze zrestartowac Tor" "Prosze zrestartowac I2P" - "Wybierz Iptables" + Wybierz iptables "Zapisz polecenia Roota w logu" "DNSCrypt, Tor, I2P sa chronione. Nie ukrywaj!" "Wykonywanie komend Root…" @@ -235,7 +235,7 @@ Takie zapytania moga wskazywac na obecnosc malware, uszkodzonych/przestarzalych "Host lub IP ktory chcesz pominac" "Edytuj Host lub IP" "Zablokowane" - "Wyczysc folder modułu" + Wyczyść pamięć podręczną "Aplikacje laczace sie przez InviZible" "Aplikacje pomijajace InviZible" "Zaznacz wszystko" @@ -285,7 +285,7 @@ Takie zapytania moga wskazywac na obecnosc malware, uszkodzonych/przestarzalych "Wyglada na to ze system android wylaczyl Tor. Twoje polaczenie z siecia zostalo przywrocone. Szprawdz ustawienia urzadzenia!" "Wyglada ze system android wylaczyl I2P. sprawdz ustawienia urzadzenia!" "Wyglada ze DNSCrypt NIE MOZE polaczyc sie z siecia." - "Wyglada ze Tor NIE MOZE polaczyc sie z siecia. Twoj ISP moze blokowac polaczenie. Mozesz sprobowac uzyc mostka. Ustawienia w MENU -> Szybkie ustawienia -> Mostki" + Wygląda na to, że Tor nie może połączyć się z Internetem. Dostawca usług internetowych może blokować połączenia z Torem. Możesz spróbować użyć mostów Tor. Można je znaleźć w MENU -> Szybkie ustawienia -> Mosty "Child Lock" "Mozesz zablokowac dostep do ustawien aplikacji. Wprowadz haslo lub uzyj poprzedniego." "Wprowadz haslo." @@ -336,11 +336,9 @@ Takie zapytania moga wskazywac na obecnosc malware, uszkodzonych/przestarzalych "Błąd trybu VPN!" "Skonfiguruj użycie serwera proxy w ustawieniach podłączonego urządzenia. Wartości domyślne: IP:10.1.10.1 Port:8118" "Ukryj adres IP za pomocą TOR" - "Chron DNS za pomocą DNSCRYPT" - " Dostep do stron I2P za pomocą Purple I2P" - "Uwaga" - "Blad uruchomienia InviZible Pro %1$s! Sprawdz %2$s ustawienia lub sprobuj wymusic zamkniecie aplikacji w ustawieniach urzadzenia. Jesli brak poprawy, uruchom urzadzenie ponownie." - "Wymus zamkniecie" + "Uwaga" + Ochrona DNSCRYPT + Dostep do sieci I2P za pomocą Purple I2P "Dodaj serwer" "Niepoprawna niestandardowa konfiguracja serwera. Sprawdź pole SDNS." "Pamiataj, ze masz oczekujacy zakup:" @@ -503,4 +501,17 @@ Takie zapytania moga wskazywac na obecnosc malware, uszkodzonych/przestarzalych "Internet connectivity check" "Real-time logs" "Show application connection logs in the DNS tab" + \\ Dziękujemy za wybranie InviZible Pro. Mamy nadzieję, że przysłuży się on Twojej prywatności i umożliwi wygodneg korzystanie z Internetu. +\n +\n\tInviZible Pro zawiera moduły Tor, DNSCrypt i Purple I2P. +\n +\n\tInviZible Pro może używać roota, jeśli twoje urządzenie ma takie uprawnienia, lub używać lokalnej sieci VPN do dostarczania ruchu internetowego do sieci Tor, DNSCrypt i I2P. +\n +\n\tPolityka prywatności: +\n\tInviZible Pro nie gromadzi ani nie udostępnia żadnych osobistych lub wrażliwych danych użytkownika. +\n +\n\tCopyright © 2019-2023 +\n\tGarmatin Oleksandr +\n\tinvizible.soft@gmail.com +\n\tinvizible.net/en/privacy diff --git a/tordnscrypt/src/main/res/values-pt-rBR/strings.xml b/tordnscrypt/src/main/res/values-pt-rBR/strings.xml index 9f7bf193d..43a3c241f 100644 --- a/tordnscrypt/src/main/res/values-pt-rBR/strings.xml +++ b/tordnscrypt/src/main/res/values-pt-rBR/strings.xml @@ -253,7 +253,7 @@ Essas consultas podem revelar a presença de malware, aplicativos quebrados / ob "Host ou IP para bypass" "Editar host ou IP" "Desativado" - "Limpar pasta de módulo" + Limpar cache "Aplicativos para usar com InviZible" "Apps para contornar InviZible" "Selecionar todos" @@ -303,7 +303,7 @@ Essas consultas podem revelar a presença de malware, aplicativos quebrados / ob "Parece que o Tor foi morto pelo sistema Android. Sua conexão com a Internet foi restaurada. Verifique as configurações do dispositivo!" "Parece que o I2P foi morto pelo sistema Android. Sua conexão com a Internet foi restaurada. Verifique as configurações do dispositivo!" "Parece que o DNSCrypt NÃO PODE se conectar à INTERNET." - "Parece que o Tor NÃO PODE se conectar à INTERNET. O ISP pode bloquear as conexões do Tor. Você pode tentar usar pontes de tor. Encontre-os em MENU -> Configurações Rápidas -> Pontes" + Parece que o Tor não consegue se conectar à Internet. O ISP pode bloquear as conexões Tor. Você pode tentar usar as Tor Bridges. Encontre-as em MENU -> Configurações rápidas -> Bridges "Bloqueio para crianças" "Você pode bloquear o controle deste aplicativo. Por favor, digite a senha ou use a anterior." "Por gentileza, entre com a Senha." @@ -354,11 +354,9 @@ Essas consultas podem revelar a presença de malware, aplicativos quebrados / ob Erro no modo VPN! "Configure o uso do servidor proxy nas configurações do dispositivo conectado. Valores padrão: IP:10.1.10.1 Porta:8118" "Ocultar IP com TOR" - "Proteger DNS com DNSCRYPT" - "Acessar sites com I2P" - "Atenção" - "InviZible Pro não pode iniciar %1$s! Verifique as configurações de %2$s ou tente forçar o fechamento do aplicativo. Se isso não ajudar, reinicie seu dispositivo." - "Força o fechamennto" + "Atenção" + Defenda-se com DNSCRYPT + Acesso à rede I2P com Purple I2P "Adicionar servidor customizado" "Configuração de servidor personalizado inválida. Verifique o campo SDNS." "Observe que você tem uma compra pendente:" diff --git a/tordnscrypt/src/main/res/values-pt/strings.xml b/tordnscrypt/src/main/res/values-pt/strings.xml index f7eae8867..af3442400 100644 --- a/tordnscrypt/src/main/res/values-pt/strings.xml +++ b/tordnscrypt/src/main/res/values-pt/strings.xml @@ -14,7 +14,7 @@ Nenhuma atualização foi encontrada. Erro no modo VPN! Acessar sites com I2P - Atenção + Atenção Tor com DNSCrypt e I2P a melhor solução para a sua privacidade Configurações @@ -395,8 +395,6 @@ Configure o uso do servidor proxy nas configurações do aparelho conectado. Valores padrão: IP:10.1.10.1 Porta:8118 Ocultar IP com TOR Proteger DNS com DNSCRYPT - InviZible Pro não pode iniciar %1$s! Verifique as configurações de %2$s ou tente forçar o fechamento do aplicação. Se isso não ajudar, reinicie o seu aparelho. - Força o fechamennto Adicionar servidor customizado Configuração de servidor personalizado inválida. Verifique o campo SDNS. Observe que tem uma compra pendente: diff --git a/tordnscrypt/src/main/res/values-ru/strings.xml b/tordnscrypt/src/main/res/values-ru/strings.xml index 4f7783f1d..c3dfd241d 100644 --- a/tordnscrypt/src/main/res/values-ru/strings.xml +++ b/tordnscrypt/src/main/res/values-ru/strings.xml @@ -361,10 +361,10 @@ Защититься с помощью DNSCRYPT Доступ к сети I2P с помощью Purple I2P Подключение - Внимание - InviZible Pro не может запустить %1$s! Пожалуйста, проверьте настройки %2$s или попробуйте Завершить приложение. + Внимание + InviZible Pro не может запустить %1$s! Пожалуйста, попробуйте сбросить настройки %2$s. Если это не помогает, перезагрузите ваше устройство. - Завершить + Сбросить Добавить сервер Неправильная конфигурация сервера. Пожалуйста, проверьте поле SDNS. Очистить кеш @@ -542,4 +542,6 @@ Активируйте эту опцию, если вы находитесь в сети, поддерживающей только ipv6, и сайты ipv4 становятся недоступными. В противном случае не включайте ее, иначе вы вообще не сможете ни к чему подключиться. Набор используемых статических префиксов IPv6. IPv6 мосты + Подделать SNI + Tor будет отслеживать недавние подключения к сайтам и пытаться использовать один и тот же выходной узел для каждого. Эта опция может помочь избежать бесконечной каптчи. diff --git a/tordnscrypt/src/main/res/values-tr/strings.xml b/tordnscrypt/src/main/res/values-tr/strings.xml index 79c707da1..e01ea21a2 100644 --- a/tordnscrypt/src/main/res/values-tr/strings.xml +++ b/tordnscrypt/src/main/res/values-tr/strings.xml @@ -417,9 +417,7 @@ TOR ile IP\'yi gizle DNSCRYPT ile DNS\'i koru Purple I2P ile I2P sitelerine eriş - Dikkat - %1$s, InviZible Pro tarafından başlatılamıyor! Lütfen %2$s ayarlarını gözden geçirin veya uygulamayı zorla kapatmayı deneyin. Bu yardımcı olmazsa, lütfen aygıtınızı yeniden başlatın. - Kapatmaya zorla + Dikkat Özel sunucu ekle Geçersiz özel sunucu yapılandırması. Lütfen SDNS alanını gözden geçirin. Bekleyen bir satın alma işleminiz olduğunu lütfen unutmayın: diff --git a/tordnscrypt/src/main/res/values-uk/strings.xml b/tordnscrypt/src/main/res/values-uk/strings.xml index d847ddfbe..5d48e57b2 100644 --- a/tordnscrypt/src/main/res/values-uk/strings.xml +++ b/tordnscrypt/src/main/res/values-uk/strings.xml @@ -1,5 +1,5 @@ - + найкраще рішення для вашої конфіденційності Налаштування I2P запускається @@ -125,7 +125,7 @@ Будь ласка, перезапустіть Tor Будь ласка, перезапустіть I2P Підтримка подвійних додатків, MIUI, Island, Shelter та додатків робочого профілю - Вибрати Iptables + Виберіть iptables Інші налаштування. Сервер для початкового завантаження. Це звичайний сервер, не який підтримує шифрування. Використовується лише для завантаження списку серверів, які підтримують шифрування, якщо системний сервер DNS не працює. Він ніколи не використовується, якщо завантажено список серверів, які підтримують шифрування. Не дозволяти dnscrypt-proxy використовувати системні установки DNS. Використовувати сервер для відновлення.. @@ -175,4 +175,317 @@ ЗАГАЛЬНІ НАЛАШТУВАННЯ Увімкніть якщо у Вас кастомна прошивка, та інтернет зникає при натисканні кнопки START DNSCrypt, Tor, I2P захищені. Не приховуйте сповіщення. - \ No newline at end of file + Видалити білий список + Сервери + Хост або IP для обходу + Вибрати все + Прибрати вибране + Зовнішній IP роутера для вхідних з\'єднань. + ntcp2 увімкнено + Ресідінґ + Перевірте підпис .su3. + Схоже, що I2P було вбито системою Android. Перевірте налаштування пристрою! + Завантаження файлу + Доступне оновлення InviZible Pro. Бажаєте завантажити та оновити його\? Оновлення продовжиться у фоновому режимі. + Приховати IP з TOR + Неправильна конфігурація сервера. Будь ласка, перевірте поле SDNS. + Запуск служб + Оновлення сповіщень + Блокування IP-адрес на основі шаблонів (чорний список IP-адрес). + Заблокувати HOTSPOT http + Проксі + Використовувати socks5 proxy + InviZible Pro здійснюватиме всі підключення через SOCKS5 proxy + Усі маршрути через Тор + Увімкнути прив\'язку Tor + Експериментальний HOTSPOT + Починати прив\'язку під час завантаження + Сервер не має застосовувати власний чорний список (для батьківського контролю, блокування реклами...). + Імпортує файл правил переадресації. Ви можете вибрати кілька файлів, повторювані рядки видаляться. + Імпортувати правила переадресації + Видалити правила переадресації + Чорний список складається з одного шаблону на рядок. + Реле + Редагувати хост або IP-адресу + Не використовати спільні ланцюги з потоками, що мають іншу адресу призначення. + Сокс-проксі + Не запитувати знову + Схоже, це неофіційна версія InviZible. Будь ласка, будьте обережні! + Пожертвувати + Захиститися за допомогою DNSCRYPT + Список веб-сайтів, які відкривати безпосередньо через HOTSPOT + Дозволити прив\'язку I2P + Зберігати рут-команди до журналу + Вимагати, щоб сервери (зі статичних + віддалених джерел) відповідали певним властивостям. + Використовувати сервери з підтримкою протоколу DNSCrypt. + Використовувати сервери, доступні через IPv6 + Сервер не має реєструвати запити користувачів (декларативно). + Може бути корисно, якщо вам потрібно направляти все через Tor. +\n В іншому разі залиште опцію вимкненою, оскільки це не покращує безпеку (dnscrypt-proxy завжди буде шифрувати все, навіть використовуючи UDP), і може лише збільшити затримку. + proxy_port + Перенаправляти всі TCP-з\'єднання на локальний вузол Tor. Tor не підтримує UDP, а отже ввімкніть force_tcp також. + Маскування повертає заздалегідь визначену адресу для певного імені. +\n Окрім того, що воно діє як файл HOSTS, це також може повертати IP-адресу іншого імені. Також виконує вирівнювання CNAME. + Увімкнути журнали запитів + Не записувати ці типи запитів, щоб зменшити багатослівність. Залишає порожній рядок, щоб записати все. + Записує клієнтські запити у файл. + Журналювати запити для неіснуючих зон. +\n Ці запити можуть виявити наявний шкідливого програмного забезпечення, зламаних/застарілих програм і пристроїв, що сигналізують про свою присутність третім особам. + Чорний список IP складається з одного шаблону на рядок. + Імпортувати чорний список IP-адрес + Імпортує чорний список IP-адрес. Ви можете вибрати декілька файлів, повторювані рядки видаляться. + Білий список на основі шаблонів (обхід чорних списків). + Білий список + Видалити чорний список IP-адрес + У файлі dnscrypt-proxy.txt немає параметра преференцій! + Видалити журнал + Негайно відповідати на запити A і AAAA для імен хостів без імені домену. + Негайно реагувати на запити до локальних зон, замість того, щоб передавати їх висхідним обробникам (що завжди призводить до помилок або тайм-аутів). + Негайно відповідати на запити, пов\'язані з IPv6, порожньою відповіддю. Це пришвидшує роботу за відсутності IPv6-з\'єднання, але також може спричинити проблеми з надійністю деяких роздільників заглушок. + Будь ласка, вимкніть \"Приватний DNS\" у налаштуваннях мережі Android. Ця опція перешкоджає роботі InviZible. + Імпортувати правила + Будь ласка, зачекайте... Імпортовано %d правил. + Готово! Імпортовано %d правил. + Будь ласка, вимкніть проксі в налаштуваннях мережі WiFi на Android. Ця опція перешкоджає роботі InviZible. + Будь ласка, вимкніть проксі у налаштуваннях APN мобільної мережі Android. Ця опція перешкоджає роботі InviZible. + Якщо увімкнено, Tor не триматиме АБО-з\'єднання відкритими дуже довго і надсилатиме менше даних на цих з\'єднаннях. Увімкніть для економії пропускної здатності. + Список кодів країн, які ніколи не слід використовувати при виборі вузла виходу, що доставляє трафік за межі мережі Tor. + Список кодів країн для використання в якості вихідного вузла - тобто вузла, який доставляє трафік для вас за межі мережі Tor. + Список кодів країн, яких слід уникати при побудові схеми. + Список кодів країн вузлів, які слід використовувати для першого переходу у ваших звичайних схемах. + Вимкніть мости Tor, якщо ви хочете вибрати вузли входу. + Якщо увімкнено StrictNodes, Tor буде розглядати виключно опцію ExcludeNodes як вимогу, якої слід дотримуватися для всіх схем, що ви створюєте, навіть якщо це порушить функціональність. + Якщо увімкнено, Tor буде створювати вихідні з\'єднання тільки з OR, що працюють на портах, дозволених вашим брандмауером (типово 80 і 443). + Кожні кілька секунд вирішується, чи будувати новий контур. + Не соромтеся повторно застосовувати контур, який використовувався не більше кількох секунд тому, але ніколи не приєднуйте новий потік до занадто старого контуру. + Якщо увімкнено, Tor не буде розміщувати два сервери, IP-адреси яких знаходяться надто близько в одному ланцюзі. Наразі дві адреси вважаються занадто близькими, якщо вони лежать в одному діапазоні /16. + Відкрити цей порт для прослуховування з\'єднань від SOCKS-програм. + Увімкнути HTTP-тунель + Відкриває цей порт для прослуховування проксі-з\'єднань за протоколом HTTP CONNECT замість SOCKS. + Відкриває цей порт для прослуховування UDP DNS-запитів та їх анонімного вирішення. + Увімкнути DNS + Якщо вимкнено, Tor уникатиме з\'єднання з серверами каталогів і вузлами входу через IPv4. + Якщо увімкнено, Tor може підключатися до серверів каталогів або вузлів входу через IPv6. + STUN-сервери для мостів SnowFlake + Редагувати tor.conf безпосередньо + Tor буде здійснювати всі OR-з\'єднання через проксі-сервер SOCKS 5. + Застосунки для використання з InviZible + Очистити кеш + Не використовувати спільні схеми з потоками, спрямованими на інший порт призначення. + Маршрутизатор не приймає транзитні тунелі, повністю відключаючи транзитний трафік. + Маршрутизатор буде затоплений. + Обмеження пропускної здатності в Кбіт/с. + Максимальний % від ліміту пропускної здатності для транзиту. 0-100. + Увімкніть транспортний протокол SSU (використовуйте UDP). + Увімкнути ntcpproxy + Вкажіть проксі-сервер для NTCP. Має бути http://address:port або socks://address:port. + HTTP-проксі + HTTP-проксі + Порт для прослуховування (HTTP-проксі). + HTTP-аутпроксі + Адреса HTTP-аутпроксі + Порт HTTP-проксі + Порт сокс-проксі + Сокс проксі + Інтерфейс SAM + Порт мосту SAM. + Шифрування + Порт аутпроксі SOCKS + Інтерфейс SAM + Порт інтерфейсу SAM + Використовувати попередньо розраховані таблиці ElGamal. + Увімкнути або вимкнути UPnP. + Перевизначити максимальну кількість транзитних тунелів. Типово 2500. + Обмеження кількості відкритих дескрипторів файлів (0 - використовувати системний ліміт). + Схоже, DNSCrypt було вбито системою Android. Ваше інтернет-з\'єднання відновлено. Перевірте налаштування пристрою! + Відомості + Схоже, що DNSCrypt не може підключитися до Інтернету. Ви можете спробувати вибрати інші сервери DNSCrypt. Будь ласка, знайдіть їх у МЕНЮ -> Швидкі налаштування -> Вибрати сервери DNSCrypt + Схоже, Tor не може підключитися до Інтернету. Можливо, провайдер блокує з\'єднання Tor. Ви можете спробувати використати Tor Bridges. Будь ласка, знайдіть їх у МЕНЮ -> Швидкі налаштування -> Мости + Пароль неправильний! + Керування розблоковано + Керування заблоковано + HOTSPOT + Шлях до журналів: + Зібрати журнали + Деякі модулі InviZible готові до оновлення. Бажаєте оновити його\? Це призведе до перезапису налаштувань модуля! + Оновити + Журнали збережено. Будь ласка, надішліть файл InvizibleLogs.txt розробнику. Логи можна знайти в теці: + Оновити + Пізніше + Перевірка оновлень + Доступне оновлення I2P. Бажаєте завантажити та оновити його\? Оновлення продовжиться у фоновому режимі. + Помилка оновлення. + Будь ласка, зачекайте, поки оновлення перевіряються. + Оновлень не знайдено. + Остання перевірка: + Знайдено оновлення. + Схоже, ваш PRO-код неправильний. Будь ласка, зв\'яжіться з розробником. + Ви перевіряли оновлення InviZible Pro більше 5 разів на день. Будь ласка, спробуйте ще раз пізніше. + Увести код + Тільки для PRO-версії + Проект InviZible Pro потребує вашої допомоги. Будь ласка, відвідайте сторінку пожертвування або введіть отриманий преміум-код. + Віддалені списки доступних реле. + Режим VPN вимкнено + Режим VPN активовано + Проект InviZible Pro та його автор висловлюють подяку за допомогу! + Будь ласка, налаштуйте використання проксі-сервера в налаштуваннях підключеного пристрою. Типове значення: IP:10.1.10.1 Port:8118 + Помилка режиму VPN! + Доступ до мережі I2P з Purple I2P + Додати власний сервер + Ви хочете зберегти зміни\? Це може зламати InviZible Pro. + Проект InviZible Pro потребує вашої допомоги. Натисніть OK, щоб придбати преміум-функції. + Вибачте, але підтвердити вашу покупку неможливо. Ви отримаєте відшкодування протягом 3 днів. + На жаль, ця функція доступна лише в преміум-версії. + Зафіксувати TTL + Увімкнути фіксування TTL і налаштувати LAN-пристрій для підключення до InviZible. Використовувати типовий шлюз: %1$s, DNS-сервер: %2$s. + Використовувати сервери, доступні через IPv4 + Сервер має підтримувати розширення безпеки DNS (DNSSEC). + Правила маскування + Видалити правила маскування + Відкрити журнал запитів + Видалити чорний список + Чорний список IP-адрес + Імпортувати білий список + Імпортує список доменів. Ви можете вибрати кілька файлів, повторювані рядки видаляться. + Список джерел закінчується після refresh_delay. + Список реле закінчується через годину refresh_delay. + Реле DNSCrypt + Журнал запитів DNSCrypt + Відкриває цей порт для прослуховування прозорих проксі-з\'єднань. + Вимкнено + Ліміти + URL-адреса AddressBook підписки для початкового налаштування. + URL підписки AddressBook. + Завантаження було зупинено + Зверніть увагу, що у вас відкладена покупка: + Для керування модулями програми використовуйте наступну команду: \"am broadcast -a pan.alexander.tordnscrypt.SHELL_SCRIPT_CONTROL --ei dnscrypt 1 --ei tor 1 --ei i2p 1 %s\". Де 1 - запускає, 0 - зупиняє модуль. + Вимагати, щоб сервери, визначені віддаленими джерелами, відповідали певним властивостям. + Увесь вхідний трафік через Тор + Список веб-сайтів, які потрібно відкрити за допомогою Tor для HOTSPOT + TTL буде зафіксовано на 64 за допомогою локальної VPN. Підтримка ядра не потрібна. Його можна використовувати лише у \"рут-режимі\" з вимкненою опцією \"Запускати модулі з правами рута\". Щоб зафіксувати TTL, будь ласка, запустіть DNSCrypt та/або Tor. + Цей параметр регулює використання Tor прокладок для захисту від деяких форм аналізу трафіку. Вимкніть для економії пропускної здатності. + Якщо ненульове, намагайтеся рідше записувати на диск. + Відкрити налаштування прив\'язки + Підтримувати багатокористувацький режим + Увімкнути прозорий проксі + Використовуйте сервери з підтримкою протоколу DNS-over-HTTPS. + У файлі tor.conf немає параметра преференцій! + Хост або IP для розблокування + Завжди використовувати TCP для підключення до висхідних серверів. + SOCKS проксі. + Увімкнути проксі + Імпортувати правила маскування + Імпортує файл правил маскування. Ви можете вибрати декілька файлів, повторювані рядки видаляться. + Журналізація запитів. + SOCKS аутпроксі + Журналізація підозрілих запитів. + Увімкнути журналювання підозрілих подій + Відкрити журнал підозрілих подій + Блокування на основі шаблонів (чорний список). + Імпортує список доменів або файл hosts. Ви можете вибрати кілька файлів, повторювані рядки видаляться. + Ви можете заблокувати доступ до цієї програми. Будь ласка, введіть пароль або використовуйте попередній. + Джерела + Доступне оновлення DNSCrypt. Бажаєте завантажити та оновити його\? Оновлення продовжиться у фоновому режимі. + Журнал підозрілих подій DNSCrypt + Журнал порожній + Коли Tor має призначити віртуальну (невикористану) адресу через команду MAPADDRESS від контролера або функцію AutomapHostsOnResolve, Tor вибирає непризначену адресу з цього діапазону. + Оновлення встановлено. + Білий спискок підтримуює ті ж шаблони, що і чорнй. Якщо ім\'я збігається з елементом білого списку, відповідний сеанс буде обходити імена та IP-фільтри. + Видалити списки доступних серверів. + Редагувати dnscrypt-proxy.txt безпосередньо + Готово! Правила стерто. + Занадто багато правил. Буде показано лише перші 1000. + Намагатися використовувати вбудоване криптографічне апаратне прискорення, якщо воно доступне. + Увімкнути SOCKS проксі + Джерела + Увімкнути проксі для виводу SOCKS + Застосунки для обходу InviZible + Видалити виділення + Дозволити вхідні з\'єднання + Порт для прослуховування вхідних з\'єднань. + Увімкніть зв\'язок через IPv4. + Увімкніть зв\'язок через IPv6. + Увімкніть транспортний протокол NTCP2 (використовуйте TCP). + Порт для прослуховування (SOCKS Proxy). + Адреса аутпроксі SOCKS + Максимальний розмір corefile в Kb (0 - використовувати системний ліміт). + Параметра немає в i2pd.conf! + Редагувати i2pd.conf безпосередньо + Редагувати tunnels.conf безпосередньо + Схоже, Tor було вбито системою Android. Ваше з\'єднання з інтернетом відновлено. Перевірте налаштування пристрою! + Будь ласка, уведіть пароль. + Будь ласка, перезапустіть InviZible Pro і дозвольте завершити інсталяцію! Після встановлення переналаштуйте HOTSPOT, якщо ви ним користуєтесь! + СКАСУВАТИ ЗАВАНТАЖЕННЯ + Нова версія: + Доступне оновлення Tor. Бажаєте завантажити та оновити його\? Оновлення продовжиться у фоновому режимі. + Сервер оновлень тимчасово недоступний. Будь ласка, повторіть спробу пізніше. + Сервер оновлень був недоступний. + Схоже, ви вже активували 3 копії InviZible з цим кодом. Якщо це не так, зверніться до розробника. + Увести код + Проект InviZible Pro та його автор висловлюють подяку за допомогу. Бажаєте завантажити та оновити до версії PRO\? Оновлення триватиме у фоновому режимі. + + \tДякуємо, що обрали InviZible Pro. Сподіваюся, він буде корисним для вашої конфіденційності та комфортного користування інтернетом. + \n\n\tInviZible Pro включає в себе Tor, DNSCrypt і Purple I2P як модулі. + \n\n\tInviZible Pro може використовувати root, якщо ваш пристрій має привілеї root, або використовувати локальний VPN для доставки інтернет-трафіку в мережі Tor, DNSCrypt і I2P. + \n\n\tПолітика конфіденційності: + \n\tInviZible Pro не збирає і не поширює будь-які особисті або конфіденційні дані користувачів. + \n\n\tCopyright © 2019-2023 + \n\tGarmatin Oleksandr + \n\tinvizible.soft@gmail.com + \n\tinvizible.net/en/privacy + Ім\'я користувача: + Пароль: + Зберегти та ввімкнути + Брандмауер + Сортувати за іменем + Увімкнення/вимкнення брандмауера + Допоміжні сповіщення + Ідентифікатор Tor змінився + Переприв\'язка DNS + Сортувати за UID + Виявлено повідомлення про помилку. Бажаєте відправити повідомлення розробнику, щоб покращити InviZible\? + Новий ідентифікатор Tor + Проксі-сервер: + Проксі-порт: + Список застосунків відкривається безпосередньо. Вони не використовують Tor або проксі для підключення до Інтернету! + Використовувати проксі для Tor + Використовувати проксі для Purple I2P + Якщо ви використовуєте локальний проксі, будь ласка, виберіть програму власника проксі, принаймні, якщо ви використовуєте локальний проксі. + Використовувати проксі для DNSCrypt + Успішне з\'єднання. Пінґ %s мс. + Виявлено підміну ARP! + Не вдається під\'єднатися до проксі: %s + Виявлено атаку \"посередницьку\" типу! Ваші дані можуть бути перехоплені іншим пристроєм у локальній мережі. Вимкніть, зачекайте кілька секунд та увімкніть Wi-Fi. Використання поточної точки доступу Wi-Fi може бути небезпечним! + Виявлено неавторизований DHCP! + Щоб активувати брандмауер, потрібно запустити хоча б DNSCrypt або Tor. + Встановлено %s + Бажаєте зберегти зміни\? + Дозволити Інтернет для цього\? + Вибрати всі + Дозволити підключення з увімкненим VPN + Дозволити підключення в роумінгу + Зелений - дозволити, білий - заборонити з\'єднання + Дозволити з\'єднання для нових застосунків + Налаштування брандмауера + Зняти виділення + Підключення до Інтернету для щойно встановлених додатків дозволено. + Підєднання до Інтернету для нових встановлених додатків заблоковано. + Зміна IP-адреси Tor + Ви додали більше 3-х плиток до Швидких налаштувань. Будь ласка, залиште лише 3. Додавання більшої кількості плиток може спричинити проблеми з керуванням програмою. + Виключення + Виявлено потенційну атаку на переприв\'язку DNS! Сайт %s було заблоковано. + Усі + Системні + Користувацькі + Дозволити підключення до локальної мережі, сайтів onion та i2p + Дозволити з\'єднання в мережах GSM + Змінити IP-адресу Tor + Захист від дітей + Сповіщення брандмауера + Це поле можна залишити порожнім + Виявлення підміни ARP не підтримується на вашому пристрої! + Дозволити підключення до мереж WiFi + Сповіщення про рут-команди + Підробити SNI + Tor відстежуватиме нещодавні підключення до сайтів і намагатиметься використовувати той самий вихідний вузол для кожного. Ця опція може допомогти уникнути нескінченної каптчі. + diff --git a/tordnscrypt/src/main/res/values-zh/strings.xml b/tordnscrypt/src/main/res/values-zh/strings.xml index afa9fb637..b2a4e2695 100644 --- a/tordnscrypt/src/main/res/values-zh/strings.xml +++ b/tordnscrypt/src/main/res/values-zh/strings.xml @@ -238,7 +238,7 @@ "绕过的的主机或 IP" "编辑主机或 IP" "已禁用" - "清除模块文件夹" + 清除缓存 "使用 InviZible 的应用" "绕过 InviZible 的应用" "选择全部" @@ -288,7 +288,7 @@ "似乎 Tor 被 Android 系统杀死了。 您的互联网连接已恢复。检查设备设置!" "似乎 I2P 被 Android 系统杀死了。检查设备设置!" "似乎 DNSCrypt 无法连接到互联网。 " - "似乎 Tor 无法连接到互联网。 ISP 可能阻止 Tor 连接。您可以尝试使用网桥。请前往菜单 -> 快速设置 -> 网桥设置" + 似乎 Tor 无法连接到互联网。 ISP 可能阻止 Tor 连接。您可以尝试使用网桥。请前往菜单 -> 快速设置 -> 网桥设置 "儿童锁" "您可以锁定此应用控制。请输入密码或使用先前的。" "请输入密码。" @@ -339,11 +339,9 @@ "VPN 模式错误!" "请再已连接设备中配置代理服务器。默认值:IP:10.1.10.1 端口:8118" "使用 TOR 隐藏 IP" - "使用 DNSCRYPT 保护 DNS" - "使用 Purple I2P 访问 I2P 站点" - "注意" - "InviZible Pro 无法启动 %1$s!请检查 %2$s 设置或尝试强制关闭应用。 如果不起作用,请重启您的设备。" - "强制关闭" + "注意" + 使用 DNSCRYPT 防护 + 使用 Purple I2P 访问 I2P 网络 "添加自定义服务器" "无效自定义服务器配置。请检查 SDNS 字段。" "请注意您有一个待完成的购买:" diff --git a/tordnscrypt/src/main/res/values/array.xml b/tordnscrypt/src/main/res/values/array.xml index 8c7110e10..57b1fa04f 100644 --- a/tordnscrypt/src/main/res/values/array.xml +++ b/tordnscrypt/src/main/res/values/array.xml @@ -542,6 +542,7 @@ meek_lite snowflake conjure + webtunnel vanilla @@ -551,6 +552,7 @@ meek_lite snowflake conjure + webtunnel vanilla @@ -565,4 +567,25 @@ P X + + uncensoreddns-dk-ipv4 + njalla-doh + faelix-ch-ipv4 + dns.digitale-gesellschaft.ch + dnscrypt.ca-1 + sth-doh-se + libredns + dnswarden-uncensor-dc-swiss + publicarray-au-doh + scaleway-fr + + + play.googleapis.com + drive.google.com + cdn.ampproject.org + api.github.com + dev.skype.com + verizon.com + eset.com + diff --git a/tordnscrypt/src/main/res/values/strings.xml b/tordnscrypt/src/main/res/values/strings.xml index 5f5c37f9d..dba2e73d5 100644 --- a/tordnscrypt/src/main/res/values/strings.xml +++ b/tordnscrypt/src/main/res/values/strings.xml @@ -148,6 +148,7 @@ Your new bridges from bridges.torproject.org: Save Close + Spoof SNI Wrong host name! Select Theme Day Mode @@ -467,6 +468,8 @@ Tor will make all OR connections through the SOCKS 5 proxy. Edit tor.conf directly Clear cache + TrackHostExits + Tor will track recent connections to hosts and attempt to reuse the same exit node for each. This option may help avoid endless captcha. IsolateDestAddr Don’t share circuits with streams targeting a different destination address. IsolateDestPort @@ -656,10 +659,10 @@ Defend with DNSCRYPT Access to I2P network with Purple I2P - Attention - InviZible Pro cannot start %1$s! Please check %2$s settings or try to Force Close the application. + Attention + Reset + InviZible Pro cannot start %1$s! Please try resetting %2$s settings. If this does not help, please reboot your device. - Force close Add custom server Invalid custom server configuration. Please check the SDNS field. diff --git a/tordnscrypt/src/main/res/xml/preferences_fast.xml b/tordnscrypt/src/main/res/xml/preferences_fast.xml index 080765c30..d1f8b1b8c 100644 --- a/tordnscrypt/src/main/res/xml/preferences_fast.xml +++ b/tordnscrypt/src/main/res/xml/preferences_fast.xml @@ -111,6 +111,11 @@ android:targetClass="pan.alexander.tordnscrypt.settings.SettingsActivity" android:targetPackage="@string/package_name" /> + +