Skip to content

Commit 5450391

Browse files
committed
testing xml modification
1 parent 34a42e2 commit 5450391

File tree

4 files changed

+110
-26
lines changed

4 files changed

+110
-26
lines changed

src/main/kotlin/components/Extensions.kt

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ import models.Extension
66
import models.ResourceFile
77
import org.gradle.api.NamedDomainObjectContainer
88
import org.gradle.api.Project
9-
import java.io.File
9+
import org.w3c.dom.Document
10+
import org.xml.sax.InputSource
11+
import java.io.*
12+
import javax.xml.parsers.DocumentBuilderFactory
13+
import javax.xml.transform.TransformerFactory
14+
import javax.xml.transform.dom.DOMSource
15+
import javax.xml.transform.stream.StreamResult
1016

1117
fun String.runCommand(runner: (command: String, result: String) -> Unit = { _, _ -> }): String {
1218
val result = execute(this)
@@ -22,7 +28,8 @@ fun File.validForConfiguration(configuration: Configuration): Boolean {
2228
var valid = false
2329
configuration.srcFolders.forEach { folder ->
2430
if (this.absolutePath.contains("/$folder/".replace("//", "/"))
25-
&& !this.absolutePath.contains("/$resourceBackup/")) {
31+
&& !this.absolutePath.contains("/$resourceBackup/")
32+
) {
2633
valid = true
2734
}
2835
}
@@ -82,13 +89,13 @@ fun ResourceFile.backup(projectPath: String): File {
8289
.replace("${File.separator}${File.separator}", File.separator)
8390

8491
val backupFile = File(cleanPath)
85-
this.file.copyTo(backupFile)
92+
this.file.copyTo(backupFile, true)
8693
return backupFile
8794
}
8895

8996
fun File.restore(projectPath: String): File {
9097
val cleanPath = "$projectPath${File.separator}${this.absolutePath.split(resourceBackup)[1]}"
91-
.replace("${File.separator}${File.separator}", File.separator)
98+
.replace("${File.separator}${File.separator}", File.separator)
9299

93100
val restore = File(cleanPath)
94101
this.copyTo(restore, true)
@@ -107,3 +114,34 @@ fun ByteArray.toReadableString(): String {
107114
return builder.toString()
108115
}
109116

117+
fun File.getXML(): Document {
118+
val inputStream = FileInputStream(this)
119+
val reader = InputStreamReader(inputStream, "UTF-8")
120+
val inputSource = InputSource(reader)
121+
inputSource.encoding = "UTF-8"
122+
123+
val builderFactory = DocumentBuilderFactory.newInstance()
124+
val docBuilder = builderFactory.newDocumentBuilder()
125+
return docBuilder.parse(inputSource)
126+
}
127+
128+
fun File.updateXML(document: Document) {
129+
val output = StringWriter()
130+
val transformer = TransformerFactory.newInstance().newTransformer()
131+
transformer.transform(DOMSource(document), StreamResult(output))
132+
val xml = output.toString()
133+
FileWriter(this.absolutePath).use { it.write(xml) }
134+
}
135+
136+
fun File.removeHiddenAttributes() {
137+
val content = this.getContent()
138+
.replace("hidden=\"true\"", "")
139+
.replace("hidden=\"false\"", "")
140+
.replace("hidden", "")
141+
FileWriter(this.absolutePath).use { it.write(content) }
142+
updateXML(this.getXML())
143+
}
144+
145+
146+
fun File.getContent() = this.inputStream().readBytes().toString(Charsets.UTF_8)
147+

src/main/kotlin/components/XParser.kt

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import models.ResourceFile
55
import models.SAttribute
66
import models.StringEntity
77
import java.io.File
8-
import javax.xml.parsers.DocumentBuilderFactory
98

109
fun locateFiles(projectPath: String, configuration: Configuration): List<ResourceFile> = File(projectPath).walkTopDown()
1110
.filterIndexed { _, file ->
@@ -33,41 +32,66 @@ fun restoreFiles(projectPath: String): List<File> {
3332

3433
fun parseXML(file: File, module: String, debug: Boolean): List<StringEntity> {
3534
if (debug) {
36-
val content = file.inputStream().readBytes().toString(Charsets.UTF_8)
37-
PrintUtils.print(module, content, true)
35+
PrintUtils.print(module, file.getContent(), true)
3836
}
3937
val entities = mutableListOf<StringEntity>()
40-
val builderFactory = DocumentBuilderFactory.newInstance()
41-
val docBuilder = builderFactory.newDocumentBuilder()
42-
val doc = docBuilder.parse(file.inputStream())
43-
// reading player tags
38+
39+
val doc = file.getXML()
4440
val nList = doc.getElementsByTagName("string")
4541
for (i in 0 until nList.length) {
4642
val node = nList.item(i)
4743
var name = ""
4844
val attributes = mutableListOf<SAttribute>()
45+
var obfuscate = false
4946
for (a in 0 until node.attributes.length) {
5047
val attribute = node.attributes.item(a)
5148
for (n in 0 until attribute.childNodes.length) {
5249
val attr = attribute.childNodes.item(n)
5350
// can set value
5451
if (attribute.nodeName == "name") name = attr.nodeValue
52+
if (attribute.nodeName == "hidden" && attr.nodeValue != "false") {
53+
obfuscate = true
54+
}
5555
attributes.add(SAttribute(attribute.nodeName, attr.nodeValue))
5656
}
5757
}
58-
entities.add(StringEntity(name, attributes, node.firstChild.nodeValue))
58+
if (obfuscate) {
59+
entities.add(StringEntity(name, attributes, node.firstChild.nodeValue, "string", i))
60+
}
5961
}
6062
return entities
6163
}
6264

65+
fun modifyXML(file: File, module: String, key: String, debug: Boolean) {
66+
val stringEntities = parseXML(file, module, debug)
67+
if (debug) {
68+
PrintUtils.print(module, file.getContent(), true)
69+
}
70+
71+
val doc = file.getXML()
72+
val nList = doc.getElementsByTagName("string")
73+
for (i in 0 until nList.length) {
74+
val node = nList.item(i)
75+
val entity = stringEntities.find {
76+
it.tag == "string" && it.index == i
77+
}
78+
entity?.let {
79+
node.firstChild.nodeValue = obfuscate(module, key, it).value
80+
}
81+
}
82+
83+
file.updateXML(doc)
84+
file.removeHiddenAttributes()
85+
}
86+
6387
fun obfuscate(mainModule: String, key: String, entity: StringEntity): StringEntity {
6488
val obfuscation = Stark.obfuscate(mainModule, key, entity.value.toByteArray()).toReadableString()
65-
return StringEntity(entity.name, entity.attributes, obfuscation)
89+
return StringEntity(entity.name, entity.attributes, obfuscation, entity.tag, entity.index)
6690
}
6791

6892
fun reveal(mainModule: String, key: String, entity: StringEntity): StringEntity {
6993
val arr: ByteArray = entity.value.split(", ").map { it.toInt().toByte() }.toByteArray()
7094
val original = String(Stark.reveal(mainModule, key, arr))
71-
return StringEntity(entity.name, entity.attributes, original)
95+
return StringEntity(entity.name, entity.attributes, original, entity.tag, entity.index)
7296
}
7397

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package models
22

3-
class StringEntity(var name: String, var attributes: List<SAttribute>, var value: String) {
3+
class StringEntity(
4+
var name: String,
5+
var attributes: List<SAttribute>,
6+
var value: String,
7+
val tag: String,
8+
val index: Int
9+
)
410

5-
}
611
data class SAttribute(val name: String, val value: String)

src/test/kotlin/SCTest.kt

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import components.*
2+
import models.StringEntity
23
import org.junit.Before
34
import org.junit.Test
45
import java.io.File
@@ -9,7 +10,8 @@ class SCTest {
910
private val logger by logger()
1011

1112
private val projectName = "KotlinSample"
12-
private val mainModuleTest = "app"
13+
private val mainModule = "app"
14+
private val mainModuleTest = "$projectName${File.separator}$mainModule"
1315

1416
private val librarySetupTask = """
1517
cp src/main/kotlin/components/jni/$osxLib out/production/classes/$osxLib
@@ -80,9 +82,9 @@ class SCTest {
8082
@Test
8183
fun `7 - xml parsing`() {
8284
prepareTask.runCommand { _, _ ->
83-
val files = backupFiles(projectName, defaultConfig())
85+
val files = locateFiles(projectName, defaultConfig())
8486
files.forEach {
85-
assert(parseXML(it, mainModuleTest, true).isNotEmpty())
87+
assert(parseXML(it.file, mainModuleTest, true).isNotEmpty())
8688
}
8789
}
8890
}
@@ -91,12 +93,12 @@ class SCTest {
9193
@Test
9294
fun `8 - obfuscate string values`() {
9395
signingReportTask.runCommand { _, report ->
94-
val files = backupFiles(projectName, defaultConfig())
96+
val files = locateFiles(projectName, defaultConfig())
9597
files.forEach { file ->
96-
val entities = parseXML(file, mainModuleTest, true)
98+
val entities = parseXML(file.file, mainModuleTest, true)
9799
entities.forEach { entity ->
98100
val obfuscated = obfuscate(
99-
"$projectName${File.separator}$mainModuleTest",
101+
mainModuleTest,
100102
report.extractFingerprint(),
101103
entity
102104
)
@@ -109,19 +111,19 @@ class SCTest {
109111
@Test
110112
fun `9 - obfuscate and reveal string values`() {
111113
signingReportTask.runCommand { _, report ->
112-
val files = backupFiles(projectName, defaultConfig())
114+
val files = locateFiles(projectName, defaultConfig())
113115
files.forEach { file ->
114-
val entities = parseXML(file, mainModuleTest, true)
116+
val entities = parseXML(file.file, mainModuleTest, true)
115117
entities.forEach { entity ->
116118
val obfuscated = obfuscate(
117-
"$projectName${File.separator}$mainModuleTest",
119+
mainModuleTest,
118120
report.extractFingerprint(),
119121
entity
120122
)
121123
assert(obfuscated.value != entity.value)
122124

123125
val original = reveal(
124-
"$projectName${File.separator}$mainModuleTest",
126+
mainModuleTest,
125127
report.extractFingerprint(),
126128
obfuscated
127129
)
@@ -133,4 +135,19 @@ class SCTest {
133135
}
134136
}
135137

138+
@Test
139+
fun `10 - obfuscate xml`() {
140+
signingReportTask.runCommand { _, report ->
141+
val files = locateFiles(projectName, defaultConfig())
142+
files.forEach { file ->
143+
modifyXML(file.file, mainModuleTest, report.extractFingerprint(), true)
144+
}
145+
val filesObfuscated = locateFiles(projectName, defaultConfig())
146+
filesObfuscated.forEach { file ->
147+
val entities = parseXML(file.file, mainModuleTest, true)
148+
assert(entities.isEmpty())
149+
}
150+
}
151+
}
152+
136153
}

0 commit comments

Comments
 (0)