diff --git a/README.md b/README.md index cf0bb4fb1..322452878 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ applicationId "com.yourname.themename" ``` Change Package Name in the project structure (optional): - - Just follow the instructions listed brilliantly here http://stackoverflow.com/a/29092698 + - Just follow the instructions listed brilliantly [here](http://stackoverflow.com/a/29092698) NOTE: If you change your project structure name, the AndroidManifest AND the build.gradle package names must match, or else encrypted assets will break. @@ -147,7 +147,7 @@ Then you would need to go to Play Developer Console. Then access to your app -> Third, if you would like to change where it checks for various things such as Amazon App Store Enforcement or Play Store Enforcement, you have options listed on line 16 and lines below it, simply change from `true` to `false` and vice versa to make your desired configuration. -Finally, if you would like to enable intensive mode anti-piracy (App package blacklist), add as many package names as you want under [BLACKLISTED_APPLICATIONS](app/src/main/kotlin/substratum/theme/template/AdvancedConstants.kt#L21) line 21. Then make sure to enable [ENABLE_APP_BLACKLIST_CHECK](app/ThemerConstants.gradle#L16) on line 16. +Finally, if you would like to enable intensive mode anti-piracy (App package blacklist), add as many package names as you want under [BLACKLISTED_APPLICATIONS](app/src/main/kotlin/substratum/theme/template/AdvancedConstants.kt#L12) on line 12. Then make sure to enable [ENABLE_APP_BLACKLIST_CHECK](app/ThemerConstants.gradle#L16) on line 16. **Under no circumstances should you share your ThemerConstants.gradle file, unless specifically asked by an [official substratum developer](https://github.com/substratum/documentation#team-info-and-responsibilities)**! @@ -166,7 +166,7 @@ As of template version 11.0.0, themes have an additional check on the build of s What this means is that themes can ensure their themes ONLY function with our full release cycle with debug and Play Store releases. -If you would like to enable this feature (only allow your theme to be used with official substratum builds), all you have to do is to flip `true` to `false` [here](app/ThemerConstants.gradle#L22)! +If you would like to enable this feature (only allow your theme to be used with official substratum builds), all you have to do is to flip `true` to `false` [here](app/ThemerConstants.gradle#L20)! ### Now what? Nothing. Now you're set to publish your theme! diff --git a/app/ThemerConstants.gradle b/app/ThemerConstants.gradle index c25796e28..be5379a91 100644 --- a/app/ThemerConstants.gradle +++ b/app/ThemerConstants.gradle @@ -14,9 +14,7 @@ ext { // Piracy library configurations ENABLE_APP_BLACKLIST_CHECK = false - ENFORCE_INTERNET_CHECK = false ENFORCE_GOOGLE_PLAY_INSTALL = false - ENFORCE_AMAZON_APP_STORE_INSTALL = false // Allow third party substratum builds ALLOW_THIRD_PARTY_SUBSTRATUM_BUILDS = true diff --git a/app/build.gradle b/app/build.gradle index 58f0eae62..0d4e4e969 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,12 +5,18 @@ import javax.crypto.SecretKey import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.SecretKeySpec +tasks.whenTaskAdded { task -> + if (task.name.startsWith("lint")) { + task.enabled = false + } +} + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply from: 'ThemerConstants.gradle' ext { - // Encryption values, do not touch as we generate a random key every time you compile! + // Themers: DO NOT MODIFY byte[] key = new byte[16] new Random().nextBytes(key) KEY = key @@ -30,36 +36,37 @@ android { // We are only supporting Nougat and above, all new changes will incorporate Nougat changes // to the substratum repo rather than anything lower. Keep targetSdkVersion the same. minSdkVersion 24 - targetSdkVersion 28 // Both versions must be changed to increment on Play Store/user's devices versionCode 2 versionName "2.0" - // Themers: Do not touch this, they will only formulate integrity structure of the core - // template + // Themers: DO NOT MODIFY buildConfigField "boolean", "SUPPORTS_THIRD_PARTY_SYSTEMS", "" + SUPPORTS_THIRD_PARTY_SYSTEMS - buildConfigField "String", "BASE_64_LICENSE_KEY", "\"" + BASE_64_LICENSE_KEY + "\"" - buildConfigField "String", "APK_SIGNATURE_PRODUCTION", "\"" + APK_SIGNATURE_PRODUCTION + "\"" buildConfigField "boolean", "ENABLE_APP_BLACKLIST_CHECK", "" + ENABLE_APP_BLACKLIST_CHECK - buildConfigField "boolean", "ENFORCE_INTERNET_CHECK", "" + ENFORCE_INTERNET_CHECK - buildConfigField "boolean", "ENFORCE_GOOGLE_PLAY_INSTALL", "" + ENFORCE_GOOGLE_PLAY_INSTALL - buildConfigField "boolean", "ENFORCE_AMAZON_APP_STORE_INSTALL", "" + ENFORCE_AMAZON_APP_STORE_INSTALL buildConfigField "boolean", "ALLOW_THIRD_PARTY_SUBSTRATUM_BUILDS", "" + ALLOW_THIRD_PARTY_SUBSTRATUM_BUILDS - resValue "string", "encryption_status", (shouldEncrypt() ? "onCompileVerify" : "false") - buildConfigField "String", "IV_KEY", "\"" + IV_KEY + "\"" buildConfigField "byte[]", "DECRYPTION_KEY", String.valueOf("\"" + KEY + "\"").replace("\"", "").replace("[", "{").replace("]", "}") buildConfigField "byte[]", "IV_KEY", String.valueOf("\"" + IV_KEY + "\"").replace("\"", "").replace("[", "{").replace("]", "}") + resValue "string", "encryption_status", (shouldEncrypt() ? "onCompileVerify" : "false") } buildTypes { debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + + // Themers: DO NOT MODIFY + buildConfigField "boolean", "ENFORCE_GOOGLE_PLAY_INSTALL", "false" + buildConfigField "String", "BASE_64_LICENSE_KEY", "\"\"" + buildConfigField "String", "APK_SIGNATURE_PRODUCTION", "\"\"" } release { - // When you compile an APK as release, your resources and IV keys will be safeguarded minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + + // Themers: DO NOT MODIFY + buildConfigField "boolean", "ENFORCE_GOOGLE_PLAY_INSTALL", "" + ENFORCE_GOOGLE_PLAY_INSTALL + buildConfigField "String", "BASE_64_LICENSE_KEY", "\"" + BASE_64_LICENSE_KEY + "\"" + buildConfigField "String", "APK_SIGNATURE_PRODUCTION", "\"" + APK_SIGNATURE_PRODUCTION + "\"" } } sourceSets { @@ -69,13 +76,13 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'com.github.javiersantos:PiracyChecker:1.2.3' + implementation 'com.github.javiersantos:PiracyChecker:1.2.4' implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version") { transitive = true } } -// Themers, do not touch this! This is our function to help us encrypt your assets! +// Themers: DO NOT MODIFY ANYTHING BELOW task encryptAssets { if (!shouldEncrypt()) { println("Skipping assets encryption...") @@ -169,7 +176,3 @@ boolean shouldEncrypt() { ArrayList tasks = project.gradle.startParameter.taskNames return SHOULD_ENCRYPT_ASSETS && Arrays.toString(tasks).toLowerCase().contains("release") } - -repositories { - mavenCentral() -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3a23ec647..2997371a4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -26,6 +26,10 @@ + + + + @@ -60,7 +64,7 @@ + android:value="14.0.2"/> diff --git a/app/src/main/kotlin/substratum/theme/template/AdvancedConstants.kt b/app/src/main/kotlin/substratum/theme/template/AdvancedConstants.kt index 6c1283a19..4edca8cbb 100644 --- a/app/src/main/kotlin/substratum/theme/template/AdvancedConstants.kt +++ b/app/src/main/kotlin/substratum/theme/template/AdvancedConstants.kt @@ -2,15 +2,6 @@ package substratum.theme.template object AdvancedConstants { - // Dynamic filter that only works on Substratum 627+ - // WARNING: Only enable if you are sure you want certification status to pass on Substratum - // before launching the theme, or else it will throw an unauthorized toast! - const internal val SUBSTRATUM_FILTER_CHECK = false - - // Miscellaneous Checks - const val ENFORCE_MINIMUM_SUBSTRATUM_VERSION = true - const val MINIMUM_SUBSTRATUM_VERSION = 712 // 510 is the final MM build - // Custom message on theme launch, see theme_strings.xml for changing the dialog content // Set SHOW_DIALOG_REPEATEDLY to true if you want the dialog to be showed on every theme launch const val SHOW_LAUNCH_DIALOG = false diff --git a/app/src/main/kotlin/substratum/theme/template/SubstratumLauncher.kt b/app/src/main/kotlin/substratum/theme/template/SubstratumLauncher.kt index bab6d36ed..62ded9023 100644 --- a/app/src/main/kotlin/substratum/theme/template/SubstratumLauncher.kt +++ b/app/src/main/kotlin/substratum/theme/template/SubstratumLauncher.kt @@ -10,30 +10,17 @@ import android.os.Bundle import android.support.v7.app.AlertDialog import android.util.Log import android.widget.Toast -import com.github.javiersantos.piracychecker.PiracyChecker -import com.github.javiersantos.piracychecker.PiracyCheckerUtils -import com.github.javiersantos.piracychecker.enums.InstallerID -import com.github.javiersantos.piracychecker.enums.PiracyCheckerCallback -import com.github.javiersantos.piracychecker.enums.PiracyCheckerError -import com.github.javiersantos.piracychecker.enums.PirateApp -import substratum.theme.template.AdvancedConstants.ENFORCE_MINIMUM_SUBSTRATUM_VERSION -import substratum.theme.template.AdvancedConstants.MINIMUM_SUBSTRATUM_VERSION +import com.github.javiersantos.piracychecker.* +import com.github.javiersantos.piracychecker.enums.* +import com.github.javiersantos.piracychecker.utils.apkSignature import substratum.theme.template.AdvancedConstants.ORGANIZATION_THEME_SYSTEMS import substratum.theme.template.AdvancedConstants.OTHER_THEME_SYSTEMS import substratum.theme.template.AdvancedConstants.SHOW_DIALOG_REPEATEDLY import substratum.theme.template.AdvancedConstants.SHOW_LAUNCH_DIALOG -import substratum.theme.template.AdvancedConstants.SUBSTRATUM_FILTER_CHECK -import substratum.theme.template.ThemeFunctions.SUBSTRATUM_PACKAGE_NAME -import substratum.theme.template.ThemeFunctions.checkSubstratumIntegrity +import substratum.theme.template.ThemeFunctions.checkApprovedSignature import substratum.theme.template.ThemeFunctions.getSelfSignature -import substratum.theme.template.ThemeFunctions.getSelfVerifiedIntentResponse import substratum.theme.template.ThemeFunctions.getSelfVerifiedPirateTools -import substratum.theme.template.ThemeFunctions.getSelfVerifiedThemeEngines -import substratum.theme.template.ThemeFunctions.getSubstratumFromPlayStore -import substratum.theme.template.ThemeFunctions.getSubstratumUpdatedResponse -import substratum.theme.template.ThemeFunctions.hasOtherThemeSystem import substratum.theme.template.ThemeFunctions.isCallingPackageAllowed -import substratum.theme.template.ThemeFunctions.isPackageInstalled /** * NOTE TO THEMERS @@ -47,175 +34,53 @@ import substratum.theme.template.ThemeFunctions.isPackageInstalled class SubstratumLauncher : Activity() { - private var substratumIntentData = "projekt.substratum.THEME" - private var getKeysIntent = "projekt.substratum.GET_KEYS" - private var receiveKeysIntent = "projekt.substratum.RECEIVE_KEYS" - private var tag = "SubstratumThemeReport" - private var piracyChecker: PiracyChecker? = null + private val debug = false + private val tag = "SubstratumThemeReport" + private val substratumIntentData = "projekt.substratum.THEME" + private val getKeysIntent = "projekt.substratum.GET_KEYS" + private val receiveKeysIntent = "projekt.substratum.RECEIVE_KEYS" - private fun calibrateSystem(certified: Boolean) { - if (!BuildConfig.DEBUG) { // Themers may want to change this for release builds! - startAntiPiracyCheck(certified) + private val themePiracyCheck by lazy { + if (BuildConfig.ENABLE_APP_BLACKLIST_CHECK) { + getSelfVerifiedPirateTools(applicationContext) } else { - quitSelf(certified) + false } } - private fun startAntiPiracyCheck(certified: Boolean) { - if (piracyChecker != null) { - piracyChecker!!.start() - } else { - if (BuildConfig.BASE_64_LICENSE_KEY.isEmpty() && !BuildConfig.DEBUG) { - Log.e(tag, PiracyCheckerUtils.getAPKSignature(this)) - } - - piracyChecker = PiracyChecker(this) - if (BuildConfig.ENFORCE_GOOGLE_PLAY_INSTALL) - piracyChecker!!.enableInstallerId(InstallerID.GOOGLE_PLAY) - if (BuildConfig.ENFORCE_AMAZON_APP_STORE_INSTALL) - piracyChecker!!.enableInstallerId(InstallerID.AMAZON_APP_STORE) - - piracyChecker!!.callback(object : PiracyCheckerCallback() { - override fun allow() { - quitSelf(certified) - } - - override fun dontAllow(error: PiracyCheckerError, pirateApp: PirateApp?) { - val parse = String.format( - getString(R.string.toast_unlicensed), - getString(R.string.ThemeName)) - Toast.makeText(this@SubstratumLauncher, parse, Toast.LENGTH_SHORT).show() - finish() - } - }) - - if (BuildConfig.BASE_64_LICENSE_KEY.isNotEmpty()) { - piracyChecker!!.enableGooglePlayLicensing(BuildConfig.BASE_64_LICENSE_KEY) - } - if (BuildConfig.APK_SIGNATURE_PRODUCTION.isNotEmpty()) { - piracyChecker!!.enableSigningCertificate(BuildConfig.APK_SIGNATURE_PRODUCTION) - } - piracyChecker!!.start() - } - } - - private fun quitSelf(certified: Boolean): Boolean { - if (!hasOtherThemeSystem(this)) { - if (!isPackageInstalled(applicationContext, SUBSTRATUM_PACKAGE_NAME)) { - getSubstratumFromPlayStore(this) - return false - } - if (ENFORCE_MINIMUM_SUBSTRATUM_VERSION - && !getSubstratumUpdatedResponse(applicationContext)) { - val parse = String.format( - getString(R.string.outdated_substratum), - getString(R.string.ThemeName), - MINIMUM_SUBSTRATUM_VERSION.toString()) - Toast.makeText(this, parse, Toast.LENGTH_SHORT).show() - return false - } - } else if (!BuildConfig.SUPPORTS_THIRD_PARTY_SYSTEMS) { - Toast.makeText(this, R.string.unauthorized_theme_client, Toast.LENGTH_LONG).show() - finish() - return false - } - - var returnIntent = Intent() - if (intent.action == getKeysIntent) { - returnIntent = Intent(receiveKeysIntent) - } - - val themeName = getString(R.string.ThemeName) - val themeAuthor = getString(R.string.ThemeAuthor) - val themePid = packageName - returnIntent.putExtra("theme_name", themeName) - returnIntent.putExtra("theme_author", themeAuthor) - returnIntent.putExtra("theme_pid", themePid) - - val themeLaunchType = getSelfVerifiedThemeEngines(applicationContext) - val themeHash = getSelfSignature(applicationContext) - var themePiracyCheck = false - if (BuildConfig.ENABLE_APP_BLACKLIST_CHECK) - themePiracyCheck = getSelfVerifiedPirateTools(applicationContext) - if (themePiracyCheck or (SUBSTRATUM_FILTER_CHECK && !certified)) { - Toast.makeText(this, R.string.unauthorized, Toast.LENGTH_LONG).show() - finish() - return false - } - returnIntent.putExtra("theme_hash", themeHash) - returnIntent.putExtra("theme_launch_type", themeLaunchType) - returnIntent.putExtra("theme_debug", BuildConfig.DEBUG) - returnIntent.putExtra("theme_piracy_check", themePiracyCheck) - returnIntent.putExtra("encryption_key", BuildConfig.DECRYPTION_KEY) - returnIntent.putExtra("iv_encrypt_key", BuildConfig.IV_KEY) - - val callingPackage = intent.getStringExtra("calling_package_name") - if (callingPackage == null) { - val parse = String.format( - getString(R.string.outdated_substratum), - getString(R.string.ThemeName), - 915) - Toast.makeText(this, parse, Toast.LENGTH_SHORT).show() - finish() - return false - } - if (!isCallingPackageAllowed(callingPackage)) { - return false - } else { - returnIntent.`package` = callingPackage - } - - if (intent.action == substratumIntentData) { - setResult(getSelfVerifiedIntentResponse(applicationContext)!!, returnIntent) - } else if (intent.action == getKeysIntent) { - returnIntent.action = receiveKeysIntent - sendBroadcast(returnIntent) - } - finish() - return true - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // Reject all other apps trying to hijack the theme first - val caller = callingActivity?.packageName - var callerVerified = false - - val themeSystems: MutableList = mutableListOf() - themeSystems.addAll(ORGANIZATION_THEME_SYSTEMS) - themeSystems.addAll(OTHER_THEME_SYSTEMS) - if (caller != null) { - themeSystems - .filter { caller.startsWith(prefix = it, ignoreCase = true) } - .forEach { callerVerified = true } - } - if (!callerVerified) { + /* STEP 1: Block hijackers */ + val caller = callingActivity!!.packageName + val organizationsSystem = ORGANIZATION_THEME_SYSTEMS.contains(caller) + val supportedSystem = organizationsSystem || OTHER_THEME_SYSTEMS.contains(caller) + if (!BuildConfig.SUPPORTS_THIRD_PARTY_SYSTEMS && !supportedSystem) { Log.e(tag, "This theme does not support the launching theme system. [HIJACK] ($caller)") - val hijackString = - String.format(getString(R.string.unauthorized_theme_client_hijack), caller) - Toast.makeText(this, hijackString, Toast.LENGTH_LONG).show() + Toast.makeText(this, + String.format(getString(R.string.unauthorized_theme_client_hijack), caller), + Toast.LENGTH_LONG).show() finish() - return - } else { + } + if (debug) { Log.d(tag, "'$caller' has been authorized to launch this theme. (Phase 1)") } - // We will ensure that our support is added where it belongs - val intent = intent + /* STEP 2: Ensure that our support is added where it belongs */ val action = intent.action - var verified = false - val certified = intent.getBooleanExtra("certified", false) - val sharedPref = getPreferences(Context.MODE_PRIVATE) + var verified = false if ((action == substratumIntentData) or (action == getKeysIntent)) { - verified = when { - BuildConfig.ALLOW_THIRD_PARTY_SUBSTRATUM_BUILDS -> true - else -> checkSubstratumIntegrity(this) + // Assume this called from organization's app + if (organizationsSystem) { + verified = when { + BuildConfig.ALLOW_THIRD_PARTY_SUBSTRATUM_BUILDS -> true + else -> checkApprovedSignature(this, caller) + } } } else { OTHER_THEME_SYSTEMS - .filter { action.startsWith(prefix = it, ignoreCase = true) } + .filter { action?.startsWith(prefix = it, ignoreCase = true) ?: false } .forEach { verified = true } } if (!verified) { @@ -223,63 +88,108 @@ class SubstratumLauncher : Activity() { Toast.makeText(this, R.string.unauthorized_theme_client, Toast.LENGTH_LONG).show() finish() return - } else { + } + if (debug) { Log.d(tag, "'$action' has been authorized to launch this theme. (Phase 2)") } + + /* STEP 3: Do da thang */ if (SHOW_LAUNCH_DIALOG) run { if (SHOW_DIALOG_REPEATEDLY) { - showDialog(certified) + showDialog() sharedPref.edit().remove("dialog_showed").apply() } else if (!sharedPref.getBoolean("dialog_showed", false)) { - showDialog(certified) + showDialog() sharedPref.edit().putBoolean("dialog_showed", true).apply() } else { - if (BuildConfig.ENFORCE_INTERNET_CHECK) { - if (sharedPref.getInt("last_version", 0) == BuildConfig.VERSION_CODE) { - calibrateSystem(certified) - } else { - checkConnection(certified) - } - } else { - calibrateSystem(certified) - } - } - } else if (BuildConfig.ENFORCE_INTERNET_CHECK) { - if (sharedPref.getInt("last_version", 0) == BuildConfig.VERSION_CODE) { - calibrateSystem(certified) - } else { - checkConnection(certified) + startAntiPiracyCheck() } } else { - calibrateSystem(certified) + startAntiPiracyCheck() } } - private fun checkConnection(certified: Boolean) { - val editor = getPreferences(Context.MODE_PRIVATE).edit() - editor.putInt("last_version", BuildConfig.VERSION_CODE).apply() - calibrateSystem(certified) + private fun startAntiPiracyCheck() { + if (BuildConfig.BASE_64_LICENSE_KEY.isEmpty() && debug && !BuildConfig.DEBUG) { + Log.e(tag, apkSignature) + } + + if (!themePiracyCheck) { + piracyChecker { + if (BuildConfig.ENFORCE_GOOGLE_PLAY_INSTALL) { + enableInstallerId(InstallerID.GOOGLE_PLAY) + } + if (BuildConfig.BASE_64_LICENSE_KEY.isNotEmpty()) { + enableGooglePlayLicensing(BuildConfig.BASE_64_LICENSE_KEY) + } + if (BuildConfig.APK_SIGNATURE_PRODUCTION.isNotEmpty()) { + enableSigningCertificate(BuildConfig.APK_SIGNATURE_PRODUCTION) + } + callback { + allow { + val returnIntent = if (intent.action == getKeysIntent) { + Intent(receiveKeysIntent) + } else { + Intent() + } + + val themeName = getString(R.string.ThemeName) + val themeAuthor = getString(R.string.ThemeAuthor) + val themePid = packageName + returnIntent.putExtra("theme_name", themeName) + returnIntent.putExtra("theme_author", themeAuthor) + returnIntent.putExtra("theme_pid", themePid) + returnIntent.putExtra("theme_debug", BuildConfig.DEBUG) + returnIntent.putExtra("theme_piracy_check", themePiracyCheck) + returnIntent.putExtra("encryption_key", BuildConfig.DECRYPTION_KEY) + returnIntent.putExtra("iv_encrypt_key", BuildConfig.IV_KEY) + + val callingPackage = intent.getStringExtra("calling_package_name") + if (!isCallingPackageAllowed(callingPackage)) { + finish() + } else { + returnIntent.`package` = callingPackage + } + + if (intent.action == substratumIntentData) { + setResult(getSelfSignature(applicationContext), returnIntent) + } else if (intent.action == getKeysIntent) { + returnIntent.action = receiveKeysIntent + sendBroadcast(returnIntent) + } + destroy() + finish() + } + doNotAllow { _, _ -> + val parse = String.format( + getString(R.string.toast_unlicensed), + getString(R.string.ThemeName)) + Toast.makeText(this@SubstratumLauncher, parse, Toast.LENGTH_SHORT).show() + destroy() + finish() + } + onError { error -> + Toast.makeText(this@SubstratumLauncher, error.toString(), Toast.LENGTH_LONG) + .show() + destroy() + finish() + } + } + }.start() + } else { + Toast.makeText(this, R.string.unauthorized, Toast.LENGTH_LONG).show() + finish() + } } - private fun showDialog(certified: Boolean) { + private fun showDialog() { val dialog = AlertDialog.Builder(this, R.style.DialogStyle) .setCancelable(false) .setIcon(R.mipmap.ic_launcher) .setTitle(R.string.launch_dialog_title) .setMessage(R.string.launch_dialog_content) - .setPositiveButton(R.string.launch_dialog_positive) { _, _ -> - val sharedPref = getPreferences(Context.MODE_PRIVATE) - if (BuildConfig.ENFORCE_INTERNET_CHECK) { - if (sharedPref.getInt("last_version", 0) == BuildConfig.VERSION_CODE) { - calibrateSystem(certified) - } else { - checkConnection(certified) - } - } else { - calibrateSystem(certified) - } - } + .setPositiveButton(R.string.launch_dialog_positive) { _, _ -> startAntiPiracyCheck() } if (getString(R.string.launch_dialog_negative).isNotEmpty()) { if (getString(R.string.launch_dialog_negative_url).isNotEmpty()) { dialog.setNegativeButton(R.string.launch_dialog_negative) { _, _ -> diff --git a/app/src/main/kotlin/substratum/theme/template/ThemeFunctions.kt b/app/src/main/kotlin/substratum/theme/template/ThemeFunctions.kt index cb5d8363f..4ea8ab221 100644 --- a/app/src/main/kotlin/substratum/theme/template/ThemeFunctions.kt +++ b/app/src/main/kotlin/substratum/theme/template/ThemeFunctions.kt @@ -1,158 +1,57 @@ package substratum.theme.template import android.annotation.SuppressLint -import android.app.Activity import android.content.Context -import android.content.Intent import android.content.pm.PackageManager import android.content.pm.Signature -import android.net.Uri import android.os.RemoteException -import android.widget.Toast import substratum.theme.template.AdvancedConstants.BLACKLISTED_APPLICATIONS -import substratum.theme.template.AdvancedConstants.MINIMUM_SUBSTRATUM_VERSION +import substratum.theme.template.AdvancedConstants.ORGANIZATION_THEME_SYSTEMS import substratum.theme.template.AdvancedConstants.OTHER_THEME_SYSTEMS @Suppress("ConstantConditionIf") object ThemeFunctions { - val SUBSTRATUM_PACKAGE_NAME = "projekt.substratum" - - fun isPackageInstalled(context: Context, package_name: String): Boolean { - return try { - val pm = context.packageManager - val ai = context.packageManager.getApplicationInfo(package_name, 0) - pm.getPackageInfo(package_name, PackageManager.GET_ACTIVITIES) - ai.enabled - } catch (e: Exception) { - false - } - } - - @SuppressLint("PackageManagerGetSignatures") - private fun checkSubstratumIntegrity(context: Context, - packageName: String?): Boolean { - return try { - val pm = context.packageManager - val pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES) - if (pi.signatures != null - && pi.signatures.size == 1 - && ((SIGNATURES[0] == pi.signatures[0]) || - (SIGNATURES[1] == pi.signatures[0]))) { - return true - } - false - } catch (e: RemoteException) { - false - } - } - - fun getSubstratumFromPlayStore(activity: Activity) { - val playURL = "https://play.google.com/store/apps/details?id=projekt.substratum" - val i = Intent(Intent.ACTION_VIEW) - Toast.makeText( - activity, - activity.getString(R.string.toast_substratum), - Toast.LENGTH_SHORT - ).show() - i.data = Uri.parse(playURL) - activity.startActivity(i) - activity.finishAffinity() - } - - fun hasOtherThemeSystem(context: Context): Boolean { - try { - val pm = context.packageManager - for (s: String in OTHER_THEME_SYSTEMS) { - val ai = pm.getApplicationInfo(s, 0) - pm.getPackageInfo(s, PackageManager.GET_ACTIVITIES) - return ai.enabled - } - } catch (e: Exception) { - } - return false - } - - fun getSubstratumUpdatedResponse(context: Context): Boolean { - try { - val packageInfo = context.applicationContext.packageManager - .getPackageInfo(SUBSTRATUM_PACKAGE_NAME, 0) - if (packageInfo.versionCode >= MINIMUM_SUBSTRATUM_VERSION) { - return true - } - } catch (e: Exception) { - // Suppress warning - } - - return false - } - - fun getSelfVerifiedIntentResponse(context: Context): Int? { - return if (BuildConfig.SUPPORTS_THIRD_PARTY_SYSTEMS) { - getSelfSignature(context) - } else { - getSubstratumSignature(context) + fun isCallingPackageAllowed(packageId: String): Boolean { + if (BuildConfig.SUPPORTS_THIRD_PARTY_SYSTEMS) { + OTHER_THEME_SYSTEMS.contains(packageId) } + return ORGANIZATION_THEME_SYSTEMS.contains(packageId) } - private fun checkPackageRegex(context: Context, stringArray: Array): Boolean { + fun getSelfVerifiedPirateTools(context: Context): Boolean { val pm = context.packageManager val packages = pm.getInstalledApplications(PackageManager.GET_META_DATA) val listOfInstalled = arrayListOf() packages.mapTo(listOfInstalled) { it.packageName } - return stringArray.any { listOfInstalled.contains(it) } - } - - fun getSelfVerifiedPirateTools(context: Context): Boolean { - return checkPackageRegex(context, BLACKLISTED_APPLICATIONS) - } - - fun checkSubstratumIntegrity(context: Context): Boolean { - SIGNATURES - .filter { checkSubstratumIntegrity(context, SUBSTRATUM_PACKAGE_NAME) } - .forEach { return true } - return false - } - - fun getSelfVerifiedThemeEngines(context: Context): Boolean? { - val isPermitted: Boolean? = OTHER_THEME_SYSTEMS.any { isPackageInstalled(context, it) } - if (BuildConfig.SUPPORTS_THIRD_PARTY_SYSTEMS) { - return isPermitted - } else if (isPackageInstalled(context, SUBSTRATUM_PACKAGE_NAME)) { - return (!isPermitted!!) - } - return false - } - - fun isCallingPackageAllowed(packageId: String): Boolean { - if (packageId == SUBSTRATUM_PACKAGE_NAME) return true - if (BuildConfig.SUPPORTS_THIRD_PARTY_SYSTEMS) { - OTHER_THEME_SYSTEMS.filter { packageId == it }.forEach { return true } - } - return false + return BLACKLISTED_APPLICATIONS.any { listOfInstalled.contains(it) } } + @Suppress("DEPRECATION") @SuppressLint("PackageManagerGetSignatures") - private fun getSubstratumSignature(context: Context): Int { - val sigs: Array - try { - sigs = context.packageManager.getPackageInfo( - SUBSTRATUM_PACKAGE_NAME, - PackageManager.GET_SIGNATURES - ).signatures - return sigs[0].hashCode() - } catch (e: PackageManager.NameNotFoundException) { - e.printStackTrace() - } - - return 0 + fun checkApprovedSignature(context: Context, packageName: String): Boolean { + SIGNATURES.filter { + try { + val pm = context.packageManager + val pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES) + if (pi.signatures != null && pi.signatures.size == 1 + && ((SIGNATURES[0] == pi.signatures[0]) || + (SIGNATURES[1] == pi.signatures[0]))) { + return true + } + return false + } catch (e: RemoteException) { + return false + } + }.forEach { return true } + return false } + @Suppress("DEPRECATION") @SuppressLint("PackageManagerGetSignatures") fun getSelfSignature(context: Context): Int { - val sigs: Array try { - sigs = context.packageManager.getPackageInfo( + val sigs = context.packageManager.getPackageInfo( context.packageName, PackageManager.GET_SIGNATURES ).signatures diff --git a/app/src/main/res/values/antipiracy_strings.xml b/app/src/main/res/values/antipiracy_strings.xml index 13b1a9209..949e41126 100644 --- a/app/src/main/res/values/antipiracy_strings.xml +++ b/app/src/main/res/values/antipiracy_strings.xml @@ -1,13 +1,6 @@ - Please install Substratum before continuing! This copy of %s is not licensed! - This theme requires a license check before continuing! - Theme Ready Google Apps were not detected on your system.\n\nBy confirming, you agree that you will receive little to no support. - Theme Ready Google Apps were detected on your system, but you have %s updated from the Play Store.\n\nPlease uninstall these updates prior to confirming or you agree that you will receive little to no support. - Cancel - Confirm This theme located a few piracy tools installed. Please uninstall them to continue. This theme does not support the current theming system, please use an official client or an official test client available on Telegram! Theme was attempted to be hijacked by \'%s\' - This version of %s requires substratum version %s and up! Please upgrade! \ No newline at end of file diff --git a/build.gradle b/build.gradle index 4a470f9a5..a4877880e 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.0-beta02' + classpath 'com.android.tools.build:gradle:3.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files