Skip to content

Commit 15bbd60

Browse files
committed
Update
1 parent 25b6166 commit 15bbd60

File tree

3 files changed

+139
-181
lines changed

3 files changed

+139
-181
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
- Supports both `root` or `no-root` versions and is only for `arm64-bit`
66

7-
- 💾 Download: **[Release](https://github.com/Zenlua/Tool-Tree/releases/latest)** or **[Beta](https://github.com/Zenlua/Tool-Tree/releases/tag/beta)**
7+
- 📲 Download: **[Release](https://github.com/Zenlua/Tool-Tree/releases/latest)** or **[Beta](https://github.com/Zenlua/Tool-Tree/releases/tag/beta)**
88

99
### See details
1010

app/src/main/java/com/omarea/krscript/config/PathAnalysis.kt

Lines changed: 73 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -7,154 +7,133 @@ import com.omarea.common.shell.RootFile
77
import com.omarea.krscript.FileOwner
88
import java.io.File
99
import java.io.InputStream
10+
import java.net.URI
1011

1112
class PathAnalysis(private var context: Context, private var parentDir: String = "") {
12-
private val ASSETS_FILE = "file:///android_asset/"
13+
companion object {
14+
private const val ASSETS_FILE = "file:///android_asset/"
15+
}
1316

14-
// 解析路径时自动获得
1517
private var currentAbsPath: String = ""
1618

17-
fun getCurrentAbsPath(): String {
18-
return currentAbsPath
19-
}
19+
fun getCurrentAbsPath(): String = currentAbsPath
2020

2121
fun parsePath(filePath: String): InputStream? {
22-
try {
22+
return try {
2323
if (filePath.startsWith(ASSETS_FILE)) {
2424
currentAbsPath = filePath
25-
return context.assets.open(filePath.substring(ASSETS_FILE.length))
25+
context.assets.open(filePath.substring(ASSETS_FILE.length))
2626
} else {
27-
return getFileByPath(filePath)
27+
getFileByPath(filePath)
2828
}
2929
} catch (ex: Exception) {
30-
return null
30+
null
3131
}
3232
}
3333

34-
// TODO:处理 ../ 、 ./
34+
/**
35+
* Tối ưu hóa việc nối đường dẫn bằng cách sử dụng java.net.URI
36+
* để tự động xử lý các ký hiệu ../ và ./ một cách chuẩn xác.
37+
*/
3538
private fun pathConcat(parent: String, target: String): String {
36-
val isAssets = parent.startsWith(ASSETS_FILE)
37-
val parentDir = if (isAssets) parent.substring(ASSETS_FILE.length) else parent
38-
val parentSlices = ArrayList(parentDir.split("/"))
39-
if (target.startsWith("../") && parentSlices.isNotEmpty()) {
40-
val targetSlices = ArrayList(target.split("/"))
41-
while (true) {
42-
val step = targetSlices.firstOrNull()
43-
if (step != null && step == ".." && parentSlices.isNotEmpty()) {
44-
parentSlices.removeAt(parentSlices.size - 1)
45-
targetSlices.removeAt(0)
46-
} else {
47-
break
48-
}
49-
}
50-
return pathConcat((if (isAssets) ASSETS_FILE else "" )+ parentSlices.joinToString("/"), targetSlices.joinToString("/"))
39+
return try {
40+
val isAssets = parent.startsWith(ASSETS_FILE)
41+
val base = if (isAssets) parent else "file://$parent"
42+
43+
// Sử dụng URI để normalize đường dẫn (xử lý ../ và ./)
44+
val uri = URI(base).resolve(target).normalize()
45+
46+
val result = uri.toString()
47+
if (isAssets) result else result.removePrefix("file:")
48+
} catch (e: Exception) {
49+
// Fallback nếu URI fail
50+
if (parent.endsWith("/")) parent + target else "$parent/$target"
5151
}
52-
53-
return (if (isAssets) ASSETS_FILE else "" )+ ( when {
54-
!(parentDir.isEmpty() || parentDir.endsWith("/")) -> "$parentDir/"
55-
else -> parentDir
56-
} + (if (target.startsWith("./")) target.substring(2) else target))
5752
}
5853

54+
/**
55+
* Cải tiến việc mở file bằng Root: sử dụng tên file động để tránh xung đột (Collision)
56+
*/
5957
private fun useRootOpenFile(filePath: String): InputStream? {
6058
if (RootFile.fileExists(filePath)) {
61-
val dir = File(FileWrite.getPrivateFilePath(context, "icons"))
62-
if (!dir.exists()) {
63-
dir.mkdirs()
64-
}
59+
val cacheDir = File(FileWrite.getPrivateFilePath(context, "icons"))
60+
if (!cacheDir.exists()) cacheDir.mkdirs()
6561

66-
val cachePath = FileWrite.getPrivateFilePath(context, "icons/outside_file.cache")
62+
// Tạo tên file cache dựa trên hash đường dẫn để tránh ghi đè khi mở nhiều file cùng lúc
63+
val fileName = "cache_${filePath.hashCode()}"
64+
val cachePath = File(cacheDir, fileName).absolutePath
6765
val fileOwner = FileOwner(context).fileOwner
68-
KeepShellPublic.doCmdSync(
69-
"cp -f \"$filePath\" \"$cachePath\"\n" +
70-
"chmod 777 \"$cachePath\"\n" +
71-
"chown $fileOwner:$fileOwner \"$cachePath\"\n")
72-
File(cachePath).run {
73-
if (exists() && canRead()) {
74-
return inputStream()
66+
67+
val command = """
68+
cp -f "$filePath" "$cachePath"
69+
chmod 777 "$cachePath"
70+
chown $fileOwner:$fileOwner "$cachePath"
71+
""".trimIndent()
72+
73+
KeepShellPublic.doCmdSync(command)
74+
75+
File(cachePath).let {
76+
if (it.exists() && it.canRead()) {
77+
return it.inputStream()
7578
}
7679
}
7780
}
7881
return null
7982
}
8083

81-
// 在assets里查找文件
8284
private fun findAssetsResource(filePath: String): InputStream? {
83-
// 解析成绝对路径
8485
val relativePath = pathConcat(parentDir, filePath)
85-
try {
86+
return try {
87+
val simplePath = relativePath.substring(ASSETS_FILE.length)
88+
context.assets.open(simplePath).also { currentAbsPath = relativePath }
89+
} catch (ex: Exception) {
8690
try {
87-
// 首先在assets里查找相对路径
88-
val simplePath = relativePath.substring(ASSETS_FILE.length)
89-
context.assets.open(simplePath).run {
90-
currentAbsPath = relativePath
91-
return this
92-
}
93-
} catch (ex: java.lang.Exception) {
94-
// 然后再尝试再assets里查找绝对路径
95-
context.assets.open(filePath).run {
96-
currentAbsPath = ASSETS_FILE + filePath
97-
return this
98-
}
91+
context.assets.open(filePath).also { currentAbsPath = ASSETS_FILE + filePath }
92+
} catch (e: Exception) {
93+
null
9994
}
100-
} catch (ex: java.lang.Exception) {
101-
return null
10295
}
10396
}
10497

105-
// 在磁盘上查找文件
10698
private fun findDiskResource(filePath: String): InputStream? {
99+
// 1. Tìm tương đối so với parentDir
107100
if (parentDir.isNotEmpty()) {
108-
// 解析成绝对路径
109101
val relativePath = pathConcat(parentDir, filePath)
110-
// 尝试使用普通权限读取文件
111-
File(relativePath).run {
112-
if (exists() && canRead()) {
113-
currentAbsPath = absolutePath
114-
return inputStream()
115-
}
116-
}
117-
useRootOpenFile(relativePath)?.run {
118-
return this
102+
val file = File(relativePath)
103+
if (file.exists() && file.canRead()) {
104+
currentAbsPath = file.absolutePath
105+
return file.inputStream()
119106
}
107+
useRootOpenFile(relativePath)?.let { return it }
120108
}
121109

122-
// 路径相对于当前配置文件没找到文件的话,继续查找相对于数据文件根目录的文件
123-
val privatePath = File( pathConcat(FileWrite.getPrivateFileDir(context), filePath)).absolutePath
124-
File(privatePath).run {
125-
if (exists() && canRead()) {
126-
currentAbsPath = absolutePath
127-
return inputStream()
128-
}
129-
}
130-
useRootOpenFile(privatePath)?.run {
131-
return this
110+
// 2. Tìm trong thư mục riêng của ứng dụng (Private Data)
111+
val privateDir = FileWrite.getPrivateFileDir(context)
112+
val privatePath = pathConcat(privateDir, filePath)
113+
val pFile = File(privatePath)
114+
if (pFile.exists() && pFile.canRead()) {
115+
currentAbsPath = pFile.absolutePath
116+
return pFile.inputStream()
132117
}
133-
134-
return null
118+
119+
return useRootOpenFile(privatePath)
135120
}
136121

137122
private fun getFileByPath(filePath: String): InputStream? {
138-
try {
123+
return try {
139124
if (filePath.startsWith("/")) {
140125
currentAbsPath = filePath
141-
val javaFileInfo = File(filePath)
142-
return if (javaFileInfo.exists() && javaFileInfo.canRead()) {
143-
javaFileInfo.inputStream()
144-
} else {
145-
useRootOpenFile(filePath)
146-
}
126+
val file = File(filePath)
127+
if (file.exists() && file.canRead()) file.inputStream() else useRootOpenFile(filePath)
147128
} else {
148-
// 如果当前配置文件来源于 assets,则查找依赖资源时也只去assets查找
149-
return if (parentDir.isNotEmpty() && parentDir.startsWith(ASSETS_FILE)) {
129+
if (parentDir.startsWith(ASSETS_FILE)) {
150130
findAssetsResource(filePath)
151131
} else {
152132
findDiskResource(filePath)
153133
}
154134
}
155-
} catch (ex: java.lang.Exception) {
156-
ex.printStackTrace()
135+
} catch (ex: Exception) {
136+
null
157137
}
158-
return null
159138
}
160139
}

0 commit comments

Comments
 (0)