diff --git a/build.gradle b/build.gradle index 4618b50..1b649c0 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group 'com.stringcare' -version '3.6.3' +version '4.0.0' def siteUrl = 'https://github.com/StringCare/KotlinGradlePlugin' def gitUrl = 'https://github.com/StringCare/KotlinGradlePlugin.git' @@ -14,11 +14,14 @@ def gitUrl = 'https://github.com/StringCare/KotlinGradlePlugin.git' sourceCompatibility = 1.8 repositories { + google() + jcenter() mavenCentral() } dependencies { implementation gradleApi() + implementation group: 'com.android.tools.build', name: 'gradle', version: '3.5.3' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" implementation group: 'com.google.guava', name: 'guava', version: '28.0-jre' testCompile group: 'junit', name: 'junit', version: '4.12' diff --git a/src/main/kotlin/StringCare.kt b/src/main/kotlin/StringCare.kt index 1e2e950..dae47df 100644 --- a/src/main/kotlin/StringCare.kt +++ b/src/main/kotlin/StringCare.kt @@ -1,8 +1,7 @@ + import components.* -import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.internal.plugins.DslObject open class StringCare : Plugin { @@ -23,16 +22,11 @@ open class StringCare : Plugin { } @JvmStatic - internal val moduleMap: MutableMap = mutableMapOf() - - @JvmStatic - internal val variantMap: MutableMap = mutableMapOf() + internal var configuration: Configuration = defaultConfig() @JvmStatic - internal var mainModule: String = defaultMainModule + internal var variantMap = mutableMapOf() - @JvmStatic - internal var debug: Boolean = defaultDebug } private lateinit var project: Project @@ -45,181 +39,115 @@ open class StringCare : Plugin { absoluteProjectPath = project.absolutePath() this.project.afterEvaluate { - extension.modules.forEach { module -> - moduleMap[module.name] = Configuration(module.name).apply { - debug = extension.debug - } - if (module.srcFolders.isNotEmpty()) { - moduleMap[module.name]!!.srcFolders.addAll(module.srcFolders) - } - if (module.stringFiles.isNotEmpty()) { - moduleMap[module.name]!!.stringFiles.addAll(module.stringFiles) - } - if (module.assetsFiles.isNotEmpty()) { - moduleMap[module.name]!!.assetsFiles.addAll(module.assetsFiles) - } - - if (moduleMap[module.name]!!.srcFolders.isEmpty()) { - moduleMap[module.name]!!.srcFolders.addAll(defaultConfig().srcFolders) - } - if (moduleMap[module.name]!!.stringFiles.isEmpty()) { - moduleMap[module.name]!!.stringFiles.addAll(defaultConfig().stringFiles) - } + this.project.applicationVariants()?.forEach { variant -> + variantMap[variant.name] = variant.applicationId } - extension.variants.forEach { variant -> - variantMap[variant.name] = VariantApplicationId(variant.name).apply { - applicationId = variant.applicationId - mockedFingerprint = variant.mockedFingerprint - skip = variant.skip - } + configuration = this.project.config(extension) + + if (configuration.debug) { + PrintUtils.print("PATH", absoluteProjectPath) } - this.project.registerTask() + this.project.registerTask(configuration) } - this.project.gradle.addBuildListener(ExecutionListener( - debug = extension.debug, - dataFound = { _, _ -> - // nothing to do here - }, - mergeResourcesStart = { module, variant -> - fingerPrint(variantMap, module, variant, extension.debug) { key -> - when { - moduleMap.containsKey(module) -> { - val variantOrFlavor = extension.variants.find { - variant.toLowerCase().contains(it.name.toLowerCase()) - } - if (variantOrFlavor != null && variantOrFlavor.skip) { - PrintUtils.print(module, "Skipping $variant") - return@fingerPrint - } + this.project.gradle.addBuildListener( + ExecutionListener( + debug = configuration.debug, + dataFound = { _, _ -> + // nothing to do here + }, + mergeResourcesStart = { module, variant -> + configuration.name = module + if (variantMap.containsKey(variant)) { + configuration.applicationId = variantMap[variant] ?: "" + } + PrintUtils.print("", "ApplicationId: ${configuration.applicationId}", tab = true) + fingerPrint(module, variant, configuration) { key -> + if (configuration.skip) { + PrintUtils.print(module, "Skipping $variant") + return@fingerPrint + } - if ("none" == key || key.trim().isEmpty()) { - PrintUtils.print("No SHA1 key found for :$module:$variant") - return@fingerPrint - } + if ("none" == key || key.trim().isEmpty()) { + PrintUtils.print("No SHA1 key found for :$module:$variant") + return@fingerPrint + } - PrintUtils.print(module, "$variant:$key") - PrintUtils.print(module, backupStringRes) - moduleMap[module]?.let { configuration -> - backupResourceFiles(absoluteProjectPath, configuration) - } + PrintUtils.print(module, "$variant:$key") + PrintUtils.print(module, backupStringRes) + backupResourceFiles(absoluteProjectPath, configuration) - moduleMap[module]?.let { configuration -> - val files = locateResourceFiles(absoluteProjectPath, configuration) - files.forEach { file -> - modifyXML( - file.file, extension.main_module, key, extension.debug, - variantOrFlavor?.applicationId ?: "" - ) - } - } - PrintUtils.print(module, obfuscateStringRes) - } - else -> { - val defaultConfiguration = defaultConfig().apply { - name = module - } - if ("none" == key || key.trim().isEmpty()) { - PrintUtils.print("No SHA1 key found for :$module:$variant") - return@fingerPrint - } - PrintUtils.print(module, "$variant:$key") - PrintUtils.print(module, backupStringRes) - backupResourceFiles(absoluteProjectPath, defaultConfiguration) - PrintUtils.print(module, obfuscateStringRes) - val files = locateResourceFiles(absoluteProjectPath, defaultConfiguration) - files.forEach { file -> - modifyXML(file.file, extension.main_module, key, extension.debug) - } + + val files = locateResourceFiles(absoluteProjectPath, configuration) + files.forEach { file -> + modifyXML(file.file, key, configuration) } } - } + PrintUtils.print(module, obfuscateStringRes) + }, + mergeResourcesFinish = { module, _ -> + if (configuration.skip) { + return@ExecutionListener + } + PrintUtils.print(module, restoreStringRes) + restoreResourceFiles(absoluteProjectPath, module) + }, + mergeAssetsStart = { module, variant -> + configuration.name = module + if (variantMap.containsKey(variant)) { + configuration.applicationId = variantMap[variant] ?: "" + } + PrintUtils.print("", "ApplicationId: ${configuration.applicationId}", tab = true) + fingerPrint(module, variant, configuration) { key -> + if (configuration.skip) { + PrintUtils.print(module, "Skipping $variant") + return@fingerPrint + } - }, - mergeResourcesFinish = { module, variant -> - PrintUtils.print(module, restoreStringRes) - val variantOrFlavor = extension.variants.find { - variant.toLowerCase().contains(it.name.toLowerCase()) - } - if (variantOrFlavor != null && variantOrFlavor.skip) { - return@ExecutionListener - } - restoreResourceFiles(absoluteProjectPath, module) - }, - mergeAssetsStart = { module, variant -> - fingerPrint(variantMap, module, variant, extension.debug) { key -> - when { - moduleMap.containsKey(module) -> { - val variantOrFlavor = extension.variants.find { - variant.toLowerCase().contains(it.name.toLowerCase()) - } - if (variantOrFlavor != null && variantOrFlavor.skip) { - PrintUtils.print(module, "Skipping $variant") - return@fingerPrint - } + if ("none" == key || key.trim().isEmpty()) { + PrintUtils.print("No SHA1 key found for :$module:$variant") + return@fingerPrint + } - if ("none" == key || key.trim().isEmpty()) { - PrintUtils.print("No SHA1 key found for :$module:$variant") - return@fingerPrint - } + PrintUtils.print(module, "$variant:$key") + PrintUtils.print(module, backupAssets) + backupAssetsFiles(absoluteProjectPath, configuration) - PrintUtils.print(module, "$variant:$key") - PrintUtils.print(module, backupAssets) - moduleMap[module]?.let { configuration -> - backupAssetsFiles(absoluteProjectPath, configuration) - } - moduleMap[module]?.let { configuration -> - val files = locateAssetsFiles(absoluteProjectPath, configuration) - files.forEach { file -> - if (extension.debug) { - PrintUtils.print(null, file.file.getContent()) - } - obfuscateFile( - extension.main_module, - key, - file.file, - variantOrFlavor?.applicationId ?: "" - ) - if (extension.debug) { - PrintUtils.print(null, file.file.getContent()) - } - } + val files = locateAssetsFiles(absoluteProjectPath, configuration) + files.forEach { file -> + if (configuration.debug) { + PrintUtils.print(null, file.file.getContent()) + } + obfuscateFile( + key, + file.file, + configuration.applicationId + ) + if (configuration.debug) { + PrintUtils.print(null, file.file.getContent()) } - PrintUtils.print(module, obfuscateAssets) } + PrintUtils.print(module, obfuscateAssets) + } + }, + mergeAssetsFinish = { module, _ -> + if (configuration.skip) { + return@ExecutionListener } + PrintUtils.print(module, restoreAssets) + restoreAssetsFiles(absoluteProjectPath, module) } - }, - mergeAssetsFinish = { module, variant -> - PrintUtils.print(module, restoreAssets) - val variantOrFlavor = extension.variants.find { - variant.toLowerCase().contains(it.name.toLowerCase()) - } - if (variantOrFlavor != null && variantOrFlavor.skip) { - return@ExecutionListener - } - restoreAssetsFiles(absoluteProjectPath, module) - } - - )) + )) } open class Extension { - var debug: Boolean = false - var main_module: String = "app" - var modules: NamedDomainObjectContainer - @Suppress("UNCHECKED_CAST") - get() = DslObject(this).extensions.getByName("modules") as NamedDomainObjectContainer - internal set(value) { - DslObject(this).extensions.add("modules", value) - } - var variants: NamedDomainObjectContainer - @Suppress("UNCHECKED_CAST") - get() = DslObject(this).extensions.getByName("variants") as NamedDomainObjectContainer - internal set(value) { - DslObject(this).extensions.add("variants", value) - } + var assetsFiles = mutableListOf() + var stringFiles = mutableListOf() + var srcFolders = mutableListOf() + var debug = false + var skip = false + var mockedFingerprint = "" } open class Configuration(var name: String) { @@ -227,12 +155,9 @@ open class StringCare : Plugin { var stringFiles = mutableListOf() var srcFolders = mutableListOf() var debug = false - } - - open class VariantApplicationId(var name: String) { + var skip = false var applicationId = "" var mockedFingerprint = "" - var skip = false } } diff --git a/src/main/kotlin/components/AParser.kt b/src/main/kotlin/components/AParser.kt index ba6fc2d..40ea09d 100644 --- a/src/main/kotlin/components/AParser.kt +++ b/src/main/kotlin/components/AParser.kt @@ -1,8 +1,8 @@ package components -import StringCare.* +import StringCare +import StringCare.Configuration import models.AssetsFile -import models.ResourceFile import java.io.File fun locateAssetsFiles(projectPath: String, configuration: Configuration): List { @@ -36,9 +36,8 @@ fun restoreAssetsFiles(projectPath: String, module: String): List { return resourceFiles } -fun obfuscateFile(mainModule: String, key: String, file: File, mockId: String = "") { +fun obfuscateFile(key: String, file: File, mockId: String) { val obfuscation = Stark.obfuscate( - mainModule, key, file.readBytes(), mockId @@ -46,6 +45,6 @@ fun obfuscateFile(mainModule: String, key: String, file: File, mockId: String = file.writeBytes(obfuscation) } -fun revealFile(mainModule: String, key: String, file: File, mockId: String = "") { - file.writeBytes(Stark.reveal(mainModule, key, file.readBytes(), mockId)) +fun revealFile(key: String, file: File, mockId: String = "") { + file.writeBytes(Stark.reveal(key, file.readBytes(), mockId)) } diff --git a/src/main/kotlin/components/Execution.kt b/src/main/kotlin/components/Execution.kt index df4c544..adc53f7 100644 --- a/src/main/kotlin/components/Execution.kt +++ b/src/main/kotlin/components/Execution.kt @@ -1,5 +1,6 @@ package components +import StringCare import com.google.common.io.Files import models.ExecutionResult import java.io.IOException diff --git a/src/main/kotlin/components/Extensions.kt b/src/main/kotlin/components/Extensions.kt index 835c870..2fabb4d 100644 --- a/src/main/kotlin/components/Extensions.kt +++ b/src/main/kotlin/components/Extensions.kt @@ -1,10 +1,16 @@ package components import StringCare -import StringCare.* +import StringCare.Configuration +import StringCare.Extension +import com.android.build.gradle.AppExtension +import com.android.build.gradle.AppPlugin +import com.android.build.gradle.api.ApplicationVariant +import com.google.gson.Gson import groovy.json.StringEscapeUtils import models.AssetsFile import models.ResourceFile +import org.gradle.api.DomainObjectSet import org.gradle.api.Project import org.gradle.api.Task import org.slf4j.Logger @@ -245,40 +251,81 @@ fun File.assetsFile(configuration: Configuration): AssetsFile? { return if (valid) AssetsFile(validFile!!, sourceFolder, configuration.name) else null } -fun Project.absolutePath(): String = this.file(wrapperWindows).absolutePath.replace( - wrapperWindows, - emptyChar -) +fun Project.absolutePath(): String { + val fPath = this.file("build.gradle").absolutePath.replace( + "build.gradle", + emptyChar + ) + val p = fPath.split(File.separator) + return fPath.replace(p[p.size - 2] + File.separator, "") +} + +fun Project.module(): String { + val fPath = this.file("build.gradle").absolutePath.replace( + "build.gradle", + emptyChar + ) + val p = fPath.split(File.separator) + return p[p.size - 2] +} fun Project.createExtension(): Extension { - val extension = this.extensions.create(extensionName, Extension::class.java) - extension.modules = this.container(Configuration::class.java) - extension.variants = this.container(VariantApplicationId::class.java) - - StringCare.mainModule = extension.main_module - StringCare.debug = extension.debug - return extension -} - -fun Project.registerTask() { - this.tasks.addRule("Pattern: $gradleTaskNameObfuscate") { taskName -> - if (taskName.startsWith(gradleTaskNameObfuscate)) { - println("taskname $taskName") - task(taskName) { - it.doLast { - val variant = taskName.replace(gradleTaskNameObfuscate, "").uncapitalize() - println("variant $variant") - val task = this.tasks.getByName(gradleTaskNameObfuscate) as SCTestObfuscation - task.variant = variant - task.module = StringCare.mainModule - task.debug = StringCare.debug - task.greet() - } - } + return extensions.create(extensionName, Extension::class.java) +} + +fun Project.applicationVariants(): DomainObjectSet? { + if (this.plugins.hasPlugin(AppPlugin::class.java)) { + val extension = this.extensions.getByType(AppExtension::class.java) + return extension.applicationVariants + } + return null +} + +fun Project.config(extension: Extension): Configuration { + val mod = this.module() + return Configuration(mod).apply { + debug = extension.debug + skip = extension.skip + if (extension.srcFolders.isNotEmpty()) { + srcFolders.addAll(extension.srcFolders) + } + if (extension.stringFiles.isNotEmpty()) { + stringFiles.addAll(extension.stringFiles) + } + if (extension.assetsFiles.isNotEmpty()) { + assetsFiles.addAll(extension.assetsFiles) + } + if (extension.mockedFingerprint.isNotEmpty()) { + mockedFingerprint = extension.mockedFingerprint } } +} + +fun Project.registerTask(configuration: Configuration) { + val gson = Gson() + this.tasks.register(gradleTaskNameDoctor, SCPreview::class.java) this.tasks.register(gradleTaskNameObfuscate, SCTestObfuscation::class.java) + + val previewTask = this.tasks.getByPath(gradleTaskNameDoctor) as SCPreview + previewTask.module = configuration.name + previewTask.applicationId = configuration.applicationId + previewTask.srcFolders = gson.toJson(configuration.srcFolders) + previewTask.stringFiles = gson.toJson(configuration.stringFiles) + previewTask.assetsFiles = gson.toJson(configuration.assetsFiles) + previewTask.mockedFingerprint = configuration.mockedFingerprint + previewTask.debug = configuration.debug + previewTask.skip = configuration.skip + + val obfuscateTask = this.tasks.getByPath(gradleTaskNameObfuscate) as SCTestObfuscation + obfuscateTask.module = configuration.name + obfuscateTask.applicationId = configuration.applicationId + obfuscateTask.srcFolders = gson.toJson(configuration.srcFolders) + obfuscateTask.stringFiles = gson.toJson(configuration.stringFiles) + obfuscateTask.assetsFiles = gson.toJson(configuration.assetsFiles) + obfuscateTask.mockedFingerprint = configuration.mockedFingerprint + obfuscateTask.debug = configuration.debug + obfuscateTask.skip = configuration.skip } fun Process.outputString(): String { diff --git a/src/main/kotlin/components/Fingerprint.kt b/src/main/kotlin/components/Fingerprint.kt index a01018e..c8a2780 100644 --- a/src/main/kotlin/components/Fingerprint.kt +++ b/src/main/kotlin/components/Fingerprint.kt @@ -10,18 +10,18 @@ private class Fingerprint { private var moduleLocated = false } - fun extract(module: String, variant: String, debug: Boolean, trace: String): String { + fun extract(module: String, variant: String, configuration: StringCare.Configuration, trace: String): String { val lines = trace.split("\n") lines.forEach { line -> when { - line.toLowerCase().contains("downloading") -> if (debug) { - PrintUtils.print(module, line, debug) + line.toLowerCase().contains("downloading") -> if (configuration.debug) { + PrintUtils.print(module, line, configuration.debug) } - line.toLowerCase().contains("unzipping") -> if (debug) { - PrintUtils.print(module, line, debug) + line.toLowerCase().contains("unzipping") -> if (configuration.debug) { + PrintUtils.print(module, line, configuration.debug) } - line.toLowerCase().contains("permissions") -> if (debug) { - PrintUtils.print(module, line, debug) + line.toLowerCase().contains("permissions") -> if (configuration.debug) { + PrintUtils.print(module, line, configuration.debug) } line.toLowerCase().contains("config:") && moduleLocated && variantLocated -> { val k = line.split(": ")[1].trim() @@ -29,10 +29,10 @@ private class Fingerprint { if (!valid) { key = k PrintUtils.print(module, "\uD83E\uDD2F no config defined for variant $variant", true) - if (debug) { + if (configuration.debug) { until = key } - } else if (debug) { + } else if (configuration.debug) { PrintUtils.print(module, "Module: $module", true) PrintUtils.print(module, "Variant: $variant", true) } @@ -40,8 +40,8 @@ private class Fingerprint { } line.toLowerCase().contains("sha1") && moduleLocated && variantLocated -> { key = line.split(" ")[1] - if (debug) { - PrintUtils.print(module, line, debug) + if (configuration.debug) { + PrintUtils.print(module, line, configuration.debug) } } line.toLowerCase().contains("error") -> { @@ -49,12 +49,12 @@ private class Fingerprint { } line.toLowerCase().contains("valid until") && moduleLocated && variantLocated -> { until = line.split(": ")[1] - if (debug) { - PrintUtils.print(module, line, debug) + if (configuration.debug) { + PrintUtils.print(module, line, configuration.debug) } } - line.toLowerCase().contains("store") && moduleLocated && variantLocated -> if (debug) { - PrintUtils.print(module, line, debug) + line.toLowerCase().contains("store") && moduleLocated && variantLocated -> if (configuration.debug) { + PrintUtils.print(module, line, configuration.debug) } line.toLowerCase().contains("variant") && moduleLocated -> { val locV = line.split(" ")[1] @@ -64,7 +64,7 @@ private class Fingerprint { } line.toLowerCase().contains(":$module") -> moduleLocated = true } - if (key != null && (!debug || debug && until != null)) { + if (key != null && (!configuration.debug || configuration.debug && until != null)) { return key!! } } @@ -76,26 +76,23 @@ private class Fingerprint { * Gets the signing report trace and extracts the fingerprint */ fun fingerPrint( - variantMap: MutableMap, module: String, variant: String, - debug: Boolean, + configuration: StringCare.Configuration, keyFound: (key: String) -> Unit ) { - if (variantMap.containsKey(variant)) { - if (variantMap[variant]!!.mockedFingerprint.isNotEmpty()) { - keyFound(variantMap[variant]!!.mockedFingerprint) - return - } + if (configuration.mockedFingerprint.isNotEmpty()) { + keyFound(configuration.mockedFingerprint) + return } signingReportTask().runCommand { _, report -> - keyFound(report.extractFingerprint(module, variant, debug)) + keyFound(report.extractFingerprint(module, variant, configuration)) } } /** * Returns the SHA1 fingerprint for the given trace */ -fun String.extractFingerprint(module: String = "app", variant: String = "debug", debug: Boolean = false): String { - return Fingerprint().extract(module, variant, debug, this) +fun String.extractFingerprint(module: String = "app", variant: String = "debug", configuration: StringCare.Configuration): String { + return Fingerprint().extract(module, variant, configuration, this) } \ No newline at end of file diff --git a/src/main/kotlin/components/Stark.kt b/src/main/kotlin/components/Stark.kt index 53b624c..fbda41c 100644 --- a/src/main/kotlin/components/Stark.kt +++ b/src/main/kotlin/components/Stark.kt @@ -1,5 +1,6 @@ package components +import StringCare import java.io.File import java.io.FileOutputStream import java.util.zip.ZipFile @@ -66,10 +67,10 @@ open class Stark { } @JvmStatic - external fun obfuscate(mainModule: String, key: String, value: ByteArray, mockId: String): ByteArray + external fun obfuscate(key: String, value: ByteArray, mockId: String): ByteArray @JvmStatic - external fun reveal(mainModule: String, key: String, value: ByteArray, mockId: String): ByteArray + external fun reveal(key: String, value: ByteArray, mockId: String): ByteArray } } \ No newline at end of file diff --git a/src/main/kotlin/components/Tasks.kt b/src/main/kotlin/components/Tasks.kt index b4cf1ab..0aad30e 100644 --- a/src/main/kotlin/components/Tasks.kt +++ b/src/main/kotlin/components/Tasks.kt @@ -49,7 +49,7 @@ internal fun basicGradleTask(directory: String): String { internal fun obfuscationTestGradleTask(directory: String): String { return """ cd $directory && - ${gradleWrapper()} ${gradleTaskNameObfuscate}Debug + ${gradleWrapper()} $gradleTaskNameObfuscate """.trimIndent() } diff --git a/src/main/kotlin/components/Vars.kt b/src/main/kotlin/components/Vars.kt index 3ae57ae..a3b8744 100644 --- a/src/main/kotlin/components/Vars.kt +++ b/src/main/kotlin/components/Vars.kt @@ -1,13 +1,8 @@ package components -import java.io.File - -internal const val version = "3.6.3" +internal const val version = "4.0.0" internal const val testProjectName = "KotlinSample" -internal const val defaultDebug = false internal const val defaultMainModule = "app" -internal const val defaultVariant = "debug" -internal val mainModuleTest = "$testProjectName${File.separator}$defaultMainModule" internal const val gradleTaskNameDoctor = "stringcarePreview" internal const val gradleTaskNameObfuscate = "stringcareTestObfuscate" internal const val extensionName = "stringcare" diff --git a/src/main/kotlin/components/XParser.kt b/src/main/kotlin/components/XParser.kt index b928896..8d4d6ac 100644 --- a/src/main/kotlin/components/XParser.kt +++ b/src/main/kotlin/components/XParser.kt @@ -1,6 +1,7 @@ package components -import StringCare.* +import StringCare +import StringCare.Configuration import models.ResourceFile import models.SAttribute import models.StringEntity @@ -80,9 +81,9 @@ fun parseXML(file: File): List { return entities } -fun modifyXML(file: File, mainModule: String, key: String, debug: Boolean, mockId: String = "") { +fun modifyXML(file: File, key: String, configuration: Configuration) { val stringEntities = parseXML(file) - if (debug) { + if (configuration.debug) { PrintUtils.print(null, file.getContent(), true) } @@ -94,20 +95,19 @@ fun modifyXML(file: File, mainModule: String, key: String, debug: Boolean, mockI it.tag == "string" && it.index == i } entity?.let { - node.textContent = obfuscateStringEntity(mainModule, key, it, mockId).value + node.textContent = obfuscateStringEntity(key, it, configuration.applicationId).value } } file.updateXML(doc) file.removeAttributes() - if (debug) { + if (configuration.debug) { PrintUtils.print(null, file.getContent(), true) } } -fun obfuscateStringEntity(mainModule: String, key: String, entity: StringEntity, mockId: String = ""): StringEntity { - val obfuscation = Stark.obfuscate( - mainModule, key, when (entity.androidTreatment) { +fun obfuscateStringEntity(key: String, entity: StringEntity, mockId: String): StringEntity { + val obfuscation = Stark.obfuscate(key, when (entity.androidTreatment) { true -> entity.value.androidTreatment() false -> entity.value.unescape() }.toByteArray(), @@ -116,9 +116,9 @@ fun obfuscateStringEntity(mainModule: String, key: String, entity: StringEntity, return StringEntity(entity.name, entity.attributes, obfuscation, entity.tag, entity.index, entity.androidTreatment) } -fun revealStringEntity(mainModule: String, key: String, entity: StringEntity, mockId: String = ""): StringEntity { +fun revealStringEntity(key: String, entity: StringEntity, mockId: String): StringEntity { val arr: ByteArray = entity.value.split(", ").map { it.toInt().toByte() }.toByteArray() - val original = String(Stark.reveal(mainModule, key, arr, mockId)) + val original = String(Stark.reveal(key, arr, mockId)) return StringEntity(entity.name, entity.attributes, original, entity.tag, entity.index, entity.androidTreatment) } diff --git a/src/main/kotlin/components/jni/libsignKey.dylib b/src/main/kotlin/components/jni/libsignKey.dylib index 04fbde8..dfe39e5 100755 Binary files a/src/main/kotlin/components/jni/libsignKey.dylib and b/src/main/kotlin/components/jni/libsignKey.dylib differ diff --git a/src/main/kotlin/task/SCPreview.kt b/src/main/kotlin/task/SCPreview.kt index eaaff91..537db0e 100644 --- a/src/main/kotlin/task/SCPreview.kt +++ b/src/main/kotlin/task/SCPreview.kt @@ -1,46 +1,94 @@ package task +import StringCare import StringCare.Companion.absoluteProjectPath -import StringCare.Companion.moduleMap +import com.google.gson.Gson +import components.applicationVariants import components.getContent import components.locateResourceFiles import components.parseXML import org.gradle.api.DefaultTask +import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction import java.io.File open class SCPreview : DefaultTask() { + + @Input + var module = String() + + @Input + var assetsFiles = String() + + @Input + var stringFiles = String() + + @Input + var srcFolders = String() + + @Input + var debug = false + + @Input + var skip = false + + @Input + var applicationId = "" + + @Input + var mockedFingerprint = "" + @TaskAction fun greet() { + val gson = Gson() println("== REPORT ======================================") - println("Modules (${moduleMap.size})") - - moduleMap.forEach { entry -> - val files = locateResourceFiles(absoluteProjectPath, entry.value) - println("Located files(${files.size}) for obfuscating") + val task = this; + project.applicationVariants()?.forEach { variant -> + println("\t== ${variant.name} ======================================") + val configuration = StringCare.Configuration(module).apply { + val lSrcFolders = gson.fromJson(task.srcFolders, MutableList::class.java) + if (task.srcFolders.isNotEmpty()) { + srcFolders.addAll(lSrcFolders as MutableList) + } + val lStringFiles = gson.fromJson(task.stringFiles, MutableList::class.java) + if (task.stringFiles.isNotEmpty()) { + stringFiles.addAll(lStringFiles as MutableList) + } + val lAssetsFiles = gson.fromJson(task.assetsFiles, MutableList::class.java) + if (task.assetsFiles.isNotEmpty()) { + assetsFiles.addAll(lAssetsFiles as MutableList) + } + if (task.mockedFingerprint.isNotEmpty()) { + mockedFingerprint = task.mockedFingerprint + } + applicationId = variant.applicationId + skip = task.skip + debug = task.debug + } + val files = locateResourceFiles(absoluteProjectPath, configuration) + println("\tLocated files(${files.size}) for obfuscating") + println("\tConfig (${gson.toJson(configuration)})") files.forEach { file -> - println("- ${file.file.name}") - println("\t${file.module}${File.separator}${file.sourceFolder}${File.separator}") + println("\t- ${file.file.name}") + println("\t\t${file.module}${File.separator}${file.sourceFolder}${File.separator}") val entities = parseXML(file.file) - println("path: ${file.file.absolutePath}") + println("\tpath: ${file.file.absolutePath}") println("") - println("============================") + println("\t============================") entities.forEach { entity -> entity.attributes.forEach { attribute -> - println("\"${attribute.name}\": \"${attribute.value}\"") + println("\t\"${attribute.name}\": \"${attribute.value}\"") } - println("\"value\": \"${entity.value}\"") - println("============================") + println("\t\"value\": \"${entity.value}\"") + println("\t============================") } println("") - println("=== content ================") - println(file.file.getContent()) - println("============================") + println("\t=== content ================") + println("" + file.file.getContent()) + println("\t============================") } } println("== END REPORT ==================================") - - } } diff --git a/src/main/kotlin/task/SCTestObfuscation.kt b/src/main/kotlin/task/SCTestObfuscation.kt index 88c20d7..4658b94 100644 --- a/src/main/kotlin/task/SCTestObfuscation.kt +++ b/src/main/kotlin/task/SCTestObfuscation.kt @@ -1,7 +1,8 @@ package task +import StringCare import StringCare.Companion.absoluteProjectPath -import StringCare.Companion.moduleMap +import com.google.gson.Gson import components.* import org.gradle.api.DefaultTask import org.gradle.api.tasks.Input @@ -10,48 +11,83 @@ import org.gradle.api.tasks.TaskAction open class SCTestObfuscation : DefaultTask() { @Input - var variant: String? = null + var module = String() @Input - var module: String? = null + var assetsFiles = String() @Input - var debug: Boolean? = null + var stringFiles = String() + + @Input + var srcFolders = String() + + @Input + var debug = false + + @Input + var skip = false + + @Input + var applicationId = "" + + @Input + var mockedFingerprint = "" @TaskAction fun greet() { println("== TEST OBFUSCATION ======================================") - println("Modules (${moduleMap.size})") + var key = "" + val gson = Gson() - moduleMap.forEach { entry -> - var key = "" + val task = this + project.applicationVariants()?.forEach { variant -> + println("\t== ${variant.name} ======================================") + val configuration = StringCare.Configuration(module).apply { + val lSrcFolders = gson.fromJson(task.srcFolders, MutableList::class.java) + if (task.srcFolders.isNotEmpty()) { + srcFolders.addAll(lSrcFolders as MutableList) + } + val lStringFiles = gson.fromJson(task.stringFiles, MutableList::class.java) + if (task.stringFiles.isNotEmpty()) { + stringFiles.addAll(lStringFiles as MutableList) + } + val lAssetsFiles = gson.fromJson(task.assetsFiles, MutableList::class.java) + if (task.assetsFiles.isNotEmpty()) { + assetsFiles.addAll(lAssetsFiles as MutableList) + } + if (task.mockedFingerprint.isNotEmpty()) { + mockedFingerprint = task.mockedFingerprint + } + applicationId = variant.applicationId + skip = task.skip + debug = task.debug + } signingReportTask().runCommand { _, result -> - key = result.extractFingerprint(entry.value.name, variant ?: defaultVariant, debug ?: defaultDebug) + key = result.extractFingerprint(module, variant.name, configuration) } - println("fingerprint: $key") - println("variant: ${variant ?: "debug"}") - val filesToObfuscate = backupResourceFiles(absoluteProjectPath, entry.value) + val filesToObfuscate = backupResourceFiles(absoluteProjectPath, configuration) filesToObfuscate.forEach { file -> val originalEntities = parseXML(file.file) - println("============================") - println("path: ${file.file.absolutePath}") + println("\t============================") + println("\tpath: ${file.file.absolutePath}") originalEntities.forEach { entity -> entity.attributes.forEach { attribute -> println("\"${attribute.name}\": \"${attribute.value}\"") } - println("\"value\": \"${entity.value}\"") - println("============================") + println("\"\tvalue\": \"${entity.value}\"") + println("\t============================") } println("") - println("=== content ================") + println("\t=== content ================") println(file.file.getContent()) - println("============================") - modifyXML(file.file, module!!, key, true) - println("=== content obfuscated ================") + println("\t============================") + modifyXML(file.file, key, configuration) + println("\t=== content obfuscated ================") println(file.file.getContent()) - println("============================") + println("\t============================") } - restoreResourceFiles(absoluteProjectPath, entry.value.name) + restoreResourceFiles(absoluteProjectPath, module) } println("== END OBFUSCATION ==================================") diff --git a/src/test/kotlin/AssetsTest.kt b/src/test/kotlin/AssetsTest.kt index 00bd3e4..2fdcc6b 100644 --- a/src/test/kotlin/AssetsTest.kt +++ b/src/test/kotlin/AssetsTest.kt @@ -9,6 +9,7 @@ class AssetsTest { private val configuration = defaultConfig().apply { debug = true + applicationId = "com.stringcare.sample" stringFiles.add("strings_extra.xml") srcFolders.add("src/other_source") } @@ -64,7 +65,7 @@ class AssetsTest { val temp = tempPath() signingReportTask(temp).runCommand { _, report -> println(report) - val key = report.extractFingerprint(variant = "prodDebug") + val key = report.extractFingerprint(variant = "prodDebug", configuration = configuration) println(key) assert(key.isNotEmpty()) val files = locateAssetsFiles( @@ -78,9 +79,9 @@ class AssetsTest { val original = it.file.getContent() println("original: \n $original") obfuscateFile( - "$temp${File.separator}$mainModuleTest", key, - it.file + it.file, + configuration.applicationId ) val obfuscated = it.file.getContent() println("obfuscated: \n $obfuscated") @@ -94,7 +95,7 @@ class AssetsTest { val temp = tempPath() signingReportTask(temp).runCommand { _, report -> println(report) - val key = report.extractFingerprint(variant = "prodDebug") + val key = report.extractFingerprint(variant = "prodDebug", configuration = configuration) println(key) assert(key.isNotEmpty()) val files = locateAssetsFiles( @@ -108,17 +109,17 @@ class AssetsTest { val original = it.file.getContent() println("original: \n $original") obfuscateFile( - "$temp${File.separator}$mainModuleTest", key, - it.file + it.file, + configuration.applicationId ) val obfuscated = it.file.getContent() println("obfuscated: \n $obfuscated") assert(original != obfuscated) revealFile( - "$temp${File.separator}$mainModuleTest", key, - it.file + it.file, + configuration.applicationId ) val reveal = it.file.getContent() println("reveal: \n $reveal") diff --git a/src/test/kotlin/SCTest.kt b/src/test/kotlin/SCTest.kt index 1223517..91c1f0e 100644 --- a/src/test/kotlin/SCTest.kt +++ b/src/test/kotlin/SCTest.kt @@ -7,9 +7,9 @@ import java.io.File class SCTest { - // private val logger by logger() - private val configuration = defaultConfig().apply { + debug = true + applicationId = "com.stringcare.sample" stringFiles.add("strings_extra.xml") srcFolders.add("src/other_source") } @@ -41,7 +41,7 @@ class SCTest { val temp = tempPath() signingReportTask(temp).runCommand { _, report -> println(report) - assert(report.extractFingerprint(variant = "prodDebug").split(":").size == 20) + assert(report.extractFingerprint(variant = "prodDebug", configuration = configuration).split(":").size == 20) } } @@ -97,7 +97,7 @@ class SCTest { val temp = tempPath() signingReportTask(temp).runCommand { _, report -> println(report) - val key = report.extractFingerprint(variant = "prodDebug") + val key = report.extractFingerprint(variant = "prodDebug", configuration = configuration) println(key) assert(key.isNotEmpty()) val files = locateResourceFiles("$temp${File.separator}$testProjectName", configuration) @@ -105,10 +105,9 @@ class SCTest { val entities = parseXML(file.file) entities.forEach { entity -> val obfuscated = obfuscateStringEntity( - "$temp${File.separator}$mainModuleTest", key, entity, - "" + configuration.applicationId ) assert(obfuscated.value != entity.value) } @@ -121,7 +120,7 @@ class SCTest { val temp = tempPath() signingReportTask(temp).runCommand { _, report -> println(report) - val key = report.extractFingerprint(variant = "prodDebug") + val key = report.extractFingerprint(variant = "prodDebug", configuration = configuration) println(key) assert(key.isNotEmpty()) val files = locateResourceFiles("$temp${File.separator}$testProjectName", configuration) @@ -129,16 +128,16 @@ class SCTest { val entities = parseXML(file.file) entities.forEach { entity -> val obfuscated = obfuscateStringEntity( - "$temp${File.separator}$mainModuleTest", key, - entity + entity, + configuration.applicationId ) assert(obfuscated.value != entity.value) val original = revealStringEntity( - "$temp${File.separator}$mainModuleTest", key, - obfuscated + obfuscated, + configuration.applicationId ) assert( @@ -162,7 +161,7 @@ class SCTest { files.forEach { file -> val entities = parseXML(file.file) assert(entities.isNotEmpty()) - modifyXML(file.file, "$temp${File.separator}$mainModuleTest", report.extractFingerprint(), true) + modifyXML(file.file, report.extractFingerprint(configuration = configuration), configuration) } val filesObfuscated = locateResourceFiles("$temp${File.separator}$testProjectName", configuration) filesObfuscated.forEach { file -> @@ -182,7 +181,7 @@ class SCTest { files.forEach { file -> val entities = parseXML(file.file) assert(entities.isNotEmpty()) - modifyXML(file.file, "$temp${File.separator}$mainModuleTest", report.extractFingerprint(), true) + modifyXML(file.file, report.extractFingerprint(configuration = configuration), configuration) } val filesObfuscated = locateResourceFiles("$temp${File.separator}$testProjectName", configuration) filesObfuscated.forEach { file -> @@ -228,9 +227,8 @@ class SCTest { assert(entities.isNotEmpty()) modifyXML( file.file, - "$temp${File.separator}$mainModuleTest", - report.extractFingerprint(), - true + report.extractFingerprint(configuration = configuration), + configuration ) } val filesObfuscated = locateResourceFiles(