优化
This commit is contained in:
@@ -243,12 +243,6 @@ dependencies {
|
|||||||
|
|
||||||
//apache
|
//apache
|
||||||
implementation('org.apache.commons:commons-text:1.10.0')
|
implementation('org.apache.commons:commons-text:1.10.0')
|
||||||
//noinspection GradleDependency,1.23.0对安卓支持不好
|
|
||||||
implementation 'org.apache.commons:commons-compress:1.22'
|
|
||||||
implementation 'org.tukaani:xz:1.9'
|
|
||||||
|
|
||||||
//RAR
|
|
||||||
implementation 'com.github.junrar:junrar:7.5.5'
|
|
||||||
|
|
||||||
//MarkDown
|
//MarkDown
|
||||||
def markwonVersion = "4.6.2"
|
def markwonVersion = "4.6.2"
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import android.net.Uri
|
|||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import cn.hutool.core.codec.Base64
|
import cn.hutool.core.codec.Base64
|
||||||
import cn.hutool.core.util.HexUtil
|
import cn.hutool.core.util.HexUtil
|
||||||
import com.github.junrar.Archive
|
|
||||||
import com.github.junrar.rarfile.FileHeader
|
|
||||||
import com.github.liuyueyi.quick.transfer.ChineseUtils
|
import com.github.liuyueyi.quick.transfer.ChineseUtils
|
||||||
import io.legado.app.constant.AppConst
|
import io.legado.app.constant.AppConst
|
||||||
import io.legado.app.constant.AppConst.dateFormat
|
import io.legado.app.constant.AppConst.dateFormat
|
||||||
@@ -23,13 +21,11 @@ import io.legado.app.model.Debug
|
|||||||
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
||||||
import io.legado.app.model.analyzeRule.QueryTTF
|
import io.legado.app.model.analyzeRule.QueryTTF
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
|
import io.legado.app.utils.compress.LibArchiveUtils
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import okio.use
|
import okio.use
|
||||||
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry
|
|
||||||
import org.apache.commons.compress.archivers.sevenz.SevenZFile
|
|
||||||
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel
|
|
||||||
import org.jsoup.Connection
|
import org.jsoup.Connection
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
@@ -699,19 +695,10 @@ interface JsExtensions : JsEncodeUtils {
|
|||||||
HexUtil.decodeHex(url)
|
HexUtil.decodeHex(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
val bos = ByteArrayOutputStream()
|
return ByteArrayInputStream(bytes).use {
|
||||||
Archive(ByteArrayInputStream(bytes)).use { archive ->
|
LibArchiveUtils.getByteArrayContent(it, path)
|
||||||
var entry: FileHeader
|
|
||||||
while (archive.nextFileHeader().also { entry = it } != null) {
|
|
||||||
if (entry.fileName.equals(path)) {
|
|
||||||
archive.getInputStream(entry).use { it.copyTo(bos) }
|
|
||||||
return bos.toByteArray()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
log("getRarContent 未发现内容")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取网络7zip文件里面的数据
|
* 获取网络7zip文件里面的数据
|
||||||
@@ -726,19 +713,10 @@ interface JsExtensions : JsEncodeUtils {
|
|||||||
HexUtil.decodeHex(url)
|
HexUtil.decodeHex(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
val bos = ByteArrayOutputStream()
|
return ByteArrayInputStream(bytes).use {
|
||||||
SevenZFile(SeekableInMemoryByteChannel(bytes)).use { sevenZFile ->
|
LibArchiveUtils.getByteArrayContent(it, path)
|
||||||
var entry: SevenZArchiveEntry
|
|
||||||
while (sevenZFile.nextEntry.also { entry = it } != null) {
|
|
||||||
if (entry.name.equals(path)) {
|
|
||||||
sevenZFile.getInputStream(entry).use { it.copyTo(bos) }
|
|
||||||
return bos.toByteArray()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
log("get7zContent 未发现内容")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//******************文件操作************************//
|
//******************文件操作************************//
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import io.legado.app.lib.icu4j.CharsetDetector
|
|||||||
import me.zhanghai.android.libarchive.Archive
|
import me.zhanghai.android.libarchive.Archive
|
||||||
import me.zhanghai.android.libarchive.ArchiveEntry
|
import me.zhanghai.android.libarchive.ArchiveEntry
|
||||||
import me.zhanghai.android.libarchive.ArchiveException
|
import me.zhanghai.android.libarchive.ArchiveException
|
||||||
|
import splitties.init.appCtx
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileDescriptor
|
import java.io.FileDescriptor
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@@ -23,6 +24,7 @@ import java.nio.charset.StandardCharsets
|
|||||||
|
|
||||||
object LibArchiveUtils {
|
object LibArchiveUtils {
|
||||||
|
|
||||||
|
val cachePath = File(appCtx.cacheDir, "archive")
|
||||||
|
|
||||||
@Throws(ArchiveException::class)
|
@Throws(ArchiveException::class)
|
||||||
fun openArchive(
|
fun openArchive(
|
||||||
@@ -60,15 +62,12 @@ object LibArchiveUtils {
|
|||||||
Archive.readOpen1(archive)
|
Archive.readOpen1(archive)
|
||||||
successful = true
|
successful = true
|
||||||
return archive
|
return archive
|
||||||
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (!successful) {
|
if (!successful) {
|
||||||
Archive.free(archive)
|
Archive.free(archive)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -135,7 +134,6 @@ object LibArchiveUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -216,7 +214,7 @@ object LibArchiveUtils {
|
|||||||
fun unArchive(
|
fun unArchive(
|
||||||
pfd: ParcelFileDescriptor,
|
pfd: ParcelFileDescriptor,
|
||||||
destDir: File,
|
destDir: File,
|
||||||
filter: ((String) -> Boolean)?
|
filter: ((String) -> Boolean)? = null
|
||||||
): List<File> {
|
): List<File> {
|
||||||
return unArchive(openArchive(pfd), destDir, filter)
|
return unArchive(openArchive(pfd), destDir, filter)
|
||||||
}
|
}
|
||||||
@@ -288,6 +286,46 @@ object LibArchiveUtils {
|
|||||||
return getFilesName(openArchive(pfd), filter)
|
return getFilesName(openArchive(pfd), filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getByteArrayContent(inputStream: InputStream, path: String): ByteArray? {
|
||||||
|
val archive = openArchive(inputStream)
|
||||||
|
try {
|
||||||
|
var entry = Archive.readNextHeader(archive)
|
||||||
|
while (entry != 0L) {
|
||||||
|
val entryName =
|
||||||
|
getEntryString(ArchiveEntry.pathnameUtf8(entry), ArchiveEntry.pathname(entry))
|
||||||
|
?: continue
|
||||||
|
|
||||||
|
val entryStat = ArchiveEntry.stat(entry)
|
||||||
|
|
||||||
|
//判断是否是文件夹
|
||||||
|
if (S_ISDIR(entryStat.stMode)) {
|
||||||
|
entry = Archive.readNextHeader(archive)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entryName == path) {
|
||||||
|
cachePath.mkdirs()
|
||||||
|
val entryFile = File(cachePath, entry.toString())
|
||||||
|
entryFile.delete()
|
||||||
|
entryFile.createNewFile()
|
||||||
|
entryFile.setReadable(true)
|
||||||
|
entryFile.setExecutable(true)
|
||||||
|
ParcelFileDescriptor.open(entryFile, ParcelFileDescriptor.MODE_WRITE_ONLY).use {
|
||||||
|
Archive.readDataIntoFd(archive, it.fd)
|
||||||
|
}
|
||||||
|
val bytes = entryFile.readBytes()
|
||||||
|
entryFile.delete()
|
||||||
|
return bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = Archive.readNextHeader(archive)
|
||||||
|
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Archive.free(archive)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(SecurityException::class)
|
@Throws(SecurityException::class)
|
||||||
private fun getFilesName(
|
private fun getFilesName(
|
||||||
@@ -320,13 +358,11 @@ object LibArchiveUtils {
|
|||||||
|
|
||||||
entry = Archive.readNextHeader(archive)
|
entry = Archive.readNextHeader(archive)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Archive.free(archive)
|
Archive.free(archive)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return fileNames
|
return fileNames
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,5 +380,4 @@ object LibArchiveUtils {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
package io.legado.app.utils.compress
|
|
||||||
|
|
||||||
import com.github.junrar.Archive
|
|
||||||
import com.github.junrar.rarfile.FileHeader
|
|
||||||
import java.io.ByteArrayInputStream
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.InputStream
|
|
||||||
|
|
||||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
|
||||||
object RarUtils {
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun unRarToPath(inputStream: InputStream, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return unRarToPath(inputStream, File(path), filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun unRarToPath(byteArray: ByteArray, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return unRarToPath(byteArray, File(path), filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun unRarToPath(zipPath: String, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return unRarToPath(zipPath, File(path), filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun unRarToPath(file: File, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return unRarToPath(file, File(path), filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun unRarToPath(inputStream: InputStream, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return Archive(inputStream).use {
|
|
||||||
unRarToPath(it, destDir, filter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun unRarToPath(byteArray: ByteArray, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return Archive(ByteArrayInputStream(byteArray)).use {
|
|
||||||
unRarToPath(it, destDir, filter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun unRarToPath(filePath: String, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return Archive(File(filePath)).use {
|
|
||||||
unRarToPath(it, destDir, filter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun unRarToPath(file: File, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return Archive(file).use {
|
|
||||||
unRarToPath(it, destDir, filter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
private fun unRarToPath(
|
|
||||||
archive: Archive,
|
|
||||||
destDir: File?,
|
|
||||||
filter: ((String) -> Boolean)? = null
|
|
||||||
): List<File> {
|
|
||||||
destDir ?: throw NullPointerException("解决路径不能为空")
|
|
||||||
val files = arrayListOf<File>()
|
|
||||||
var entry: FileHeader?
|
|
||||||
while (archive.nextFileHeader().also { entry = it } != null) {
|
|
||||||
val entryName = entry!!.fileName
|
|
||||||
val entryFile = File(destDir, entryName)
|
|
||||||
if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath)) {
|
|
||||||
throw SecurityException("压缩文件只能解压到指定路径")
|
|
||||||
}
|
|
||||||
if (entry!!.isDirectory) {
|
|
||||||
if (!entryFile.exists()) {
|
|
||||||
entryFile.mkdirs()
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (entryFile.parentFile?.exists() != true) {
|
|
||||||
entryFile.parentFile?.mkdirs()
|
|
||||||
}
|
|
||||||
if (filter != null && !filter.invoke(entryName)) continue
|
|
||||||
if (!entryFile.exists()) {
|
|
||||||
entryFile.createNewFile()
|
|
||||||
entryFile.setReadable(true)
|
|
||||||
entryFile.setExecutable(true)
|
|
||||||
}
|
|
||||||
FileOutputStream(entryFile).use {
|
|
||||||
archive.getInputStream(entry).copyTo(it)
|
|
||||||
files.add(entryFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return files
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 遍历目录获取所有文件名 */
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun getFilesName(
|
|
||||||
inputStream: InputStream,
|
|
||||||
filter: ((String) -> Boolean)? = null
|
|
||||||
): List<String> {
|
|
||||||
return Archive(inputStream).use {
|
|
||||||
getFilesName(it, filter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
private fun getFilesName(
|
|
||||||
archive: Archive,
|
|
||||||
filter: ((String) -> Boolean)? = null
|
|
||||||
): List<String> {
|
|
||||||
val fileNames = mutableListOf<String>()
|
|
||||||
var entry: FileHeader?
|
|
||||||
while (archive.nextFileHeader().also { entry = it } != null) {
|
|
||||||
if (entry!!.isDirectory) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val fileName = entry!!.fileName
|
|
||||||
if (filter != null && filter.invoke(fileName))
|
|
||||||
fileNames.add(fileName)
|
|
||||||
}
|
|
||||||
return fileNames
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
package io.legado.app.utils.compress
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.os.ParcelFileDescriptor
|
|
||||||
import io.legado.app.utils.ParcelFileDescriptorChannel
|
|
||||||
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry
|
|
||||||
import org.apache.commons.compress.archivers.sevenz.SevenZFile
|
|
||||||
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.nio.channels.FileChannel
|
|
||||||
|
|
||||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
|
||||||
object SevenZipUtils {
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun un7zToPath(inputStream: InputStream, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return un7zToPath(inputStream, File(path), filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun un7zToPath(byteArray: ByteArray, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return un7zToPath(byteArray, File(path),filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun un7zToPath(pfd: ParcelFileDescriptor, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return un7zToPath(pfd, File(path), filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun un7zToPath(fileChannel: FileChannel, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return un7zToPath(fileChannel, File(path), filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun un7zToPath(inputStream: InputStream, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())), destDir, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun un7zToPath(byteArray: ByteArray, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(byteArray)), destDir, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun un7zToPath(pfd: ParcelFileDescriptor, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return un7zToPath(SevenZFile(ParcelFileDescriptorChannel(pfd)), destDir, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun un7zToPath(fileChannel: FileChannel, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return un7zToPath(SevenZFile(fileChannel), destDir, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun un7zToPath(file: File, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return un7zToPath(SevenZFile(file), destDir, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun un7zToPath(filePath: String, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
return un7zToPath(SevenZFile(File(filePath)), destDir, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
private fun un7zToPath(sevenZFile: SevenZFile, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
|
||||||
destDir ?: throw NullPointerException("解决路径不能为空")
|
|
||||||
val files = arrayListOf<File>()
|
|
||||||
var entry: SevenZArchiveEntry?
|
|
||||||
while (sevenZFile.nextEntry.also { entry = it } != null) {
|
|
||||||
val entryName = entry!!.name
|
|
||||||
val entryFile = File(destDir, entryName)
|
|
||||||
if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath)) {
|
|
||||||
throw SecurityException("压缩文件只能解压到指定路径")
|
|
||||||
}
|
|
||||||
if (entry!!.isDirectory) {
|
|
||||||
if (!entryFile.exists()) {
|
|
||||||
entryFile.mkdirs()
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (entryFile.parentFile?.exists() != true) {
|
|
||||||
entryFile.parentFile?.mkdirs()
|
|
||||||
}
|
|
||||||
if (filter != null && !filter.invoke(entryName)) continue
|
|
||||||
if (!entryFile.exists()) {
|
|
||||||
entryFile.createNewFile()
|
|
||||||
entryFile.setReadable(true)
|
|
||||||
entryFile.setExecutable(true)
|
|
||||||
}
|
|
||||||
FileOutputStream(entryFile).use {
|
|
||||||
sevenZFile.getInputStream(entry).copyTo(it)
|
|
||||||
files.add(entryFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return files
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 遍历目录获取所有文件名 */
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
fun getFilesName(
|
|
||||||
inputStream: InputStream,
|
|
||||||
filter: ((String) -> Boolean)? = null
|
|
||||||
): List<String> {
|
|
||||||
return getFilesName(
|
|
||||||
SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())),
|
|
||||||
filter
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
|
||||||
private fun getFilesName(
|
|
||||||
sevenZFile: SevenZFile,
|
|
||||||
filter: ((String) -> Boolean)? = null
|
|
||||||
): List<String> {
|
|
||||||
val fileNames = mutableListOf<String>()
|
|
||||||
var entry: SevenZArchiveEntry?
|
|
||||||
while (sevenZFile.nextEntry.also { entry = it } != null) {
|
|
||||||
if (entry!!.isDirectory) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val fileName = entry!!.name
|
|
||||||
if (filter != null && filter.invoke(fileName))
|
|
||||||
fileNames.add(fileName)
|
|
||||||
}
|
|
||||||
return fileNames
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,10 @@
|
|||||||
package io.legado.app.utils.compress
|
package io.legado.app.utils.compress
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Build
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import io.legado.app.utils.DebugLog
|
import io.legado.app.utils.DebugLog
|
||||||
import io.legado.app.utils.printOnDebug
|
import io.legado.app.utils.printOnDebug
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.apache.commons.compress.archivers.ArchiveEntry
|
|
||||||
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream
|
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.util.zip.*
|
import java.util.zip.*
|
||||||
|
|
||||||
@@ -215,15 +211,9 @@ object ZipUtils {
|
|||||||
path: String,
|
path: String,
|
||||||
filter: ((String) -> Boolean)? = null
|
filter: ((String) -> Boolean)? = null
|
||||||
): List<File> {
|
): List<File> {
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
return ZipInputStream(inputStream).use {
|
||||||
ZipArchiveInputStream(inputStream).use {
|
|
||||||
unZipToPath(it, File(path), filter)
|
unZipToPath(it, File(path), filter)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
ZipInputStream(inputStream).use {
|
|
||||||
unZipToPath(it, File(path), filter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(SecurityException::class)
|
@Throws(SecurityException::class)
|
||||||
@@ -232,55 +222,10 @@ object ZipUtils {
|
|||||||
dir: File,
|
dir: File,
|
||||||
filter: ((String) -> Boolean)? = null
|
filter: ((String) -> Boolean)? = null
|
||||||
): List<File> {
|
): List<File> {
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
return ZipInputStream(inputStream).use {
|
||||||
ZipArchiveInputStream(inputStream).use {
|
|
||||||
unZipToPath(it, dir, filter)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ZipInputStream(inputStream).use {
|
|
||||||
unZipToPath(it, dir, filter)
|
unZipToPath(it, dir, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.N)
|
|
||||||
@Throws(SecurityException::class)
|
|
||||||
private fun unZipToPath(
|
|
||||||
zipInputStream: ZipArchiveInputStream,
|
|
||||||
dir: File,
|
|
||||||
filter: ((String) -> Boolean)? = null
|
|
||||||
): List<File> {
|
|
||||||
val files = arrayListOf<File>()
|
|
||||||
var entry: ArchiveEntry?
|
|
||||||
while (zipInputStream.nextEntry.also { entry = it } != null) {
|
|
||||||
val entryName = entry!!.name
|
|
||||||
val entryFile = File(dir, entryName)
|
|
||||||
if (!entryFile.canonicalPath.startsWith(dir.canonicalPath)) {
|
|
||||||
throw SecurityException("压缩文件只能解压到指定路径")
|
|
||||||
}
|
|
||||||
if (entry!!.isDirectory) {
|
|
||||||
if (!entryFile.exists()) {
|
|
||||||
entryFile.mkdirs()
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (entryFile.parentFile?.exists() != true) {
|
|
||||||
entryFile.parentFile?.mkdirs()
|
|
||||||
}
|
|
||||||
if (filter != null && !filter.invoke(entryName)) continue
|
|
||||||
if (!entryFile.exists()) {
|
|
||||||
entryFile.createNewFile()
|
|
||||||
entryFile.setReadable(true)
|
|
||||||
entryFile.setExecutable(true)
|
|
||||||
}
|
|
||||||
FileOutputStream(entryFile).use {
|
|
||||||
zipInputStream.copyTo(it)
|
|
||||||
files.add(entryFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return files
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Throws(SecurityException::class)
|
@Throws(SecurityException::class)
|
||||||
private fun unZipToPath(
|
private fun unZipToPath(
|
||||||
@@ -325,34 +270,9 @@ object ZipUtils {
|
|||||||
inputStream: InputStream,
|
inputStream: InputStream,
|
||||||
filter: ((String) -> Boolean)? = null
|
filter: ((String) -> Boolean)? = null
|
||||||
): List<String> {
|
): List<String> {
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
return ZipInputStream(inputStream).use {
|
||||||
ZipArchiveInputStream(inputStream).use {
|
|
||||||
getFilesName(it, filter)
|
getFilesName(it, filter)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
ZipInputStream(inputStream).use {
|
|
||||||
getFilesName(it, filter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.N)
|
|
||||||
@Throws(SecurityException::class)
|
|
||||||
private fun getFilesName(
|
|
||||||
zipInputStream: ZipArchiveInputStream,
|
|
||||||
filter: ((String) -> Boolean)? = null
|
|
||||||
): List<String> {
|
|
||||||
val fileNames = mutableListOf<String>()
|
|
||||||
var entry: ArchiveEntry?
|
|
||||||
while (zipInputStream.nextEntry.also { entry = it } != null) {
|
|
||||||
if (entry!!.isDirectory) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val fileName = entry!!.name
|
|
||||||
if (filter != null && filter.invoke(fileName))
|
|
||||||
fileNames.add(fileName)
|
|
||||||
}
|
|
||||||
return fileNames
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(SecurityException::class)
|
@Throws(SecurityException::class)
|
||||||
|
|||||||
Reference in New Issue
Block a user