ag2s20150909 3 ani în urmă
părinte
comite
06e616ac1b

+ 174 - 13
app/src/main/java/io/legado/app/help/JsExtensions.kt

@@ -4,6 +4,8 @@ import android.net.Uri
 import androidx.annotation.Keep
 import cn.hutool.core.codec.Base64
 import cn.hutool.core.util.HexUtil
+import com.github.junrar.Archive
+import com.github.junrar.rarfile.FileHeader
 import io.legado.app.constant.AppConst
 import io.legado.app.constant.AppConst.dateFormat
 import io.legado.app.constant.AppLog
@@ -21,6 +23,10 @@ import io.legado.app.utils.*
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.async
 import kotlinx.coroutines.runBlocking
+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.Jsoup
 import splitties.init.appCtx
@@ -312,21 +318,21 @@ interface JsExtensions : JsEncodeUtils {
         }
         return response
     }
-    
+
     /* Str转ByteArray */
     fun strToBytes(str: String): ByteArray {
         return str.toByteArray(charset("UTF-8"))
     }
-    
+
     fun strToBytes(str: String, charset: String): ByteArray {
         return str.toByteArray(charset(charset))
     }
-    
+
     /* ByteArray转Str */
     fun bytesToStr(bytes: ByteArray): String {
         return String(bytes, charset("UTF-8"))
     }
-    
+
     fun bytesToStr(bytes: ByteArray, charset: String): String {
         return String(bytes, charset(charset))
     }
@@ -337,7 +343,7 @@ interface JsExtensions : JsEncodeUtils {
     fun base64Decode(str: String?): String {
         return Base64.decodeStr(str)
     }
-    
+
     fun base64Decode(str: String?, charset: String): String {
         return Base64.decodeStr(str, charset(charset))
     }
@@ -481,7 +487,7 @@ interface JsExtensions : JsEncodeUtils {
     }
 
     /**
-     * js实现压缩文件解压
+     * js实现Zip压缩文件解压
      * @param zipPath 相对路径
      * @return 相对路径
      */
@@ -497,6 +503,71 @@ interface JsExtensions : JsEncodeUtils {
         FileUtils.delete(zipFile.absolutePath)
         return unzipPath.substring(FileUtils.getCachePath().length)
     }
+    /**
+     * js实现7Zip压缩文件解压
+     * @param zipPath 相对路径
+     * @return 相对路径
+     */
+    fun un7zFile(zipPath: String): String {
+        if (zipPath.isEmpty()) return ""
+        val unzipPath = FileUtils.getPath(
+            FileUtils.createFolderIfNotExist(FileUtils.getCachePath()),
+            FileUtils.getNameExcludeExtension(zipPath)
+        )
+        val unzipFolder = File(unzipPath).createFolderReplace()
+        val zipFile = getFile(zipPath)
+        SevenZipUtils.un7zToPath(zipFile, unzipFolder)
+        FileUtils.delete(zipFile.absolutePath)
+        return unzipPath.substring(FileUtils.getCachePath().length)
+    }
+    /**
+     * js实现Rar压缩文件解压
+     * @param zipPath 相对路径
+     * @return 相对路径
+     */
+    fun unrarFile(zipPath: String): String {
+        if (zipPath.isEmpty()) return ""
+        val unzipPath = FileUtils.getPath(
+            FileUtils.createFolderIfNotExist(FileUtils.getCachePath()),
+            FileUtils.getNameExcludeExtension(zipPath)
+        )
+        val unzipFolder = File(unzipPath).createFolderReplace()
+        val zipFile = getFile(zipPath)
+        RarUtils.unRarToPath(zipFile, unzipFolder)
+        FileUtils.delete(zipFile.absolutePath)
+        return unzipPath.substring(FileUtils.getCachePath().length)
+    }
+    /**
+     * js实现压缩文件解压
+     * @param zipPath 相对路径
+     * @return 相对路径
+     */
+    fun unArchiveFile(zipPath: String): String {
+        if (zipPath.isEmpty()) return ""
+        val unzipPath = FileUtils.getPath(
+            FileUtils.createFolderIfNotExist(FileUtils.getCachePath()),
+            FileUtils.getNameExcludeExtension(zipPath)
+        )
+        val unzipFolder = File(unzipPath).createFolderReplace()
+        val zipFile = getFile(zipPath)
+        when {
+            zipPath.endsWith(".zip", ignoreCase = true) -> {
+                ZipUtils.unzipFile(zipFile, unzipFolder)
+            }
+            zipPath.endsWith(".rar", ignoreCase = true) -> {
+                RarUtils.unRarToPath(zipFile, unzipFolder)
+            }
+
+            zipPath.endsWith(".7z", ignoreCase = true) -> {
+                SevenZipUtils.un7zToPath(zipFile, unzipFolder)
+            }
+            else -> {
+               log("自动解压未识别类型${zipPath}")
+            }
+        }
+        FileUtils.delete(zipFile.absolutePath)
+        return unzipPath.substring(FileUtils.getCachePath().length)
+    }
 
     /**
      * js实现文件夹内所有文本文件读取
@@ -538,6 +609,40 @@ interface JsExtensions : JsEncodeUtils {
         return String(byteArray, Charset.forName(charsetName))
     }
 
+    /**
+     * 获取网络zip文件里面的数据
+     * @param url zip文件的链接或十六进制字符串
+     * @param path 所需获取文件在zip内的路径
+     * @return zip指定文件的数据
+     */
+    fun getRarStringContent(url: String, path: String): String {
+        val byteArray = getRarByteArrayContent(url, path) ?: return ""
+        val charsetName = EncodingDetect.getEncode(byteArray)
+        return String(byteArray, Charset.forName(charsetName))
+    }
+
+    fun getRarStringContent(url: String, path: String, charsetName: String): String {
+        val byteArray = getRarByteArrayContent(url, path) ?: return ""
+        return String(byteArray, Charset.forName(charsetName))
+    }
+
+    /**
+     * 获取网络7zip文件里面的数据
+     * @param url 7zip文件的链接或十六进制字符串
+     * @param path 所需获取文件在7zip内的路径
+     * @return zip指定文件的数据
+     */
+    fun get7zStringContent(url: String, path: String): String {
+        val byteArray = get7zByteArrayContent(url, path) ?: return ""
+        val charsetName = EncodingDetect.getEncode(byteArray)
+        return String(byteArray, Charset.forName(charsetName))
+    }
+
+    fun get7zStringContent(url: String, path: String, charsetName: String): String {
+        val byteArray = get7zByteArrayContent(url, path) ?: return ""
+        return String(byteArray, Charset.forName(charsetName))
+    }
+
     /**
      * 获取网络zip文件里面的数据
      * @param url zip文件的链接或十六进制字符串
@@ -551,19 +656,75 @@ interface JsExtensions : JsEncodeUtils {
             HexUtil.decodeHex(url)
         }
         val bos = ByteArrayOutputStream()
-        val zis = ZipInputStream(ByteArrayInputStream(bytes))
-        var entry: ZipEntry? = zis.nextEntry
-        while (entry != null) {
-            if (entry.name.equals(path)) {
-                zis.use { it.copyTo(bos) }
-                return bos.toByteArray()
+        ZipInputStream(ByteArrayInputStream(bytes)).use { zis ->
+            var entry: ZipEntry
+            while (zis.nextEntry.also { entry = it } != null) {
+                if (entry.name.equals(path)) {
+                    zis.use { it.copyTo(bos) }
+                    return bos.toByteArray()
+                }
+                entry = zis.nextEntry
             }
-            entry = zis.nextEntry
         }
+
         log("getZipContent 未发现内容")
         return null
     }
 
+    /**
+     * 获取网络Rar文件里面的数据
+     * @param url Rar文件的链接或十六进制字符串
+     * @param path 所需获取文件在Rar内的路径
+     * @return Rar指定文件的数据
+     */
+    fun getRarByteArrayContent(url: String, path: String): ByteArray? {
+        val bytes = if (url.isAbsUrl()) {
+            AnalyzeUrl(url, source = getSource()).getByteArray()
+        } else {
+            HexUtil.decodeHex(url)
+        }
+
+        val bos = ByteArrayOutputStream()
+        Archive(ByteArrayInputStream(bytes)).use { archive ->
+            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文件里面的数据
+     * @param url 7zip文件的链接或十六进制字符串
+     * @param path 所需获取文件在7zip内的路径
+     * @return 7zip指定文件的数据
+     */
+    fun get7zByteArrayContent(url: String, path: String): ByteArray? {
+        val bytes = if (url.isAbsUrl()) {
+            AnalyzeUrl(url, source = getSource()).getByteArray()
+        } else {
+            HexUtil.decodeHex(url)
+        }
+
+        val bos = ByteArrayOutputStream()
+        SevenZFile(SeekableInMemoryByteChannel(bytes)).use { sevenZFile ->
+            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
+    }
+
 
 //******************文件操作************************//
 

+ 32 - 6
app/src/main/java/io/legado/app/utils/RarUtils.kt

@@ -1,17 +1,44 @@
 package io.legado.app.utils
 
+import androidx.annotation.Keep
 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")
+
+@Keep
+@Suppress("unused","MemberVisibilityCanBePrivate")
 object RarUtils {
-    fun unRarToPath(inputStream: InputStream, path: String){
-        val archive= Archive(inputStream)
+    fun unRarToPath(inputStream: InputStream, destDir: File?) {
+        Archive(inputStream).use {
+            unRarToPath(it, destDir)
+        }
+        inputStream.close()
+    }
+    fun unRarToPath(byteArray: ByteArray, destDir: File?) {
+        Archive(ByteArrayInputStream(byteArray)).use {
+            unRarToPath(it, destDir)
+        }
+    }
+
+    fun unRarToPath(filePath:String, destDir: File?) {
+        Archive(File(filePath)).use {
+            unRarToPath(it, destDir)
+        }
+    }
+
+    fun unRarToPath(file: File, destDir: File?) {
+        Archive(file).use {
+            unRarToPath(it, destDir)
+        }
+    }
+
+    fun unRarToPath(archive: Archive, destDir: File?) {
         var entry: FileHeader
-        while (archive.nextFileHeader().also { entry=it }!=null){
-            val entryFile = File(path, entry.fileName)
+        while (archive.nextFileHeader().also { entry = it } != null) {
+            val entryFile = File(destDir, entry.fileName)
             if (entry.isDirectory) {
                 if (!entryFile.exists()) {
                     entryFile.mkdirs()
@@ -31,7 +58,6 @@ object RarUtils {
             }
 
         }
-        inputStream.close()
     }
 
 }

+ 20 - 11
app/src/main/java/io/legado/app/utils/SevenZipUtils.kt

@@ -2,6 +2,7 @@ package io.legado.app.utils
 
 import android.annotation.SuppressLint
 import android.os.ParcelFileDescriptor
+import androidx.annotation.Keep
 import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry
 import org.apache.commons.compress.archivers.sevenz.SevenZFile
 import org.apache.commons.compress.utils.SeekableInMemoryByteChannel
@@ -9,30 +10,38 @@ import java.io.File
 import java.io.FileOutputStream
 import java.io.InputStream
 import java.nio.channels.FileChannel
-@Suppress("unused")
+
+@Keep
+@Suppress("unused","MemberVisibilityCanBePrivate")
 object SevenZipUtils {
 
 
 
-    fun un7zToPath(inputStream: InputStream, path: String){
-        un7zToPath(SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())),path)
+    fun un7zToPath(inputStream: InputStream, destDir: File?){
+        un7zToPath(SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())),destDir)
+    }
+    fun un7zToPath(byteArray: ByteArray, destDir: File?){
+        un7zToPath(SevenZFile(SeekableInMemoryByteChannel(byteArray)),destDir)
     }
-    fun un7zToPath(pfd: ParcelFileDescriptor, path: String){
-        un7zToPath(SevenZFile(ParcelFileDescriptorChannel(pfd)),path)
+    fun un7zToPath(pfd: ParcelFileDescriptor, destDir: File?){
+        un7zToPath(SevenZFile(ParcelFileDescriptorChannel(pfd)),destDir)
     }
     @SuppressLint("NewApi")
-    fun un7zToPath(fileChannel: FileChannel, path: String){
-        un7zToPath(SevenZFile(fileChannel),path)
+    fun un7zToPath(fileChannel: FileChannel, destDir: File?){
+        un7zToPath(SevenZFile(fileChannel),destDir)
+    }
+    fun un7zToPath(file: File, destDir: File?){
+        un7zToPath(SevenZFile(file),destDir)
     }
-    fun un7zToPath(file: File, path: String){
-        un7zToPath(SevenZFile(file),path)
+    fun un7zToPath(filePath: String, destDir: File?){
+        un7zToPath(SevenZFile(File(filePath)),destDir)
     }
 
 
-    fun un7zToPath(sevenZFile:SevenZFile, path: String){
+    fun un7zToPath(sevenZFile:SevenZFile, destDir: File?){
         var entry: SevenZArchiveEntry
         while (sevenZFile.nextEntry.also { entry=it }!=null){
-            val entryFile = File(path, entry.name)
+            val entryFile = File(destDir, entry.name)
             if (entry.isDirectory) {
                 if (!entryFile.exists()) {
                     entryFile.mkdirs()